From 3488b88be90f9e995a0c8864cdd1fdc25036ae5c Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Wed, 25 Mar 2026 23:33:57 +0400 Subject: [PATCH 01/69] Rename OrderBook to Raindex in src/ and script/ Rename all Solidity source contracts, libraries, and scripts from OrderBook naming to Raindex naming. File renames and content updates for src/abstract/, src/concrete/, src/lib/, src/generated/, and script/. Co-Authored-By: Claude Opus 4.6 (1M context) --- script/BuildAuthoringMeta.sol | 6 +- script/BuildPointers.sol | 48 +++++------ script/Deploy.sol | 82 +++++++++---------- ...V6ArbCommon.sol => RaindexV6ArbCommon.sol} | 12 +-- ...erTaker.sol => RaindexV6ArbOrderTaker.sol} | 26 +++--- ...askGated.sol => RaindexV6ArbTaskGated.sol} | 10 +-- ...orrower.sol => RaindexV6FlashBorrower.sol} | 44 +++++----- ...ashLender.sol => RaindexV6FlashLender.sol} | 18 ++-- ... => GenericPoolRaindexV6ArbOrderTaker.sol} | 8 +- ... => GenericPoolRaindexV6FlashBorrower.sol} | 10 +-- ... RouteProcessorRaindexV6ArbOrderTaker.sol} | 12 +-- .../ob/{OrderBookV6.sol => RaindexV6.sol} | 22 ++--- ...V6SubParser.sol => RaindexV6SubParser.sol} | 74 ++++++++--------- ...icPoolRaindexV6ArbOrderTaker.pointers.sol} | 0 ...icPoolRaindexV6FlashBorrower.pointers.sol} | 0 ...V6.pointers.sol => RaindexV6.pointers.sol} | 0 ...rs.sol => RaindexV6SubParser.pointers.sol} | 0 ...cessorRaindexV6ArbOrderTaker.pointers.sol} | 0 src/lib/{LibOrderBook.sol => LibRaindex.sol} | 4 +- ...{LibOrderBookArb.sol => LibRaindexArb.sol} | 8 +- ...kSubParser.sol => LibRaindexSubParser.sol} | 18 ++-- ...derBookDeploy.sol => LibRaindexDeploy.sol} | 52 ++++++------ 22 files changed, 227 insertions(+), 227 deletions(-) rename src/abstract/{OrderBookV6ArbCommon.sol => RaindexV6ArbCommon.sol} (73%) rename src/abstract/{OrderBookV6ArbOrderTaker.sol => RaindexV6ArbOrderTaker.sol} (75%) rename src/abstract/{OrderBookV6ArbTaskGated.sol => RaindexV6ArbTaskGated.sol} (78%) rename src/abstract/{OrderBookV6FlashBorrower.sol => RaindexV6FlashBorrower.sol} (82%) rename src/abstract/{OrderBookV6FlashLender.sol => RaindexV6FlashLender.sol} (85%) rename src/concrete/arb/{GenericPoolOrderBookV6ArbOrderTaker.sol => GenericPoolRaindexV6ArbOrderTaker.sol} (82%) rename src/concrete/arb/{GenericPoolOrderBookV6FlashBorrower.sol => GenericPoolRaindexV6FlashBorrower.sol} (81%) rename src/concrete/arb/{RouteProcessorOrderBookV6ArbOrderTaker.sol => RouteProcessorRaindexV6ArbOrderTaker.sol} (84%) rename src/concrete/ob/{OrderBookV6.sol => RaindexV6.sol} (98%) rename src/concrete/parser/{OrderBookV6SubParser.sol => RaindexV6SubParser.sol} (85%) rename src/generated/{GenericPoolOrderBookV6ArbOrderTaker.pointers.sol => GenericPoolRaindexV6ArbOrderTaker.pointers.sol} (100%) rename src/generated/{GenericPoolOrderBookV6FlashBorrower.pointers.sol => GenericPoolRaindexV6FlashBorrower.pointers.sol} (100%) rename src/generated/{OrderBookV6.pointers.sol => RaindexV6.pointers.sol} (100%) rename src/generated/{OrderBookV6SubParser.pointers.sol => RaindexV6SubParser.pointers.sol} (100%) rename src/generated/{RouteProcessorOrderBookV6ArbOrderTaker.pointers.sol => RouteProcessorRaindexV6ArbOrderTaker.pointers.sol} (100%) rename src/lib/{LibOrderBook.sol => LibRaindex.sol} (98%) rename src/lib/{LibOrderBookArb.sol => LibRaindexArb.sol} (95%) rename src/lib/{LibOrderBookSubParser.sol => LibRaindexSubParser.sol} (98%) rename src/lib/deploy/{LibOrderBookDeploy.sol => LibRaindexDeploy.sol} (61%) diff --git a/script/BuildAuthoringMeta.sol b/script/BuildAuthoringMeta.sol index 3db5476c8d..392aab23f4 100644 --- a/script/BuildAuthoringMeta.sol +++ b/script/BuildAuthoringMeta.sol @@ -3,13 +3,13 @@ pragma solidity =0.8.25; import {Script} from "forge-std/Script.sol"; -import {LibOrderBookSubParser} from "../src/lib/LibOrderBookSubParser.sol"; +import {LibRaindexSubParser} from "../src/lib/LibRaindexSubParser.sol"; -/// @title OrderBook subparser Authoring Meta +/// @title Raindex subparser Authoring Meta /// @notice A script that writes the raw authoring meta out to file so it can be /// wrapped in CBOR and emitted on metaboard. contract BuildAuthoringMeta is Script { function run() external { - vm.writeFileBinary("meta/OrderBookV6SubParserAuthoringMeta.rain.meta", LibOrderBookSubParser.authoringMetaV2()); + vm.writeFileBinary("meta/RaindexV6SubParserAuthoringMeta.rain.meta", LibRaindexSubParser.authoringMetaV2()); } } diff --git a/script/BuildPointers.sol b/script/BuildPointers.sol index c3221c153c..b6ca61b522 100644 --- a/script/BuildPointers.sol +++ b/script/BuildPointers.sol @@ -5,15 +5,15 @@ pragma solidity =0.8.25; import {Script} from "forge-std/Script.sol"; import {LibCodeGen} from "rain.sol.codegen/lib/LibCodeGen.sol"; import {LibFs} from "rain.sol.codegen/lib/LibFs.sol"; -import {OrderBookV6} from "../src/concrete/ob/OrderBookV6.sol"; -import {OrderBookV6SubParser} from "../src/concrete/parser/OrderBookV6SubParser.sol"; -import {LibOrderBookSubParser, EXTERN_PARSE_META_BUILD_DEPTH} from "../src/lib/LibOrderBookSubParser.sol"; +import {RaindexV6} from "../src/concrete/ob/RaindexV6.sol"; +import {RaindexV6SubParser} from "../src/concrete/parser/RaindexV6SubParser.sol"; +import {LibRaindexSubParser, EXTERN_PARSE_META_BUILD_DEPTH} from "../src/lib/LibRaindexSubParser.sol"; import {LibGenParseMeta} from "rain.interpreter.interface/lib/codegen/LibGenParseMeta.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; import {ROUTE_PROCESSOR_4_CREATION_CODE} from "../src/lib/deploy/LibRouteProcessor4CreationCode.sol"; -import {GenericPoolOrderBookV6ArbOrderTaker} from "../src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol"; -import {RouteProcessorOrderBookV6ArbOrderTaker} from "../src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol"; -import {GenericPoolOrderBookV6FlashBorrower} from "../src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol"; +import {GenericPoolRaindexV6ArbOrderTaker} from "../src/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.sol"; +import {RouteProcessorRaindexV6ArbOrderTaker} from "../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; +import {GenericPoolRaindexV6FlashBorrower} from "../src/concrete/arb/GenericPoolRaindexV6FlashBorrower.sol"; contract BuildPointers is Script { function addressConstantString(address addr) internal pure returns (string memory) { @@ -27,20 +27,20 @@ contract BuildPointers is Script { ); } - function buildOrderBookV6Pointers() internal { - address deployed = LibRainDeploy.deployZoltu(type(OrderBookV6).creationCode); + function buildRaindexV6Pointers() internal { + address deployed = LibRainDeploy.deployZoltu(type(RaindexV6).creationCode); LibFs.buildFileForContract( vm, deployed, - "OrderBookV6", + "RaindexV6", string.concat( addressConstantString(deployed), LibCodeGen.bytesConstantString( vm, "/// @dev The creation bytecode of the contract.", "CREATION_CODE", - type(OrderBookV6).creationCode + type(RaindexV6).creationCode ), LibCodeGen.bytesConstantString( vm, "/// @dev The runtime bytecode of the contract.", "RUNTIME_CODE", deployed.code @@ -49,11 +49,11 @@ contract BuildPointers is Script { ); } - function buildOrderBookSubParserPointers() internal { - address deployed = LibRainDeploy.deployZoltu(type(OrderBookV6SubParser).creationCode); - OrderBookV6SubParser subParser = OrderBookV6SubParser(deployed); + function buildRaindexSubParserPointers() internal { + address deployed = LibRainDeploy.deployZoltu(type(RaindexV6SubParser).creationCode); + RaindexV6SubParser subParser = RaindexV6SubParser(deployed); - string memory name = "OrderBookV6SubParser"; + string memory name = "RaindexV6SubParser"; LibFs.buildFileForContract( vm, @@ -66,7 +66,7 @@ contract BuildPointers is Script { vm, "/// @dev The creation bytecode of the contract.", "CREATION_CODE", - type(OrderBookV6SubParser).creationCode + type(RaindexV6SubParser).creationCode ), LibCodeGen.bytesConstantString( vm, "/// @dev The runtime bytecode of the contract.", "RUNTIME_CODE", deployed.code @@ -75,7 +75,7 @@ contract BuildPointers is Script { string.concat( LibCodeGen.describedByMetaHashConstantString(vm, name), LibGenParseMeta.parseMetaConstantString( - vm, LibOrderBookSubParser.authoringMetaV2(), EXTERN_PARSE_META_BUILD_DEPTH + vm, LibRaindexSubParser.authoringMetaV2(), EXTERN_PARSE_META_BUILD_DEPTH ), LibCodeGen.subParserWordParsersConstantString(vm, subParser), LibCodeGen.operandHandlerFunctionPointersConstantString(vm, subParser), @@ -102,12 +102,12 @@ contract BuildPointers is Script { } function buildGenericPoolArbOrderTakerPointers() internal { - address deployed = LibRainDeploy.deployZoltu(type(GenericPoolOrderBookV6ArbOrderTaker).creationCode); + address deployed = LibRainDeploy.deployZoltu(type(GenericPoolRaindexV6ArbOrderTaker).creationCode); LibFs.buildFileForContract( vm, deployed, - "GenericPoolOrderBookV6ArbOrderTaker", + "GenericPoolRaindexV6ArbOrderTaker", string.concat( addressConstantString(deployed), LibCodeGen.bytesConstantString( @@ -118,12 +118,12 @@ contract BuildPointers is Script { } function buildRouteProcessorArbOrderTakerPointers() internal { - address deployed = LibRainDeploy.deployZoltu(type(RouteProcessorOrderBookV6ArbOrderTaker).creationCode); + address deployed = LibRainDeploy.deployZoltu(type(RouteProcessorRaindexV6ArbOrderTaker).creationCode); LibFs.buildFileForContract( vm, deployed, - "RouteProcessorOrderBookV6ArbOrderTaker", + "RouteProcessorRaindexV6ArbOrderTaker", string.concat( addressConstantString(deployed), LibCodeGen.bytesConstantString( @@ -134,12 +134,12 @@ contract BuildPointers is Script { } function buildGenericPoolFlashBorrowerPointers() internal { - address deployed = LibRainDeploy.deployZoltu(type(GenericPoolOrderBookV6FlashBorrower).creationCode); + address deployed = LibRainDeploy.deployZoltu(type(GenericPoolRaindexV6FlashBorrower).creationCode); LibFs.buildFileForContract( vm, deployed, - "GenericPoolOrderBookV6FlashBorrower", + "GenericPoolRaindexV6FlashBorrower", string.concat( addressConstantString(deployed), LibCodeGen.bytesConstantString( @@ -152,8 +152,8 @@ contract BuildPointers is Script { function run() external { LibRainDeploy.etchZoltuFactory(vm); - buildOrderBookV6Pointers(); - buildOrderBookSubParserPointers(); + buildRaindexV6Pointers(); + buildRaindexSubParserPointers(); buildRouteProcessor4Pointers(); buildGenericPoolArbOrderTakerPointers(); buildRouteProcessorArbOrderTakerPointers(); diff --git a/script/Deploy.sol b/script/Deploy.sol index dc36d517c4..7de3fc4b5d 100644 --- a/script/Deploy.sol +++ b/script/Deploy.sol @@ -3,36 +3,36 @@ pragma solidity =0.8.25; import {Script, console2} from "forge-std/Script.sol"; -import {OrderBookV6SubParser} from "../src/concrete/parser/OrderBookV6SubParser.sol"; +import {RaindexV6SubParser} from "../src/concrete/parser/RaindexV6SubParser.sol"; import {IMetaBoardV1_2} from "rain.metadata/interface/unstable/IMetaBoardV1_2.sol"; import {LibDescribedByMeta} from "rain.metadata/lib/LibDescribedByMeta.sol"; import {LibMetaBoardDeploy} from "rain.metadata/lib/deploy/LibMetaBoardDeploy.sol"; import {LibDecimalFloatDeploy} from "rain.math.float/lib/deploy/LibDecimalFloatDeploy.sol"; import {LibTOFUTokenDecimals} from "rain.tofu.erc20-decimals/lib/LibTOFUTokenDecimals.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; -import {LibOrderBookDeploy} from "../src/lib/deploy/LibOrderBookDeploy.sol"; -import {CREATION_CODE as ORDERBOOK_CREATION_CODE} from "../src/generated/OrderBookV6.pointers.sol"; -import {CREATION_CODE as SUB_PARSER_CREATION_CODE} from "../src/generated/OrderBookV6SubParser.pointers.sol"; +import {LibRaindexDeploy} from "../src/lib/deploy/LibRaindexDeploy.sol"; +import {CREATION_CODE as RAINDEX_CREATION_CODE} from "../src/generated/RaindexV6.pointers.sol"; +import {CREATION_CODE as SUB_PARSER_CREATION_CODE} from "../src/generated/RaindexV6SubParser.pointers.sol"; import {ROUTE_PROCESSOR_4_CREATION_CODE} from "../src/lib/deploy/LibRouteProcessor4CreationCode.sol"; -import {GenericPoolOrderBookV6ArbOrderTaker} from "../src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol"; -import {RouteProcessorOrderBookV6ArbOrderTaker} from "../src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol"; -import {GenericPoolOrderBookV6FlashBorrower} from "../src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol"; +import {GenericPoolRaindexV6ArbOrderTaker} from "../src/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.sol"; +import {RouteProcessorRaindexV6ArbOrderTaker} from "../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; +import {GenericPoolRaindexV6FlashBorrower} from "../src/concrete/arb/GenericPoolRaindexV6FlashBorrower.sol"; -/// @dev Deploy only the OrderBookV6 (raindex) contract. +/// @dev Deploy only the RaindexV6 (raindex) contract. bytes32 constant DEPLOYMENT_SUITE_RAINDEX = keccak256("raindex"); -/// @dev Deploy only the OrderBookV6SubParser contract. +/// @dev Deploy only the RaindexV6SubParser contract. bytes32 constant DEPLOYMENT_SUITE_SUBPARSER = keccak256("subparser"); /// @dev Deploy only the RouteProcessor4 contract. bytes32 constant DEPLOYMENT_SUITE_ROUTE_PROCESSOR = keccak256("route-processor"); -/// @dev Deploy only GenericPoolOrderBookV6ArbOrderTaker. +/// @dev Deploy only GenericPoolRaindexV6ArbOrderTaker. bytes32 constant DEPLOYMENT_SUITE_ARB_GENERIC_POOL_ORDER_TAKER = keccak256("arb-generic-pool-order-taker"); -/// @dev Deploy only RouteProcessorOrderBookV6ArbOrderTaker. +/// @dev Deploy only RouteProcessorRaindexV6ArbOrderTaker. bytes32 constant DEPLOYMENT_SUITE_ARB_ROUTE_PROCESSOR_ORDER_TAKER = keccak256("arb-route-processor-order-taker"); -/// @dev Deploy only GenericPoolOrderBookV6FlashBorrower. +/// @dev Deploy only GenericPoolRaindexV6FlashBorrower. bytes32 constant DEPLOYMENT_SUITE_ARB_GENERIC_POOL_FLASH_BORROWER = keccak256("arb-generic-pool-flash-borrower"); /// @title Deploy -/// @notice Foundry script that deploys orderbook contracts. Controlled by the +/// @notice Foundry script that deploys raindex contracts. Controlled by the /// `DEPLOYMENT_SUITE` env var to select which subset to deploy, and /// `DEPLOYMENT_KEY` for the deployer private key. contract Deploy is Script { @@ -48,7 +48,7 @@ contract Deploy is Script { bytes32 suite = keccak256(bytes(suiteString)); if (suite == DEPLOYMENT_SUITE_RAINDEX) { - console2.log("Deploying OrderBookV6..."); + console2.log("Deploying RaindexV6..."); address[] memory deps = new address[](3); deps[0] = LibDecimalFloatDeploy.ZOLTU_DEPLOYED_LOG_TABLES_ADDRESS; deps[1] = address(LibTOFUTokenDecimals.TOFU_DECIMALS_DEPLOYMENT); @@ -57,15 +57,15 @@ contract Deploy is Script { vm, LibRainDeploy.supportedNetworks(), deployerPrivateKey, - ORDERBOOK_CREATION_CODE, - "src/concrete/ob/OrderBookV6.sol:OrderBookV6", - LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS, - LibOrderBookDeploy.ORDERBOOK_DEPLOYED_CODEHASH, + RAINDEX_CREATION_CODE, + "src/concrete/ob/RaindexV6.sol:RaindexV6", + LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, + LibRaindexDeploy.RAINDEX_DEPLOYED_CODEHASH, deps, sDepCodeHashes ); } else if (suite == DEPLOYMENT_SUITE_SUBPARSER) { - console2.log("Deploying OrderBookV6SubParser..."); + console2.log("Deploying RaindexV6SubParser..."); address[] memory deps = new address[](3); deps[0] = LibDecimalFloatDeploy.ZOLTU_DEPLOYED_LOG_TABLES_ADDRESS; deps[1] = address(LibTOFUTokenDecimals.TOFU_DECIMALS_DEPLOYMENT); @@ -75,18 +75,18 @@ contract Deploy is Script { LibRainDeploy.supportedNetworks(), deployerPrivateKey, SUB_PARSER_CREATION_CODE, - "src/concrete/parser/OrderBookV6SubParser.sol:OrderBookV6SubParser", - LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS, - LibOrderBookDeploy.SUB_PARSER_DEPLOYED_CODEHASH, + "src/concrete/parser/RaindexV6SubParser.sol:RaindexV6SubParser", + LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS, + LibRaindexDeploy.SUB_PARSER_DEPLOYED_CODEHASH, deps, sDepCodeHashes ); IMetaBoardV1_2 metaboard = IMetaBoardV1_2(LibMetaBoardDeploy.METABOARD_DEPLOYED_ADDRESS); vm.startBroadcast(deployerPrivateKey); - bytes memory subParserDescribedByMeta = vm.readFileBinary("meta/OrderBookV6SubParser.rain.meta"); + bytes memory subParserDescribedByMeta = vm.readFileBinary("meta/RaindexV6SubParser.rain.meta"); LibDescribedByMeta.emitForDescribedAddress( metaboard, - OrderBookV6SubParser(LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS), + RaindexV6SubParser(LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS), subParserDescribedByMeta ); vm.stopBroadcast(); @@ -99,50 +99,50 @@ contract Deploy is Script { deployerPrivateKey, ROUTE_PROCESSOR_4_CREATION_CODE, "RouteProcessor4", - LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS, - LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_CODEHASH, + LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS, + LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_CODEHASH, deps, sDepCodeHashes ); } else if (suite == DEPLOYMENT_SUITE_ARB_GENERIC_POOL_ORDER_TAKER) { - console2.log("Deploying GenericPoolOrderBookV6ArbOrderTaker..."); + console2.log("Deploying GenericPoolRaindexV6ArbOrderTaker..."); address[] memory deps = new address[](0); LibRainDeploy.deployAndBroadcast( vm, LibRainDeploy.supportedNetworks(), deployerPrivateKey, - type(GenericPoolOrderBookV6ArbOrderTaker).creationCode, - "src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol:GenericPoolOrderBookV6ArbOrderTaker", - LibOrderBookDeploy.GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_ADDRESS, - LibOrderBookDeploy.GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_CODEHASH, + type(GenericPoolRaindexV6ArbOrderTaker).creationCode, + "src/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.sol:GenericPoolRaindexV6ArbOrderTaker", + LibRaindexDeploy.GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_ADDRESS, + LibRaindexDeploy.GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_CODEHASH, deps, sDepCodeHashes ); } else if (suite == DEPLOYMENT_SUITE_ARB_ROUTE_PROCESSOR_ORDER_TAKER) { - console2.log("Deploying RouteProcessorOrderBookV6ArbOrderTaker..."); + console2.log("Deploying RouteProcessorRaindexV6ArbOrderTaker..."); address[] memory deps = new address[](0); LibRainDeploy.deployAndBroadcast( vm, LibRainDeploy.supportedNetworks(), deployerPrivateKey, - type(RouteProcessorOrderBookV6ArbOrderTaker).creationCode, - "src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol:RouteProcessorOrderBookV6ArbOrderTaker", - LibOrderBookDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_ADDRESS, - LibOrderBookDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_CODEHASH, + type(RouteProcessorRaindexV6ArbOrderTaker).creationCode, + "src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol:RouteProcessorRaindexV6ArbOrderTaker", + LibRaindexDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_ADDRESS, + LibRaindexDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_CODEHASH, deps, sDepCodeHashes ); } else if (suite == DEPLOYMENT_SUITE_ARB_GENERIC_POOL_FLASH_BORROWER) { - console2.log("Deploying GenericPoolOrderBookV6FlashBorrower..."); + console2.log("Deploying GenericPoolRaindexV6FlashBorrower..."); address[] memory deps = new address[](0); LibRainDeploy.deployAndBroadcast( vm, LibRainDeploy.supportedNetworks(), deployerPrivateKey, - type(GenericPoolOrderBookV6FlashBorrower).creationCode, - "src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol:GenericPoolOrderBookV6FlashBorrower", - LibOrderBookDeploy.GENERIC_POOL_FLASH_BORROWER_DEPLOYED_ADDRESS, - LibOrderBookDeploy.GENERIC_POOL_FLASH_BORROWER_DEPLOYED_CODEHASH, + type(GenericPoolRaindexV6FlashBorrower).creationCode, + "src/concrete/arb/GenericPoolRaindexV6FlashBorrower.sol:GenericPoolRaindexV6FlashBorrower", + LibRaindexDeploy.GENERIC_POOL_FLASH_BORROWER_DEPLOYED_ADDRESS, + LibRaindexDeploy.GENERIC_POOL_FLASH_BORROWER_DEPLOYED_CODEHASH, deps, sDepCodeHashes ); diff --git a/src/abstract/OrderBookV6ArbCommon.sol b/src/abstract/RaindexV6ArbCommon.sol similarity index 73% rename from src/abstract/OrderBookV6ArbCommon.sol rename to src/abstract/RaindexV6ArbCommon.sol index e3f893699e..4c801b28e8 100644 --- a/src/abstract/OrderBookV6ArbCommon.sol +++ b/src/abstract/RaindexV6ArbCommon.sol @@ -5,26 +5,26 @@ pragma solidity ^0.8.19; import {TaskV2} from "rain.raindex.interface/interface/IRaindexV6.sol"; /// @param task The task to run as post for each arb. -struct OrderBookV6ArbConfig { +struct RaindexV6ArbConfig { TaskV2 task; } /// Thrown when the task does not match the expected hash. error WrongTask(); -/// @title OrderBookV6ArbCommon -/// @notice Common base for arb contracts that interact with `OrderBook`. +/// @title RaindexV6ArbCommon +/// @notice Common base for arb contracts that interact with `Raindex`. /// Provides a `_beforeArb` hook that is called at the start of every arb /// operation. The base implementation is a no-op; task-gated variants /// override it to validate the task hash. -abstract contract OrderBookV6ArbCommon { +abstract contract RaindexV6ArbCommon { /// @notice Emitted on construction with the full config. /// @param sender The deployer address. /// @param config The arb config used to construct this contract. - event Construct(address sender, OrderBookV6ArbConfig config); + event Construct(address sender, RaindexV6ArbConfig config); /// @dev Hook called at the start of every arb. Base implementation is a - /// no-op. Overridden by `OrderBookV6ArbTaskGated` to validate the task + /// no-op. Overridden by `RaindexV6ArbTaskGated` to validate the task /// hash. function _beforeArb(TaskV2 memory task) internal virtual {} } diff --git a/src/abstract/OrderBookV6ArbOrderTaker.sol b/src/abstract/RaindexV6ArbOrderTaker.sol similarity index 75% rename from src/abstract/OrderBookV6ArbOrderTaker.sol rename to src/abstract/RaindexV6ArbOrderTaker.sol index 7ace0ae632..691ed97cdb 100644 --- a/src/abstract/OrderBookV6ArbOrderTaker.sol +++ b/src/abstract/RaindexV6ArbOrderTaker.sol @@ -8,21 +8,21 @@ import {IERC20, SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/ut import {IRaindexV6} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {IRaindexV6ArbOrderTaker, TaskV2} from "rain.raindex.interface/interface/IRaindexV6ArbOrderTaker.sol"; import {TakeOrdersConfigV5, Float} from "rain.raindex.interface/interface/IRaindexV6.sol"; -import {OrderBookV6ArbCommon} from "./OrderBookV6ArbCommon.sol"; -import {LibOrderBookArb} from "../lib/LibOrderBookArb.sol"; +import {RaindexV6ArbCommon} from "./RaindexV6ArbCommon.sol"; +import {LibRaindexArb} from "../lib/LibRaindexArb.sol"; import {IRaindexV6OrderTaker} from "rain.raindex.interface/interface/IRaindexV6OrderTaker.sol"; import {LibTOFUTokenDecimals} from "rain.tofu.erc20-decimals/lib/LibTOFUTokenDecimals.sol"; -/// @title OrderBookV6ArbOrderTaker -/// @notice Arb contract that takes orders directly from an `OrderBook` without +/// @title RaindexV6ArbOrderTaker +/// @notice Arb contract that takes orders directly from a `Raindex` without /// flash loans. Inheritors implement the strategy for sourcing the input token /// (e.g. routing through a DEX). -abstract contract OrderBookV6ArbOrderTaker is +abstract contract RaindexV6ArbOrderTaker is IRaindexV6OrderTaker, IRaindexV6ArbOrderTaker, ReentrancyGuard, ERC165, - OrderBookV6ArbCommon + RaindexV6ArbCommon { using SafeERC20 for IERC20; @@ -35,13 +35,13 @@ abstract contract OrderBookV6ArbOrderTaker is } /// @inheritdoc IRaindexV6ArbOrderTaker - function arb5(IRaindexV6 orderBook, TakeOrdersConfigV5 calldata takeOrders, TaskV2 calldata task) + function arb5(IRaindexV6 raindex, TakeOrdersConfigV5 calldata takeOrders, TaskV2 calldata task) external payable nonReentrant { _beforeArb(task); - // Mimic what OB would do anyway if called with zero orders. + // Mimic what Raindex would do anyway if called with zero orders. if (takeOrders.orders.length == 0) { revert IRaindexV6.NoOrders(); } @@ -49,12 +49,12 @@ abstract contract OrderBookV6ArbOrderTaker is address ordersInputToken = takeOrders.orders[0].order.validInputs[takeOrders.orders[0].inputIOIndex].token; address ordersOutputToken = takeOrders.orders[0].order.validOutputs[takeOrders.orders[0].outputIOIndex].token; - IERC20(ordersInputToken).forceApprove(address(orderBook), type(uint256).max); + IERC20(ordersInputToken).forceApprove(address(raindex), type(uint256).max); //slither-disable-next-line unused-return - orderBook.takeOrders4(takeOrders); - IERC20(ordersInputToken).forceApprove(address(orderBook), 0); + raindex.takeOrders4(takeOrders); + IERC20(ordersInputToken).forceApprove(address(raindex), 0); - LibOrderBookArb.finalizeArb( + LibRaindexArb.finalizeArb( task, ordersInputToken, LibTOFUTokenDecimals.safeDecimalsForToken(ordersInputToken), @@ -65,7 +65,7 @@ abstract contract OrderBookV6ArbOrderTaker is /// @inheritdoc IRaindexV6OrderTaker /// @dev Empty no-op. The contract holds no value between operations and the - /// caller chooses which orderbook to interact with, so there is nothing to + /// caller chooses which raindex to interact with, so there is nothing to /// protect via `msg.sender` validation here. function onTakeOrders2(address, address, Float, Float, bytes calldata) public virtual override {} } diff --git a/src/abstract/OrderBookV6ArbTaskGated.sol b/src/abstract/RaindexV6ArbTaskGated.sol similarity index 78% rename from src/abstract/OrderBookV6ArbTaskGated.sol rename to src/abstract/RaindexV6ArbTaskGated.sol index c94c6bd4e9..c1f4d9a4b2 100644 --- a/src/abstract/OrderBookV6ArbTaskGated.sol +++ b/src/abstract/RaindexV6ArbTaskGated.sol @@ -2,19 +2,19 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.19; -import {OrderBookV6ArbCommon, OrderBookV6ArbConfig, WrongTask} from "./OrderBookV6ArbCommon.sol"; +import {RaindexV6ArbCommon, RaindexV6ArbConfig, WrongTask} from "./RaindexV6ArbCommon.sol"; import {TaskV2} from "rain.raindex.interface/interface/IRaindexV6.sol"; -/// @title OrderBookV6ArbTaskGated +/// @title RaindexV6ArbTaskGated /// @notice Mixin that adds task-hash gating to arb contracts. Stores a task /// hash at construction time. Concrete task-gated contracts override -/// `_beforeArb` from `OrderBookV6ArbCommon` to call `_checkTaskHash`. -abstract contract OrderBookV6ArbTaskGated is OrderBookV6ArbCommon { +/// `_beforeArb` from `RaindexV6ArbCommon` to call `_checkTaskHash`. +abstract contract RaindexV6ArbTaskGated is RaindexV6ArbCommon { /// @notice Hash of the configured task, or `bytes32(0)` if no task was set. bytes32 public immutable iTaskHash = 0; /// @param config The arb config for this contract. - constructor(OrderBookV6ArbConfig memory config) { + constructor(RaindexV6ArbConfig memory config) { emit Construct(msg.sender, config); if (config.task.evaluable.bytecode.length != 0) { diff --git a/src/abstract/OrderBookV6FlashBorrower.sol b/src/abstract/RaindexV6FlashBorrower.sol similarity index 82% rename from src/abstract/OrderBookV6FlashBorrower.sol rename to src/abstract/RaindexV6FlashBorrower.sol index 5b917ed088..6c1f95c8a0 100644 --- a/src/abstract/OrderBookV6FlashBorrower.sol +++ b/src/abstract/RaindexV6FlashBorrower.sol @@ -9,9 +9,9 @@ import {ReentrancyGuard} from "openzeppelin-contracts/contracts/utils/Reentrancy import {ON_FLASH_LOAN_CALLBACK_SUCCESS} from "rain.raindex.interface/interface/ierc3156/IERC3156FlashBorrower.sol"; import {IRaindexV6, TakeOrdersConfigV5, TaskV2} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {IERC3156FlashBorrower} from "rain.raindex.interface/interface/ierc3156/IERC3156FlashBorrower.sol"; -import {OrderBookV6ArbCommon} from "./OrderBookV6ArbCommon.sol"; -import {LibOrderBookArb} from "../lib/LibOrderBookArb.sol"; -import {LibOrderBookDeploy} from "../lib/deploy/LibOrderBookDeploy.sol"; +import {RaindexV6ArbCommon} from "./RaindexV6ArbCommon.sol"; +import {LibRaindexArb} from "../lib/LibRaindexArb.sol"; +import {LibRaindexDeploy} from "../lib/deploy/LibRaindexDeploy.sol"; import {LibTOFUTokenDecimals} from "rain.tofu.erc20-decimals/lib/LibTOFUTokenDecimals.sol"; import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; @@ -20,17 +20,17 @@ import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; error BadInitiator(address badInitiator); /// Thrown when onFlashLoan is called by an address other than the deterministic -/// orderbook deployment. Prevents malicious contracts from invoking the callback. +/// raindex deployment. Prevents malicious contracts from invoking the callback. /// @param badLender The untrusted caller of onFlashLoan. error BadLender(address badLender); /// Thrown when the flash loan fails somehow. error FlashLoanFailed(); -/// @title OrderBookV6FlashBorrower +/// @title RaindexV6FlashBorrower /// @notice Abstract contract that liq-source specialized contracts can inherit /// to provide flash loan based arbitrage against external liquidity sources to -/// fill orderbook orders. +/// fill raindex orders. /// /// For example consider a simple order: /// @@ -41,9 +41,9 @@ error FlashLoanFailed(); /// /// Assume external liq is offering 102 DAI per USDT so it exceeds the IO ratio /// but the order itself has no way to interact with the external contract. -/// The `OrderBookFlashBorrower` can: +/// The `RaindexFlashBorrower` can: /// -/// - Flash loan 100 USDT from `Orderbook` +/// - Flash loan 100 USDT from `Raindex` /// - Sell the 100 USDT for 102 DAI on external liq /// - Take the order, giving 101 DAI and paying down 100 USDT loan /// - Keep 1 DAI profit @@ -57,7 +57,7 @@ error FlashLoanFailed(); /// - The arb operator wants to attempt to prevent front running by other bots. /// - The arb operator may prefer a dedicated instance of the contract to make /// it easier to track profits, etc. -abstract contract OrderBookV6FlashBorrower is IERC3156FlashBorrower, ReentrancyGuard, ERC165, OrderBookV6ArbCommon { +abstract contract RaindexV6FlashBorrower is IERC3156FlashBorrower, ReentrancyGuard, ERC165, RaindexV6ArbCommon { using SafeERC20 for IERC20; constructor() {} @@ -80,8 +80,8 @@ abstract contract OrderBookV6FlashBorrower is IERC3156FlashBorrower, ReentrancyG /// @inheritdoc IERC3156FlashBorrower function onFlashLoan(address initiator, address, uint256, uint256, bytes calldata data) external returns (bytes32) { - // Only the deterministic orderbook deployment may call this callback. - if (msg.sender != LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS) { + // Only the deterministic raindex deployment may call this callback. + if (msg.sender != LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS) { revert BadLender(msg.sender); } // As per reference implementation. @@ -112,28 +112,28 @@ abstract contract OrderBookV6FlashBorrower is IERC3156FlashBorrower, ReentrancyG /// If there is no task configured, anyone can call this and should expect /// to be front run on the arb for any sufficiently profitable opportunity. /// - /// A flash loan is taken from the orderbook, then inside the callback + /// A flash loan is taken from the raindex, then inside the callback /// `_exchange` converts the borrowed tokens into the tokens needed to fill /// the orders, and the orders are taken. After the flash loan repays, /// remaining assets are sent to the sender via `finalizeArb`. /// - /// @param orderBook The `OrderBook` contract to take orders from and flash + /// @param raindex The `Raindex` contract to take orders from and flash /// loan against. /// @param takeOrders As per `IRaindexV6.takeOrders4`. /// @param exchangeData Arbitrary bytes that will be passed to `_exchange` /// after the flash loan is taken. The inheriting contract is responsible /// for decoding this data and defining how it controls interactions with - /// the external liquidity. For example, `GenericPoolOrderBookV6FlashBorrower` + /// the external liquidity. For example, `GenericPoolRaindexV6FlashBorrower` /// uses this data as a literal encoded external call. /// @param task The task to evaluate after the arb completes. function arb4( - IRaindexV6 orderBook, + IRaindexV6 raindex, TakeOrdersConfigV5 calldata takeOrders, bytes calldata exchangeData, TaskV2 calldata task ) external payable nonReentrant { _beforeArb(task); - // Mimic what OB would do anyway if called with zero orders. + // Mimic what Raindex would do anyway if called with zero orders. if (takeOrders.orders.length == 0) { revert IRaindexV6.NoOrders(); } @@ -155,14 +155,14 @@ abstract contract OrderBookV6FlashBorrower is IERC3156FlashBorrower, ReentrancyG // Take the flash loan, which will in turn call `onFlashLoan`, which is // expected to process an exchange against external liq to pay back the // flash loan, cover the orders and remain in profit. - IERC20(ordersInputToken).forceApprove(address(orderBook), type(uint256).max); - IERC20(ordersOutputToken).forceApprove(address(orderBook), type(uint256).max); - if (!orderBook.flashLoan(this, ordersOutputToken, flashLoanAmount, data)) { + IERC20(ordersInputToken).forceApprove(address(raindex), type(uint256).max); + IERC20(ordersOutputToken).forceApprove(address(raindex), type(uint256).max); + if (!raindex.flashLoan(this, ordersOutputToken, flashLoanAmount, data)) { revert FlashLoanFailed(); } - IERC20(ordersOutputToken).forceApprove(address(orderBook), 0); - IERC20(ordersInputToken).forceApprove(address(orderBook), 0); + IERC20(ordersOutputToken).forceApprove(address(raindex), 0); + IERC20(ordersInputToken).forceApprove(address(raindex), 0); - LibOrderBookArb.finalizeArb(task, ordersInputToken, inputDecimals, ordersOutputToken, outputDecimals); + LibRaindexArb.finalizeArb(task, ordersInputToken, inputDecimals, ordersOutputToken, outputDecimals); } } diff --git a/src/abstract/OrderBookV6FlashLender.sol b/src/abstract/RaindexV6FlashLender.sol similarity index 85% rename from src/abstract/OrderBookV6FlashLender.sol rename to src/abstract/RaindexV6FlashLender.sol index 9625cb1a41..98d70605f5 100644 --- a/src/abstract/OrderBookV6FlashLender.sol +++ b/src/abstract/RaindexV6FlashLender.sol @@ -17,16 +17,16 @@ import {IERC3156FlashLender} from "rain.raindex.interface/interface/ierc3156/IER /// @param result The value that was returned by `onFlashLoan`. error FlashLenderCallbackFailed(bytes32 result); -/// @dev Flash fee is always 0 for orderbook as there's no entity to take -/// revenue for `Orderbook` and its more important anyway that flashloans happen +/// @dev Flash fee is always 0 for raindex as there's no entity to take +/// revenue for `Raindex` and its more important anyway that flashloans happen /// to connect external liquidity to live orders via arbitrage. uint256 constant FLASH_FEE = 0; -/// @title OrderBookV6FlashLender -/// @notice Implements `IERC3156FlashLender` for `OrderBook`. Based on the +/// @title RaindexV6FlashLender +/// @notice Implements `IERC3156FlashLender` for `Raindex`. Based on the /// reference implementation by Alberto Cuesta CaƱada found at /// https://eips.ethereum.org/EIPS/eip-3156#flash-loan-reference-implementation -abstract contract OrderBookV6FlashLender is IERC3156FlashLender, ERC165 { +abstract contract RaindexV6FlashLender is IERC3156FlashLender, ERC165 { using SafeERC20 for IERC20; /// @inheritdoc IERC165 @@ -49,9 +49,9 @@ abstract contract OrderBookV6FlashLender is IERC3156FlashLender, ERC165 { // This behaviour is copied almost verbatim from the ERC3156 spec. // Slither is complaining because this kind of logic can normally be used - // to grief the token holder. Consider if alice were to approve order book + // to grief the token holder. Consider if alice were to approve raindex // for the sake of depositing and then bob could cause alice to send - // tokens to order book without their consent. However, in this case the + // tokens to raindex without their consent. However, in this case the // flash loan spec provides two reasons that this is not a problem: // - We just sent this exact amount to the receiver as the loan, so // transferring them back with a 0 fee is net neutral. @@ -71,8 +71,8 @@ abstract contract OrderBookV6FlashLender is IERC3156FlashLender, ERC165 { return FLASH_FEE; } - /// There's no limit to the size of a flash loan from `Orderbook` other than - /// the current tokens deposited in `Orderbook`. + /// There's no limit to the size of a flash loan from `Raindex` other than + /// the current tokens deposited in `Raindex`. /// @inheritdoc IERC3156FlashLender function maxFlashLoan(address token) external view override returns (uint256) { return IERC20(token).balanceOf(address(this)); diff --git a/src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol b/src/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.sol similarity index 82% rename from src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol rename to src/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.sol index 8023bbc9c0..568bf5bace 100644 --- a/src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol +++ b/src/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.sol @@ -2,16 +2,16 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ArbOrderTaker, Float} from "../../abstract/OrderBookV6ArbOrderTaker.sol"; +import {RaindexV6ArbOrderTaker, Float} from "../../abstract/RaindexV6ArbOrderTaker.sol"; import {LibGenericPoolExchange} from "../../lib/LibGenericPoolExchange.sol"; -/// @title GenericPoolOrderBookV6ArbOrderTaker +/// @title GenericPoolRaindexV6ArbOrderTaker /// @notice Order-taker arb that swaps via an arbitrary external pool call. /// The `takeOrdersData` is decoded as `(spender, pool, encodedFunctionCall)`. -contract GenericPoolOrderBookV6ArbOrderTaker is OrderBookV6ArbOrderTaker { +contract GenericPoolRaindexV6ArbOrderTaker is RaindexV6ArbOrderTaker { constructor() {} - /// @inheritdoc OrderBookV6ArbOrderTaker + /// @inheritdoc RaindexV6ArbOrderTaker /// @dev Decodes `takeOrdersData` as `(spender, pool, encodedFunctionCall)` /// and routes the swap through the specified pool via `LibGenericPoolExchange`. function onTakeOrders2( diff --git a/src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol b/src/concrete/arb/GenericPoolRaindexV6FlashBorrower.sol similarity index 81% rename from src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol rename to src/concrete/arb/GenericPoolRaindexV6FlashBorrower.sol index e1c3e984c6..fae371a54c 100644 --- a/src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol +++ b/src/concrete/arb/GenericPoolRaindexV6FlashBorrower.sol @@ -2,12 +2,12 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6FlashBorrower, TakeOrdersConfigV5} from "../../abstract/OrderBookV6FlashBorrower.sol"; +import {RaindexV6FlashBorrower, TakeOrdersConfigV5} from "../../abstract/RaindexV6FlashBorrower.sol"; import {LibGenericPoolExchange} from "../../lib/LibGenericPoolExchange.sol"; -/// @title GenericPoolOrderBookV6FlashBorrower +/// @title GenericPoolRaindexV6FlashBorrower /// @notice Flash-loan arb that swaps via an arbitrary external pool call. -/// @dev Implements the OrderBookV6FlashBorrower interface for an external +/// @dev Implements the RaindexV6FlashBorrower interface for an external /// liquidity source that behaves vaguely like a standard AMM. The /// `exchangeData` from `arb` is decoded into a spender, pool and callData. /// The `callData` is literally the encoded function call to the pool. This @@ -16,10 +16,10 @@ import {LibGenericPoolExchange} from "../../lib/LibGenericPoolExchange.sol"; /// The `spender` is the address that will be approved to spend the input token /// on `takeOrders`, which is almost always going to be the pool itself. If you /// are unsure, simply set it to the pool address. -contract GenericPoolOrderBookV6FlashBorrower is OrderBookV6FlashBorrower { +contract GenericPoolRaindexV6FlashBorrower is RaindexV6FlashBorrower { constructor() {} - /// @inheritdoc OrderBookV6FlashBorrower + /// @inheritdoc RaindexV6FlashBorrower /// @dev Decodes `exchangeData` as `(spender, pool, encodedFunctionCall)` /// and routes the swap through the specified pool via `LibGenericPoolExchange`. function _exchange(TakeOrdersConfigV5 memory takeOrders, bytes memory exchangeData) internal virtual override { diff --git a/src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol b/src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol similarity index 84% rename from src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol rename to src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol index 915c0f6f10..012d1834fe 100644 --- a/src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol +++ b/src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol @@ -6,20 +6,20 @@ import {IRouteProcessor} from "sushixswap-v2/src/interfaces/IRouteProcessor.sol" import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; -import {OrderBookV6ArbOrderTaker, Float} from "../../abstract/OrderBookV6ArbOrderTaker.sol"; +import {RaindexV6ArbOrderTaker, Float} from "../../abstract/RaindexV6ArbOrderTaker.sol"; import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {LibOrderBookDeploy} from "../../lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "../../lib/deploy/LibRaindexDeploy.sol"; -/// @title RouteProcessorOrderBookV6ArbOrderTaker +/// @title RouteProcessorRaindexV6ArbOrderTaker /// @notice Order-taker arb that swaps via the deterministic Sushi /// RouteProcessor4 deployment. -contract RouteProcessorOrderBookV6ArbOrderTaker is OrderBookV6ArbOrderTaker { +contract RouteProcessorRaindexV6ArbOrderTaker is RaindexV6ArbOrderTaker { using SafeERC20 for IERC20; constructor() {} - /// @inheritdoc OrderBookV6ArbOrderTaker + /// @inheritdoc RaindexV6ArbOrderTaker function onTakeOrders2( address inputToken, address outputToken, @@ -28,7 +28,7 @@ contract RouteProcessorOrderBookV6ArbOrderTaker is OrderBookV6ArbOrderTaker { bytes calldata takeOrdersData ) public virtual override { super.onTakeOrders2(inputToken, outputToken, inputAmountSent, totalOutputAmount, takeOrdersData); - address routeProcessor = LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS; + address routeProcessor = LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS; IERC20(inputToken).forceApprove(routeProcessor, type(uint256).max); bytes memory route = abi.decode(takeOrdersData, (bytes)); // Input amount precision loss is acceptable as the route processor diff --git a/src/concrete/ob/OrderBookV6.sol b/src/concrete/ob/RaindexV6.sol similarity index 98% rename from src/concrete/ob/OrderBookV6.sol rename to src/concrete/ob/RaindexV6.sol index 00ec47bd32..cce56a1572 100644 --- a/src/concrete/ob/OrderBookV6.sol +++ b/src/concrete/ob/RaindexV6.sol @@ -24,7 +24,7 @@ import {IInterpreterStoreV3} from "rain.interpreter.interface/interface/IInterpr import {LibNamespace} from "rain.interpreter.interface/lib/ns/LibNamespace.sol"; import {LibMeta} from "rain.metadata/lib/LibMeta.sol"; import {IMetaV1_2} from "rain.metadata/interface/unstable/IMetaV1_2.sol"; -import {LibOrderBook} from "../../lib/LibOrderBook.sol"; +import {LibRaindex} from "../../lib/LibRaindex.sol"; import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibTOFUTokenDecimals, TOFUOutcome} from "rain.tofu.erc20-decimals/lib/LibTOFUTokenDecimals.sol"; import {ITOFUTokenDecimals} from "rain.tofu.erc20-decimals/interface/ITOFUTokenDecimals.sol"; @@ -57,8 +57,8 @@ import { CONTEXT_VAULT_IO_TOKEN, CONTEXT_VAULT_OUTPUTS_COLUMN, CONTEXT_VAULT_IO_VAULT_ID -} from "../../lib/LibOrderBook.sol"; -import {OrderBookV6FlashLender} from "../../abstract/OrderBookV6FlashLender.sol"; +} from "../../lib/LibRaindex.sol"; +import {RaindexV6FlashLender} from "../../abstract/RaindexV6FlashLender.sol"; import {LibBytes32Array} from "rain.solmem/lib/LibBytes32Array.sol"; import {LibBytes32Matrix} from "rain.solmem/lib/LibBytes32Matrix.sol"; @@ -172,9 +172,9 @@ struct OrderIOCalculationV4 { bytes32[] kvs; } -/// @title OrderBookV6 +/// @title RaindexV6 /// See `IRaindexV6` for more documentation. -contract OrderBookV6 is IRaindexV6, IMetaV1_2, ReentrancyGuard, Multicall, OrderBookV6FlashLender { +contract RaindexV6 is IRaindexV6, IMetaV1_2, ReentrancyGuard, Multicall, RaindexV6FlashLender { using LibUint256Array for uint256[]; using SafeERC20 for IERC20; using LibOrder for OrderV4; @@ -233,7 +233,7 @@ contract OrderBookV6 is IRaindexV6, IMetaV1_2, ReentrancyGuard, Multicall, Order /// @inheritdoc IRaindexV6 function entask2(TaskV2[] calldata post) external nonReentrant { - LibOrderBook.doPost(new bytes32[][](0), post); + LibRaindex.doPost(new bytes32[][](0), post); } /// @inheritdoc IRaindexV6 @@ -248,7 +248,7 @@ contract OrderBookV6 is IRaindexV6, IMetaV1_2, ReentrancyGuard, Multicall, Order (uint256 depositAmountUint256, uint8 decimals) = pullTokens(msg.sender, token, depositAmount); - // It is safest with vault deposits to move tokens in to the Orderbook + // It is safest with vault deposits to move tokens in to the Raindex // before updating internal vault balances although we have a reentrancy // guard in place anyway. emit DepositV2(msg.sender, token, vaultId, depositAmountUint256); @@ -256,7 +256,7 @@ contract OrderBookV6 is IRaindexV6, IMetaV1_2, ReentrancyGuard, Multicall, Order (Float beforeBalance, Float afterBalance) = increaseVaultBalance(msg.sender, token, vaultId, depositAmount); if (post.length != 0) { - LibOrderBook.doPost( + LibRaindex.doPost( LibBytes32Matrix.matrixFrom( LibBytes32Array.arrayFrom( bytes32(uint256(uint160(token))), @@ -306,7 +306,7 @@ contract OrderBookV6 is IRaindexV6, IMetaV1_2, ReentrancyGuard, Multicall, Order bytes32[][] memory context = LibBytes32Matrix.matrixFrom(contextColumn); if (post.length != 0) { - LibOrderBook.doPost(context, post); + LibRaindex.doPost(context, post); } } @@ -349,7 +349,7 @@ contract OrderBookV6 is IRaindexV6, IMetaV1_2, ReentrancyGuard, Multicall, Order emit MetaV1_2(order.owner, orderHash, orderConfig.meta); } - LibOrderBook.doPost( + LibRaindex.doPost( LibBytes32Matrix.matrixFrom( LibBytes32Array.arrayFrom(orderHash, bytes32(uint256(uint160(msg.sender)))) ), @@ -375,7 +375,7 @@ contract OrderBookV6 is IRaindexV6, IMetaV1_2, ReentrancyGuard, Multicall, Order sOrders[orderHash] = ORDER_DEAD; emit RemoveOrderV3(msg.sender, orderHash, order); - LibOrderBook.doPost( + LibRaindex.doPost( LibBytes32Matrix.matrixFrom( LibBytes32Array.arrayFrom(orderHash, bytes32(uint256(uint160(msg.sender)))) ), diff --git a/src/concrete/parser/OrderBookV6SubParser.sol b/src/concrete/parser/RaindexV6SubParser.sol similarity index 85% rename from src/concrete/parser/OrderBookV6SubParser.sol rename to src/concrete/parser/RaindexV6SubParser.sol index 9bade6da61..fc98d38291 100644 --- a/src/concrete/parser/OrderBookV6SubParser.sol +++ b/src/concrete/parser/RaindexV6SubParser.sol @@ -12,7 +12,7 @@ import {LibConvert} from "rain.lib.typecast/LibConvert.sol"; import {LibUint256Matrix} from "rain.solmem/lib/LibUint256Matrix.sol"; import { - LibOrderBookSubParser, + LibRaindexSubParser, SUB_PARSER_WORD_PARSERS_LENGTH, DEPOSIT_WORD_VAULT_ID, DEPOSIT_WORD_TOKEN, @@ -27,7 +27,7 @@ import { WITHDRAW_WORD_VAULT_AFTER, WITHDRAW_WORD_TARGET_AMOUNT, WITHDRAW_WORDS_LENGTH -} from "../../lib/LibOrderBookSubParser.sol"; +} from "../../lib/LibRaindexSubParser.sol"; import { CONTEXT_BASE_COLUMN, CONTEXT_BASE_ROW_SENDER, @@ -59,21 +59,21 @@ import { CONTEXT_SIGNED_CONTEXT_SIGNERS_COLUMN, CONTEXT_SIGNED_CONTEXT_SIGNERS_ROW, CONTEXT_SIGNED_CONTEXT_SIGNERS_ROWS -} from "../../lib/LibOrderBook.sol"; +} from "../../lib/LibRaindex.sol"; import { DESCRIBED_BY_META_HASH, PARSE_META as SUB_PARSER_PARSE_META, SUB_PARSER_WORD_PARSERS, OPERAND_HANDLER_FUNCTION_POINTERS as SUB_PARSER_OPERAND_HANDLERS -} from "../../generated/OrderBookV6SubParser.pointers.sol"; +} from "../../generated/RaindexV6SubParser.pointers.sol"; import {IDescribedByMetaV1} from "rain.metadata/interface/IDescribedByMetaV1.sol"; import {ISubParserToolingV1} from "rain.sol.codegen/interface/ISubParserToolingV1.sol"; -/// @title OrderBookV6SubParser -/// @notice Sub-parser that provides orderbook-specific context words (sender, +/// @title RaindexV6SubParser +/// @notice Sub-parser that provides raindex-specific context words (sender, /// order hash, vault IO, deposit/withdraw, signed context, etc.) to the /// Rain interpreter. -contract OrderBookV6SubParser is BaseRainterpreterSubParser { +contract RaindexV6SubParser is BaseRainterpreterSubParser { using LibUint256Matrix for uint256[][]; /// @inheritdoc IDescribedByMetaV1 @@ -198,63 +198,63 @@ contract OrderBookV6SubParser is BaseRainterpreterSubParser { new function(uint256, uint256, OperandV2) internal view returns (bool, bytes memory, bytes32[] memory)[](CONTEXT_BASE_ROWS); - contextBaseParsers[CONTEXT_BASE_ROW_SENDER] = LibOrderBookSubParser.subParserSender; - contextBaseParsers[CONTEXT_BASE_ROW_CALLING_CONTRACT] = LibOrderBookSubParser.subParserCallingContract; + contextBaseParsers[CONTEXT_BASE_ROW_SENDER] = LibRaindexSubParser.subParserSender; + contextBaseParsers[CONTEXT_BASE_ROW_CALLING_CONTRACT] = LibRaindexSubParser.subParserCallingContract; function(uint256, uint256, OperandV2) internal view returns (bool, bytes memory, bytes32[] memory)[] memory contextCallingContextParsers = new function(uint256, uint256, OperandV2) internal view returns (bool, bytes memory, bytes32[] memory)[](CONTEXT_CALLING_CONTEXT_ROWS); - contextCallingContextParsers[CONTEXT_CALLING_CONTEXT_ROW_ORDER_HASH] = LibOrderBookSubParser.subParserOrderHash; + contextCallingContextParsers[CONTEXT_CALLING_CONTEXT_ROW_ORDER_HASH] = LibRaindexSubParser.subParserOrderHash; contextCallingContextParsers[CONTEXT_CALLING_CONTEXT_ROW_ORDER_OWNER] = - LibOrderBookSubParser.subParserOrderOwner; + LibRaindexSubParser.subParserOrderOwner; contextCallingContextParsers[CONTEXT_CALLING_CONTEXT_ROW_ORDER_COUNTERPARTY] = - LibOrderBookSubParser.subParserOrderCounterparty; + LibRaindexSubParser.subParserOrderCounterparty; function(uint256, uint256, OperandV2) internal view returns (bool, bytes memory, bytes32[] memory)[] memory contextCalculationsParsers = new function(uint256, uint256, OperandV2) internal view returns (bool, bytes memory, bytes32[] memory)[](CONTEXT_CALCULATIONS_ROWS); - contextCalculationsParsers[CONTEXT_CALCULATIONS_ROW_MAX_OUTPUT] = LibOrderBookSubParser.subParserMaxOutput; - contextCalculationsParsers[CONTEXT_CALCULATIONS_ROW_IO_RATIO] = LibOrderBookSubParser.subParserIORatio; + contextCalculationsParsers[CONTEXT_CALCULATIONS_ROW_MAX_OUTPUT] = LibRaindexSubParser.subParserMaxOutput; + contextCalculationsParsers[CONTEXT_CALCULATIONS_ROW_IO_RATIO] = LibRaindexSubParser.subParserIORatio; function(uint256, uint256, OperandV2) internal view returns (bool, bytes memory, bytes32[] memory)[] memory contextVaultInputsParsers = new function(uint256, uint256, OperandV2) internal view returns (bool, bytes memory, bytes32[] memory)[](CONTEXT_VAULT_IO_ROWS); - contextVaultInputsParsers[CONTEXT_VAULT_IO_TOKEN] = LibOrderBookSubParser.subParserInputToken; - contextVaultInputsParsers[CONTEXT_VAULT_IO_TOKEN_DECIMALS] = LibOrderBookSubParser.subParserInputTokenDecimals; - contextVaultInputsParsers[CONTEXT_VAULT_IO_VAULT_ID] = LibOrderBookSubParser.subParserInputVaultId; - contextVaultInputsParsers[CONTEXT_VAULT_IO_BALANCE_BEFORE] = LibOrderBookSubParser.subParserInputBalanceBefore; - contextVaultInputsParsers[CONTEXT_VAULT_IO_BALANCE_DIFF] = LibOrderBookSubParser.subParserInputBalanceDiff; + contextVaultInputsParsers[CONTEXT_VAULT_IO_TOKEN] = LibRaindexSubParser.subParserInputToken; + contextVaultInputsParsers[CONTEXT_VAULT_IO_TOKEN_DECIMALS] = LibRaindexSubParser.subParserInputTokenDecimals; + contextVaultInputsParsers[CONTEXT_VAULT_IO_VAULT_ID] = LibRaindexSubParser.subParserInputVaultId; + contextVaultInputsParsers[CONTEXT_VAULT_IO_BALANCE_BEFORE] = LibRaindexSubParser.subParserInputBalanceBefore; + contextVaultInputsParsers[CONTEXT_VAULT_IO_BALANCE_DIFF] = LibRaindexSubParser.subParserInputBalanceDiff; function(uint256, uint256, OperandV2) internal view returns (bool, bytes memory, bytes32[] memory)[] memory contextVaultOutputsParsers = new function(uint256, uint256, OperandV2) internal view returns (bool, bytes memory, bytes32[] memory)[](CONTEXT_VAULT_IO_ROWS); - contextVaultOutputsParsers[CONTEXT_VAULT_IO_TOKEN] = LibOrderBookSubParser.subParserOutputToken; - contextVaultOutputsParsers[CONTEXT_VAULT_IO_TOKEN_DECIMALS] = LibOrderBookSubParser.subParserOutputTokenDecimals; - contextVaultOutputsParsers[CONTEXT_VAULT_IO_VAULT_ID] = LibOrderBookSubParser.subParserOutputVaultId; - contextVaultOutputsParsers[CONTEXT_VAULT_IO_BALANCE_BEFORE] = LibOrderBookSubParser.subParserOutputBalanceBefore; - contextVaultOutputsParsers[CONTEXT_VAULT_IO_BALANCE_DIFF] = LibOrderBookSubParser.subParserOutputBalanceDiff; + contextVaultOutputsParsers[CONTEXT_VAULT_IO_TOKEN] = LibRaindexSubParser.subParserOutputToken; + contextVaultOutputsParsers[CONTEXT_VAULT_IO_TOKEN_DECIMALS] = LibRaindexSubParser.subParserOutputTokenDecimals; + contextVaultOutputsParsers[CONTEXT_VAULT_IO_VAULT_ID] = LibRaindexSubParser.subParserOutputVaultId; + contextVaultOutputsParsers[CONTEXT_VAULT_IO_BALANCE_BEFORE] = LibRaindexSubParser.subParserOutputBalanceBefore; + contextVaultOutputsParsers[CONTEXT_VAULT_IO_BALANCE_DIFF] = LibRaindexSubParser.subParserOutputBalanceDiff; function(uint256, uint256, OperandV2) internal view returns (bool, bytes memory, bytes32[] memory)[] memory contextSignersParsers = new function(uint256, uint256, OperandV2) internal view returns (bool, bytes memory, bytes32[] memory)[](CONTEXT_SIGNED_CONTEXT_SIGNERS_ROWS); - contextSignersParsers[CONTEXT_SIGNED_CONTEXT_SIGNERS_ROW] = LibOrderBookSubParser.subParserSigners; + contextSignersParsers[CONTEXT_SIGNED_CONTEXT_SIGNERS_ROW] = LibRaindexSubParser.subParserSigners; function(uint256, uint256, OperandV2) internal view returns (bool, bytes memory, bytes32[] memory)[] memory contextSignedContextParsers = new function(uint256, uint256, OperandV2) internal view returns (bool, bytes memory, bytes32[] memory)[](CONTEXT_SIGNED_CONTEXT_START_ROWS); - contextSignedContextParsers[CONTEXT_SIGNED_CONTEXT_START_ROW] = LibOrderBookSubParser.subParserSignedContext; + contextSignedContextParsers[CONTEXT_SIGNED_CONTEXT_START_ROW] = LibRaindexSubParser.subParserSignedContext; parsers[CONTEXT_BASE_COLUMN] = contextBaseParsers; parsers[CONTEXT_CALLING_CONTEXT_COLUMN] = contextCallingContextParsers; @@ -272,11 +272,11 @@ contract OrderBookV6SubParser is BaseRainterpreterSubParser { internal view returns (bool, bytes memory, bytes32[] memory)[](DEPOSIT_WORDS_LENGTH); - depositParsers[DEPOSIT_WORD_DEPOSITOR] = LibOrderBookSubParser.subParserSender; - depositParsers[DEPOSIT_WORD_TOKEN] = LibOrderBookSubParser.subParserDepositToken; - depositParsers[DEPOSIT_WORD_VAULT_ID] = LibOrderBookSubParser.subParserDepositVaultId; - depositParsers[DEPOSIT_WORD_VAULT_BEFORE] = LibOrderBookSubParser.subParserDepositVaultBalanceBefore; - depositParsers[DEPOSIT_WORD_VAULT_AFTER] = LibOrderBookSubParser.subParserDepositVaultBalanceAfter; + depositParsers[DEPOSIT_WORD_DEPOSITOR] = LibRaindexSubParser.subParserSender; + depositParsers[DEPOSIT_WORD_TOKEN] = LibRaindexSubParser.subParserDepositToken; + depositParsers[DEPOSIT_WORD_VAULT_ID] = LibRaindexSubParser.subParserDepositVaultId; + depositParsers[DEPOSIT_WORD_VAULT_BEFORE] = LibRaindexSubParser.subParserDepositVaultBalanceBefore; + depositParsers[DEPOSIT_WORD_VAULT_AFTER] = LibRaindexSubParser.subParserDepositVaultBalanceAfter; parsers[CONTEXT_SIGNED_CONTEXT_START_COLUMN + 1] = depositParsers; @@ -288,12 +288,12 @@ contract OrderBookV6SubParser is BaseRainterpreterSubParser { internal view returns (bool, bytes memory, bytes32[] memory)[](WITHDRAW_WORDS_LENGTH); - withdrawParsers[WITHDRAW_WORD_WITHDRAWER] = LibOrderBookSubParser.subParserSender; - withdrawParsers[WITHDRAW_WORD_TOKEN] = LibOrderBookSubParser.subParserWithdrawToken; - withdrawParsers[WITHDRAW_WORD_VAULT_ID] = LibOrderBookSubParser.subParserWithdrawVaultId; - withdrawParsers[WITHDRAW_WORD_VAULT_BEFORE] = LibOrderBookSubParser.subParserWithdrawVaultBalanceBefore; - withdrawParsers[WITHDRAW_WORD_VAULT_AFTER] = LibOrderBookSubParser.subParserWithdrawVaultBalanceAfter; - withdrawParsers[WITHDRAW_WORD_TARGET_AMOUNT] = LibOrderBookSubParser.subParserWithdrawTargetAmount; + withdrawParsers[WITHDRAW_WORD_WITHDRAWER] = LibRaindexSubParser.subParserSender; + withdrawParsers[WITHDRAW_WORD_TOKEN] = LibRaindexSubParser.subParserWithdrawToken; + withdrawParsers[WITHDRAW_WORD_VAULT_ID] = LibRaindexSubParser.subParserWithdrawVaultId; + withdrawParsers[WITHDRAW_WORD_VAULT_BEFORE] = LibRaindexSubParser.subParserWithdrawVaultBalanceBefore; + withdrawParsers[WITHDRAW_WORD_VAULT_AFTER] = LibRaindexSubParser.subParserWithdrawVaultBalanceAfter; + withdrawParsers[WITHDRAW_WORD_TARGET_AMOUNT] = LibRaindexSubParser.subParserWithdrawTargetAmount; parsers[CONTEXT_SIGNED_CONTEXT_START_COLUMN + 2] = withdrawParsers; diff --git a/src/generated/GenericPoolOrderBookV6ArbOrderTaker.pointers.sol b/src/generated/GenericPoolRaindexV6ArbOrderTaker.pointers.sol similarity index 100% rename from src/generated/GenericPoolOrderBookV6ArbOrderTaker.pointers.sol rename to src/generated/GenericPoolRaindexV6ArbOrderTaker.pointers.sol diff --git a/src/generated/GenericPoolOrderBookV6FlashBorrower.pointers.sol b/src/generated/GenericPoolRaindexV6FlashBorrower.pointers.sol similarity index 100% rename from src/generated/GenericPoolOrderBookV6FlashBorrower.pointers.sol rename to src/generated/GenericPoolRaindexV6FlashBorrower.pointers.sol diff --git a/src/generated/OrderBookV6.pointers.sol b/src/generated/RaindexV6.pointers.sol similarity index 100% rename from src/generated/OrderBookV6.pointers.sol rename to src/generated/RaindexV6.pointers.sol diff --git a/src/generated/OrderBookV6SubParser.pointers.sol b/src/generated/RaindexV6SubParser.pointers.sol similarity index 100% rename from src/generated/OrderBookV6SubParser.pointers.sol rename to src/generated/RaindexV6SubParser.pointers.sol diff --git a/src/generated/RouteProcessorOrderBookV6ArbOrderTaker.pointers.sol b/src/generated/RouteProcessorRaindexV6ArbOrderTaker.pointers.sol similarity index 100% rename from src/generated/RouteProcessorOrderBookV6ArbOrderTaker.pointers.sol rename to src/generated/RouteProcessorRaindexV6ArbOrderTaker.pointers.sol diff --git a/src/lib/LibOrderBook.sol b/src/lib/LibRaindex.sol similarity index 98% rename from src/lib/LibOrderBook.sol rename to src/lib/LibRaindex.sol index 268f3e77d0..e7e58d2f5c 100644 --- a/src/lib/LibOrderBook.sol +++ b/src/lib/LibRaindex.sol @@ -12,7 +12,7 @@ import { import {LibNamespace, FullyQualifiedNamespace} from "rain.interpreter.interface/lib/ns/LibNamespace.sol"; import {LibContext} from "rain.interpreter.interface/lib/caller/LibContext.sol"; -/// @dev Orderbook context is actually fairly complex. The calling context column +/// @dev Raindex context is actually fairly complex. The calling context column /// is populated before calculate order, but the remaining columns are only /// available to handle IO as they depend on the full evaluation of calculate /// order, and cross referencing against the same from the counterparty, as well @@ -99,7 +99,7 @@ uint256 constant CONTEXT_SIGNED_CONTEXT_START_COLUMN = 6; uint256 constant CONTEXT_SIGNED_CONTEXT_START_ROWS = 1; uint256 constant CONTEXT_SIGNED_CONTEXT_START_ROW = 0; -library LibOrderBook { +library LibRaindex { /// @dev Evaluates each task in `post` against the provided `context`. /// Tasks with empty bytecode are skipped. function doPost(bytes32[][] memory context, TaskV2[] memory post) internal { diff --git a/src/lib/LibOrderBookArb.sol b/src/lib/LibRaindexArb.sol similarity index 95% rename from src/lib/LibOrderBookArb.sol rename to src/lib/LibRaindexArb.sol index 2d2ea84b4a..4c27735ff3 100644 --- a/src/lib/LibOrderBookArb.sol +++ b/src/lib/LibRaindexArb.sol @@ -4,13 +4,13 @@ pragma solidity ^0.8.19; import {TaskV2} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import {LibOrderBook} from "./LibOrderBook.sol"; +import {LibRaindex} from "./LibRaindex.sol"; import {Address} from "openzeppelin-contracts/contracts/utils/Address.sol"; import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import {LibDecimalFloat, Float} from "rain.math.float/lib/LibDecimalFloat.sol"; -/// @title LibOrderBookArb -library LibOrderBookArb { +/// @title LibRaindexArb +library LibRaindexArb { using SafeERC20 for IERC20; /// @dev Sends all remaining token balances and native gas to `msg.sender`, @@ -70,6 +70,6 @@ library LibOrderBookArb { TaskV2[] memory post = new TaskV2[](1); post[0] = task; - LibOrderBook.doPost(context, post); + LibRaindex.doPost(context, post); } } diff --git a/src/lib/LibOrderBookSubParser.sol b/src/lib/LibRaindexSubParser.sol similarity index 98% rename from src/lib/LibOrderBookSubParser.sol rename to src/lib/LibRaindexSubParser.sol index d26cb58c5a..bb03cca804 100644 --- a/src/lib/LibOrderBookSubParser.sol +++ b/src/lib/LibRaindexSubParser.sol @@ -46,13 +46,13 @@ import { CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_BEFORE, CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_AFTER, CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_TARGET_AMOUNT -} from "./LibOrderBook.sol"; +} from "./LibRaindex.sol"; uint256 constant SUB_PARSER_WORD_PARSERS_LENGTH = 2; uint8 constant EXTERN_PARSE_META_BUILD_DEPTH = 1; bytes constant WORD_ORDER_CLEARER = "order-clearer"; -bytes constant WORD_ORDERBOOK = "orderbook"; +bytes constant WORD_RAINDEX = "raindex"; bytes constant WORD_ORDER_HASH = "order-hash"; bytes constant WORD_ORDER_OWNER = "order-owner"; bytes constant WORD_ORDER_COUNTERPARTY = "order-counterparty"; @@ -97,10 +97,10 @@ uint256 constant WITHDRAW_WORD_VAULT_AFTER = 4; uint256 constant WITHDRAW_WORD_TARGET_AMOUNT = 5; uint256 constant WITHDRAW_WORDS_LENGTH = 6; -/// @title LibOrderBookSubParser -/// @notice Sub-parser word dispatch and authoring metadata for OrderBook +/// @title LibRaindexSubParser +/// @notice Sub-parser word dispatch and authoring metadata for Raindex /// context columns (base, calling, calculations, vault IO, signed). -library LibOrderBookSubParser { +library LibRaindexSubParser { using LibUint256Matrix for uint256[][]; /// @dev Maps the "sender" word to the base context column sender row. @@ -400,7 +400,7 @@ library LibOrderBookSubParser { return LibSubParse.subParserContext(CONTEXT_SIGNED_CONTEXT_START_COLUMN + column, row); } - /// @dev Builds the complete authoring metadata for all orderbook context + /// @dev Builds the complete authoring metadata for all raindex context /// words. Returns ABI-encoded `AuthoringMetaV2[]` covering every context /// column (base, calling, calculations, vault IO, signers, signed context, /// deposit, withdraw). The inner arrays are flattened before encoding. @@ -417,10 +417,10 @@ library LibOrderBookSubParser { "The order clearer is the address that submitted the transaction that is causing the order to execute. This MAY be the counterparty, e.g. when an order is being taken directly, but it MAY NOT be the counterparty if a third party is clearing two orders against each other." ); contextBaseMeta[CONTEXT_BASE_ROW_CALLING_CONTRACT] = - // constant WORD_ORDERBOOK defined above is less than 32 bytes, so + // constant WORD_RAINDEX defined above is less than 32 bytes, so // this conversion is safe. // forge-lint: disable-next-line(unsafe-typecast) - AuthoringMetaV2(bytes32(WORD_ORDERBOOK), "The address of the orderbook that the order is being run on."); + AuthoringMetaV2(bytes32(WORD_RAINDEX), "The address of the raindex that the order is being run on."); AuthoringMetaV2[] memory contextCallingContextMeta = new AuthoringMetaV2[](CONTEXT_CALLING_CONTEXT_ROWS); contextCallingContextMeta[CONTEXT_CALLING_CONTEXT_ROW_ORDER_HASH] = @@ -540,7 +540,7 @@ library LibOrderBookSubParser { // conversion is safe. // forge-lint: disable-next-line(unsafe-typecast) bytes32("signed-context"), - "Signed context is provided by the order clearer/taker and can be signed by anyone. Orderbook will check the signature, but the expression author must authorize the signer's public key." + "Signed context is provided by the order clearer/taker and can be signed by anyone. Raindex will check the signature, but the expression author must authorize the signer's public key." ); meta[CONTEXT_BASE_COLUMN] = contextBaseMeta; diff --git a/src/lib/deploy/LibOrderBookDeploy.sol b/src/lib/deploy/LibRaindexDeploy.sol similarity index 61% rename from src/lib/deploy/LibOrderBookDeploy.sol rename to src/lib/deploy/LibRaindexDeploy.sol index 3c18566c7a..a5f89c8927 100644 --- a/src/lib/deploy/LibOrderBookDeploy.sol +++ b/src/lib/deploy/LibRaindexDeploy.sol @@ -3,13 +3,13 @@ pragma solidity ^0.8.25; import { - BYTECODE_HASH as ORDERBOOK_HASH, - DEPLOYED_ADDRESS as ORDERBOOK_ADDR -} from "../../generated/OrderBookV6.pointers.sol"; + BYTECODE_HASH as RAINDEX_HASH, + DEPLOYED_ADDRESS as RAINDEX_ADDR +} from "../../generated/RaindexV6.pointers.sol"; import { BYTECODE_HASH as SUB_PARSER_HASH, DEPLOYED_ADDRESS as SUB_PARSER_ADDR -} from "../../generated/OrderBookV6SubParser.pointers.sol"; +} from "../../generated/RaindexV6SubParser.pointers.sol"; import { BYTECODE_HASH as ROUTE_PROCESSOR_HASH, DEPLOYED_ADDRESS as ROUTE_PROCESSOR_ADDR @@ -17,36 +17,36 @@ import { import { BYTECODE_HASH as GENERIC_POOL_ARB_OT_HASH, DEPLOYED_ADDRESS as GENERIC_POOL_ARB_OT_ADDR -} from "../../generated/GenericPoolOrderBookV6ArbOrderTaker.pointers.sol"; +} from "../../generated/GenericPoolRaindexV6ArbOrderTaker.pointers.sol"; import { BYTECODE_HASH as RP_ARB_OT_HASH, DEPLOYED_ADDRESS as RP_ARB_OT_ADDR -} from "../../generated/RouteProcessorOrderBookV6ArbOrderTaker.pointers.sol"; +} from "../../generated/RouteProcessorRaindexV6ArbOrderTaker.pointers.sol"; import { BYTECODE_HASH as GENERIC_POOL_FB_HASH, DEPLOYED_ADDRESS as GENERIC_POOL_FB_ADDR -} from "../../generated/GenericPoolOrderBookV6FlashBorrower.pointers.sol"; +} from "../../generated/GenericPoolRaindexV6FlashBorrower.pointers.sol"; -/// @title LibOrderBookDeploy +/// @title LibRaindexDeploy /// @notice A library containing the deployed address and code hash of the -/// OrderBook contracts when deployed with the rain standard zoltu deployer. +/// Raindex contracts when deployed with the rain standard zoltu deployer. /// This allows idempotent deployments against precommitted addresses and hashes /// that can be easily verified automatically in tests and scripts rather than /// relying on registries or manual verification. -library LibOrderBookDeploy { - /// The address of the `OrderBookV6` contract when deployed with the rain +library LibRaindexDeploy { + /// The address of the `RaindexV6` contract when deployed with the rain /// standard zoltu deployer. - address constant ORDERBOOK_DEPLOYED_ADDRESS = ORDERBOOK_ADDR; + address constant RAINDEX_DEPLOYED_ADDRESS = RAINDEX_ADDR; - /// The code hash of the `OrderBookV6` contract when deployed with the rain + /// The code hash of the `RaindexV6` contract when deployed with the rain /// standard zoltu deployer. - bytes32 constant ORDERBOOK_DEPLOYED_CODEHASH = ORDERBOOK_HASH; + bytes32 constant RAINDEX_DEPLOYED_CODEHASH = RAINDEX_HASH; - /// The address of the `OrderBookV6SubParser` contract when deployed with + /// The address of the `RaindexV6SubParser` contract when deployed with /// the rain standard zoltu deployer. address constant SUB_PARSER_DEPLOYED_ADDRESS = SUB_PARSER_ADDR; - /// The code hash of the `OrderBookV6SubParser` contract when deployed with + /// The code hash of the `RaindexV6SubParser` contract when deployed with /// the rain standard zoltu deployer. bytes32 constant SUB_PARSER_DEPLOYED_CODEHASH = SUB_PARSER_HASH; @@ -58,32 +58,32 @@ library LibOrderBookDeploy { /// rain standard zoltu deployer. bytes32 constant ROUTE_PROCESSOR_DEPLOYED_CODEHASH = ROUTE_PROCESSOR_HASH; - /// The address of the `GenericPoolOrderBookV6ArbOrderTaker` contract when + /// The address of the `GenericPoolRaindexV6ArbOrderTaker` contract when /// deployed with the rain standard zoltu deployer. address constant GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_ADDRESS = GENERIC_POOL_ARB_OT_ADDR; - /// The code hash of the `GenericPoolOrderBookV6ArbOrderTaker` contract when + /// The code hash of the `GenericPoolRaindexV6ArbOrderTaker` contract when /// deployed with the rain standard zoltu deployer. bytes32 constant GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_CODEHASH = GENERIC_POOL_ARB_OT_HASH; - /// The address of the `RouteProcessorOrderBookV6ArbOrderTaker` contract + /// The address of the `RouteProcessorRaindexV6ArbOrderTaker` contract /// when deployed with the rain standard zoltu deployer. address constant ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_ADDRESS = RP_ARB_OT_ADDR; - /// The code hash of the `RouteProcessorOrderBookV6ArbOrderTaker` contract + /// The code hash of the `RouteProcessorRaindexV6ArbOrderTaker` contract /// when deployed with the rain standard zoltu deployer. bytes32 constant ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_CODEHASH = RP_ARB_OT_HASH; - /// The address of the `GenericPoolOrderBookV6FlashBorrower` contract when + /// The address of the `GenericPoolRaindexV6FlashBorrower` contract when /// deployed with the rain standard zoltu deployer. address constant GENERIC_POOL_FLASH_BORROWER_DEPLOYED_ADDRESS = GENERIC_POOL_FB_ADDR; - /// The code hash of the `GenericPoolOrderBookV6FlashBorrower` contract when + /// The code hash of the `GenericPoolRaindexV6FlashBorrower` contract when /// deployed with the rain standard zoltu deployer. bytes32 constant GENERIC_POOL_FLASH_BORROWER_DEPLOYED_CODEHASH = GENERIC_POOL_FB_HASH; - uint256 constant ORDERBOOK_START_BLOCK_ARBITRUM = 441612693; - uint256 constant ORDERBOOK_START_BLOCK_BASE = 43339885; - uint256 constant ORDERBOOK_START_BLOCK_FLARE = 56972130; - uint256 constant ORDERBOOK_START_BLOCK_POLYGON = 84174550; + uint256 constant RAINDEX_START_BLOCK_ARBITRUM = 441612693; + uint256 constant RAINDEX_START_BLOCK_BASE = 43339885; + uint256 constant RAINDEX_START_BLOCK_FLARE = 56972130; + uint256 constant RAINDEX_START_BLOCK_POLYGON = 84174550; } From 72e39b2f38c9ada6cf5d5b76f04ce13ce6acc4a6 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Thu, 26 Mar 2026 12:58:10 +0400 Subject: [PATCH 02/69] Rename OrderBook to Raindex in test/ Content and file renames for all test utility, abstract, concrete, and lib test files. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../abstract/OrderBookV6FlashLender.fee.t.sol | 14 - .../OrderBookV6FlashLender.maxFlashLoan.t.sol | 19 -- ....sol => RaindexV6ArbCommon.fallback.t.sol} | 12 +- ...l => RaindexV6ArbOrderTaker.context.t.sol} | 14 +- ...l => RaindexV6ArbOrderTaker.ierc165.t.sol} | 8 +- ... => RaindexV6ArbOrderTaker.noOrders.t.sol} | 10 +- ...aindexV6ArbOrderTaker.onTakeOrders2.t.sol} | 16 +- ...V6ArbOrderTaker.onTakeOrders2Direct.t.sol} | 6 +- ...> RaindexV6ArbOrderTaker.reentrancy.t.sol} | 14 +- ...ArbTaskGated.checkTaskHashPassMatch.t.sol} | 8 +- ...6ArbTaskGated.checkTaskHashPassZero.t.sol} | 8 +- ...ArbTaskGated.checkTaskHashWrongTask.t.sol} | 8 +- ... => RaindexV6ArbTaskGated.construct.t.sol} | 12 +- ...ndexV6ArbTaskGated.iTaskHashNonzero.t.sol} | 8 +- ...RaindexV6ArbTaskGated.iTaskHashZero.t.sol} | 8 +- ...RaindexV6FlashBorrower.badInitiator.t.sol} | 16 +- ...exV6FlashBorrower.badLenderApproval.t.sol} | 18 +- ...ndexV6FlashBorrower.flashLoanFailed.t.sol} | 24 +- ...l => RaindexV6FlashBorrower.ierc165.t.sol} | 10 +- ...dexV6FlashBorrower.lenderValidation.t.sol} | 10 +- ...aindexV6FlashBorrower.mixedDecimals.t.sol} | 22 +- ... => RaindexV6FlashBorrower.noOrders.t.sol} | 10 +- ...xV6FlashBorrower.realTokenTransfers.t.sol} | 24 +- ...> RaindexV6FlashBorrower.reentrancy.t.sol} | 24 +- test/abstract/RaindexV6FlashLender.fee.t.sol | 14 + ...RaindexV6FlashLender.griefRecipient.t.sol} | 16 +- ...sol => RaindexV6FlashLender.ierc165.t.sol} | 12 +- .../RaindexV6FlashLender.maxFlashLoan.t.sol | 19 ++ ...=> RaindexV6FlashLender.mockSuccess.t.sol} | 12 +- ...l => RaindexV6FlashLender.reentrant.t.sol} | 26 +- ...l => RaindexV6FlashLender.transfers.t.sol} | 18 +- ...ndexV6ArbOrderTaker.approvalRevoked.t.sol} | 4 +- ...indexV6ArbOrderTaker.exchangeRevert.t.sol} | 4 +- ...icPoolRaindexV6ArbOrderTaker.sender.t.sol} | 10 +- ...ndexV6FlashBorrower.approvalRevoked.t.sol} | 4 +- ...RaindexV6FlashBorrower.ethForwarded.t.sol} | 4 +- ...indexV6FlashBorrower.exchangeRevert.t.sol} | 4 +- ...icPoolRaindexV6FlashBorrower.sender.t.sol} | 12 +- ...aindexV6ArbOrderTaker.lossyRounding.t.sol} | 20 +- ...V6ArbOrderTaker.nonStandardDecimals.t.sol} | 26 +- ...aindexV6ArbOrderTaker.onTakeOrders2.t.sol} | 26 +- ...V6ArbOrderTaker.onTakeOrders2Direct.t.sol} | 12 +- ...cessorRaindexV6ArbOrderTaker.sender.t.sol} | 14 +- .../ob/OrderBookV6.removeOrder.owner.t.sol | 138 -------- ....t.sol => RaindexV6.addOrder.entask.t.sol} | 14 +- ...ck.t.sol => RaindexV6.addOrder.mock.t.sol} | 24 +- ...e.t.sol => RaindexV6.addOrder.nonce.t.sol} | 28 +- ...r.t.sol => RaindexV6.addOrder.owner.t.sol} | 20 +- ...ddOrder.t.sol => RaindexV6.addOrder.t.sol} | 28 +- ...k.t.sol => RaindexV6.clear.badStack.t.sol} | 12 +- ...xt.t.sol => RaindexV6.clear.context.t.sol} | 20 +- ... => RaindexV6.clear.handleIO.revert.t.sol} | 20 +- ....mock.t.sol => RaindexV6.clear.mock.t.sol} | 52 +-- ....t.sol => RaindexV6.clear.sameOwner.t.sol} | 12 +- ....t.sol => RaindexV6.clear.sameToken.t.sol} | 12 +- ...t.sol => RaindexV6.clear.zeroAmount.t.sol} | 12 +- ...k.t.sol => RaindexV6.deposit.entask.t.sol} | 36 +- ....deposit.t.sol => RaindexV6.deposit.t.sol} | 50 +-- ...V6.entask.t.sol => RaindexV6.entask.t.sol} | 20 +- ....t.sol => RaindexV6.quote.sameToken.t.sol} | 12 +- ...okV6.quote.t.sol => RaindexV6.quote.t.sol} | 22 +- ...sol => RaindexV6.removeOrder.entask.t.sol} | 20 +- ...t.sol => RaindexV6.removeOrder.mock.t.sol} | 34 +- .../ob/RaindexV6.removeOrder.owner.t.sol | 138 ++++++++ ...sol => RaindexV6.takeOrder.badStack.t.sol} | 10 +- ...RaindexV6.takeOrder.exceedsMaxRatio.t.sol} | 10 +- ...RaindexV6.takeOrder.handleIO.revert.t.sol} | 20 +- ...=> RaindexV6.takeOrder.maximumInput.t.sol} | 26 +- ...> RaindexV6.takeOrder.maximumOutput.t.sol} | 26 +- ...ol => RaindexV6.takeOrder.minimumIO.t.sol} | 12 +- ...p.t.sol => RaindexV6.takeOrder.noop.t.sol} | 16 +- ...ol => RaindexV6.takeOrder.precision.t.sol} | 22 +- ...ol => RaindexV6.takeOrder.sameToken.t.sol} | 10 +- ...> RaindexV6.takeOrder.tokenMismatch.t.sol} | 14 +- ...nce.t.sol => RaindexV6.vaultBalance.t.sol} | 8 +- ....t.sol => RaindexV6.withdraw.entask.t.sol} | 44 +-- ...ithdraw.t.sol => RaindexV6.withdraw.t.sol} | 56 ++-- ...OrderBookV6SubParser.describedByMeta.t.sol | 21 -- ...6SubParser.contextCalculatedIORatio.t.sol} | 4 +- ...ubParser.contextCalculatedMaxOutput.t.sol} | 4 +- ...aindexV6SubParser.contextInputToken.t.sol} | 4 +- ...SubParser.contextInputTokenDecimals.t.sol} | 4 +- ...rser.contextInputVaultBalanceBefore.t.sol} | 4 +- ...er.contextInputVaultBalanceIncrease.t.sol} | 4 +- ...ndexV6SubParser.contextInputVaultId.t.sol} | 4 +- ...ndexV6SubParser.contextOrderClearer.t.sol} | 4 +- ...6SubParser.contextOrderCounterparty.t.sol} | 4 +- ...RaindexV6SubParser.contextOrderHash.t.sol} | 4 +- ...aindexV6SubParser.contextOrderOwner.t.sol} | 4 +- ...indexV6SubParser.contextOutputToken.t.sol} | 4 +- ...ubParser.contextOutputTokenDecimals.t.sol} | 4 +- ...ser.contextOutputVaultBalanceBefore.t.sol} | 4 +- ...r.contextOutputVaultBalanceDecrease.t.sol} | 4 +- ...dexV6SubParser.contextOutputVaultId.t.sol} | 4 +- ...> RaindexV6SubParser.contextRaindex.t.sol} | 6 +- .../RaindexV6SubParser.describedByMeta.t.sol | 21 ++ ...t.sol => RaindexV6SubParser.ierc165.t.sol} | 14 +- ....sol => RaindexV6SubParser.pointers.t.sol} | 22 +- ...=> RaindexV6SubParser.signedContext.t.sol} | 32 +- ...t.sol => RaindexV6SubParser.signers.t.sol} | 24 +- ... LibRaindexArb.finalizeArbNativeGas.t.sol} | 2 +- ...dexArb.finalizeArbOutputTokenProfit.t.sol} | 4 +- ...ibRaindexArb.finalizeArbTaskContext.t.sol} | 4 +- ...aindexArb.finalizeArbTokenTransfers.t.sol} | 4 +- test/lib/deploy/LibOrderBookDeploy.t.sol | 311 ------------------ test/lib/deploy/LibRaindexDeploy.t.sol | 311 ++++++++++++++++++ ...ibRaindexDeployIsStartBlockArbitrum.t.sol} | 12 +- ...=> LibRaindexDeployIsStartBlockBase.t.sol} | 12 +- ...> LibRaindexDeployIsStartBlockFlare.t.sol} | 12 +- ...LibRaindexDeployIsStartBlockPolygon.t.sol} | 12 +- ...bRaindexDeployNetworksJsonAddresses.t.sol} | 10 +- ...eployNetworksJsonStartBlockArbitrum.t.sol} | 10 +- ...dexDeployNetworksJsonStartBlockBase.t.sol} | 10 +- ...exDeployNetworksJsonStartBlockFlare.t.sol} | 10 +- ...DeployNetworksJsonStartBlockPolygon.t.sol} | 10 +- ...yProd.t.sol => LibRaindexDeployProd.t.sol} | 40 +-- ... LibRaindexDeployStartBlockArbitrum.t.sol} | 14 +- ...l => LibRaindexDeployStartBlockBase.t.sol} | 12 +- ... => LibRaindexDeployStartBlockFlare.t.sol} | 12 +- ...> LibRaindexDeployStartBlockPolygon.t.sol} | 12 +- ...LibRaindexDeploySubgraphYamlAddress.t.sol} | 10 +- test/util/abstract/ArbTest.sol | 18 +- ...GenericPoolRaindexV6ArbOrderTakerTest.sol} | 6 +- ...kOrderBookBase.sol => MockRaindexBase.sol} | 4 +- ...Test.sol => RaindexV6ExternalMockTest.sol} | 46 +-- ...Test.sol => RaindexV6ExternalRealTest.sol} | 28 +- ...okV6SelfTest.sol => RaindexV6SelfTest.sol} | 8 +- ....sol => RaindexV6SubParserContextTest.sol} | 18 +- ...teProcessorRaindexV6ArbOrderTakerTest.sol} | 8 +- ...er.sol => ChildRaindexV6ArbOrderTaker.sol} | 4 +- ...ted.sol => ChildRaindexV6ArbTaskGated.sol} | 6 +- ...erBook.sol => FlashLendingMockRaindex.sol} | 2 +- test/util/concrete/MaliciousLender.sol | 4 +- ...iousOrderBook.sol => MaliciousRaindex.sol} | 10 +- ...l => RealisticFlashLendingMockRaindex.sol} | 6 +- ...sol => RealisticOrderTakerMockRaindex.sol} | 6 +- test/util/concrete/ReentrantExchange.sol | 12 +- ...OrderBook.sol => ReentrantMockRaindex.sol} | 8 +- ... => LibRaindexSubParserContextFixture.sol} | 8 +- test/util/lib/LibEtchOrderBook.sol | 34 -- test/util/lib/LibEtchRaindex.sol | 34 ++ test/util/lib/LibTestAddOrder.sol | 2 +- test/util/lib/LibTestArb.sol | 30 +- test/util/lib/LibTestFlashBorrowerArb.sol | 24 +- test/util/lib/LibTestTakeOrder.sol | 8 +- 145 files changed, 1475 insertions(+), 1475 deletions(-) delete mode 100644 test/abstract/OrderBookV6FlashLender.fee.t.sol delete mode 100644 test/abstract/OrderBookV6FlashLender.maxFlashLoan.t.sol rename test/abstract/{OrderBookV6ArbCommon.fallback.t.sol => RaindexV6ArbCommon.fallback.t.sol} (82%) rename test/abstract/{OrderBookV6ArbOrderTaker.context.t.sol => RaindexV6ArbOrderTaker.context.t.sol} (89%) rename test/abstract/{OrderBookV6ArbOrderTaker.ierc165.t.sol => RaindexV6ArbOrderTaker.ierc165.t.sol} (77%) rename test/abstract/{OrderBookV6ArbOrderTaker.noOrders.t.sol => RaindexV6ArbOrderTaker.noOrders.t.sol} (79%) rename test/abstract/{OrderBookV6ArbOrderTaker.onTakeOrders2.t.sol => RaindexV6ArbOrderTaker.onTakeOrders2.t.sol} (84%) rename test/abstract/{OrderBookV6ArbOrderTaker.onTakeOrders2Direct.t.sol => RaindexV6ArbOrderTaker.onTakeOrders2Direct.t.sol} (85%) rename test/abstract/{OrderBookV6ArbOrderTaker.reentrancy.t.sol => RaindexV6ArbOrderTaker.reentrancy.t.sol} (83%) rename test/abstract/{OrderBookV6ArbTaskGated.checkTaskHashPassMatch.t.sol => RaindexV6ArbTaskGated.checkTaskHashPassMatch.t.sol} (76%) rename test/abstract/{OrderBookV6ArbTaskGated.checkTaskHashPassZero.t.sol => RaindexV6ArbTaskGated.checkTaskHashPassZero.t.sol} (81%) rename test/abstract/{OrderBookV6ArbTaskGated.checkTaskHashWrongTask.t.sol => RaindexV6ArbTaskGated.checkTaskHashWrongTask.t.sol} (83%) rename test/abstract/{OrderBookV6ArbTaskGated.construct.t.sol => RaindexV6ArbTaskGated.construct.t.sol} (70%) rename test/abstract/{OrderBookV6ArbTaskGated.iTaskHashNonzero.t.sol => RaindexV6ArbTaskGated.iTaskHashNonzero.t.sol} (77%) rename test/abstract/{OrderBookV6ArbTaskGated.iTaskHashZero.t.sol => RaindexV6ArbTaskGated.iTaskHashZero.t.sol} (75%) rename test/abstract/{OrderBookV6FlashBorrower.badInitiator.t.sol => RaindexV6FlashBorrower.badInitiator.t.sol} (55%) rename test/abstract/{OrderBookV6FlashBorrower.badLenderApproval.t.sol => RaindexV6FlashBorrower.badLenderApproval.t.sol} (82%) rename test/abstract/{OrderBookV6FlashBorrower.flashLoanFailed.t.sol => RaindexV6FlashBorrower.flashLoanFailed.t.sol} (73%) rename test/abstract/{OrderBookV6FlashBorrower.ierc165.t.sol => RaindexV6FlashBorrower.ierc165.t.sol} (68%) rename test/abstract/{OrderBookV6FlashBorrower.lenderValidation.t.sol => RaindexV6FlashBorrower.lenderValidation.t.sol} (64%) rename test/abstract/{OrderBookV6FlashBorrower.mixedDecimals.t.sol => RaindexV6FlashBorrower.mixedDecimals.t.sol} (78%) rename test/abstract/{OrderBookV6FlashBorrower.noOrders.t.sol => RaindexV6FlashBorrower.noOrders.t.sol} (84%) rename test/abstract/{OrderBookV6FlashBorrower.realTokenTransfers.t.sol => RaindexV6FlashBorrower.realTokenTransfers.t.sol} (78%) rename test/abstract/{OrderBookV6FlashBorrower.reentrancy.t.sol => RaindexV6FlashBorrower.reentrancy.t.sol} (75%) create mode 100644 test/abstract/RaindexV6FlashLender.fee.t.sol rename test/abstract/{OrderBookV6FlashLender.griefRecipient.t.sol => RaindexV6FlashLender.griefRecipient.t.sol} (76%) rename test/abstract/{OrderBookV6FlashLender.ierc165.t.sol => RaindexV6FlashLender.ierc165.t.sol} (66%) create mode 100644 test/abstract/RaindexV6FlashLender.maxFlashLoan.t.sol rename test/abstract/{OrderBookV6FlashLender.mockSuccess.t.sol => RaindexV6FlashLender.mockSuccess.t.sol} (72%) rename test/abstract/{OrderBookV6FlashLender.reentrant.t.sol => RaindexV6FlashLender.reentrant.t.sol} (92%) rename test/abstract/{OrderBookV6FlashLender.transfers.t.sol => RaindexV6FlashLender.transfers.t.sol} (85%) rename test/concrete/arb/{GenericPoolOrderBookV6ArbOrderTaker.approvalRevoked.t.sol => GenericPoolRaindexV6ArbOrderTaker.approvalRevoked.t.sol} (87%) rename test/concrete/arb/{GenericPoolOrderBookV6ArbOrderTaker.exchangeRevert.t.sol => GenericPoolRaindexV6ArbOrderTaker.exchangeRevert.t.sol} (81%) rename test/concrete/arb/{GenericPoolOrderBookV6ArbOrderTaker.sender.t.sol => GenericPoolRaindexV6ArbOrderTaker.sender.t.sol} (79%) rename test/concrete/arb/{GenericPoolOrderBookV6FlashBorrower.approvalRevoked.t.sol => GenericPoolRaindexV6FlashBorrower.approvalRevoked.t.sol} (85%) rename test/concrete/arb/{GenericPoolOrderBookV6FlashBorrower.ethForwarded.t.sol => GenericPoolRaindexV6FlashBorrower.ethForwarded.t.sol} (87%) rename test/concrete/arb/{GenericPoolOrderBookV6FlashBorrower.exchangeRevert.t.sol => GenericPoolRaindexV6FlashBorrower.exchangeRevert.t.sol} (81%) rename test/concrete/arb/{GenericPoolOrderBookV6FlashBorrower.sender.t.sol => GenericPoolRaindexV6FlashBorrower.sender.t.sol} (81%) rename test/concrete/arb/{RouteProcessorOrderBookV6ArbOrderTaker.lossyRounding.t.sol => RouteProcessorRaindexV6ArbOrderTaker.lossyRounding.t.sol} (78%) rename test/concrete/arb/{RouteProcessorOrderBookV6ArbOrderTaker.nonStandardDecimals.t.sol => RouteProcessorRaindexV6ArbOrderTaker.nonStandardDecimals.t.sol} (80%) rename test/concrete/arb/{RouteProcessorOrderBookV6ArbOrderTaker.onTakeOrders2.t.sol => RouteProcessorRaindexV6ArbOrderTaker.onTakeOrders2.t.sol} (78%) rename test/concrete/arb/{RouteProcessorOrderBookV6ArbOrderTaker.onTakeOrders2Direct.t.sol => RouteProcessorRaindexV6ArbOrderTaker.onTakeOrders2Direct.t.sol} (77%) rename test/concrete/arb/{RouteProcessorOrderBookV6ArbOrderTaker.sender.t.sol => RouteProcessorRaindexV6ArbOrderTaker.sender.t.sol} (79%) delete mode 100644 test/concrete/ob/OrderBookV6.removeOrder.owner.t.sol rename test/concrete/ob/{OrderBookV6.addOrder.entask.t.sol => RaindexV6.addOrder.entask.t.sol} (94%) rename test/concrete/ob/{OrderBookV6.addOrder.mock.t.sol => RaindexV6.addOrder.mock.t.sol} (91%) rename test/concrete/ob/{OrderBookV6.addOrder.nonce.t.sol => RaindexV6.addOrder.nonce.t.sol} (74%) rename test/concrete/ob/{OrderBookV6.addOrder.owner.t.sol => RaindexV6.addOrder.owner.t.sol} (69%) rename test/concrete/ob/{OrderBookV6.addOrder.t.sol => RaindexV6.addOrder.t.sol} (85%) rename test/concrete/ob/{OrderBookV6.clear.badStack.t.sol => RaindexV6.clear.badStack.t.sol} (92%) rename test/concrete/ob/{OrderBookV6.clear.context.t.sol => RaindexV6.clear.context.t.sol} (94%) rename test/concrete/ob/{OrderBookV6.clear.handleIO.revert.t.sol => RaindexV6.clear.handleIO.revert.t.sol} (91%) rename test/concrete/ob/{OrderBookV6.clear.mock.t.sol => RaindexV6.clear.mock.t.sol} (96%) rename test/concrete/ob/{OrderBookV6.clear.sameOwner.t.sol => RaindexV6.clear.sameOwner.t.sol} (81%) rename test/concrete/ob/{OrderBookV6.clear.sameToken.t.sol => RaindexV6.clear.sameToken.t.sol} (80%) rename test/concrete/ob/{OrderBookV6.clear.zeroAmount.t.sol => RaindexV6.clear.zeroAmount.t.sol} (82%) rename test/concrete/ob/{OrderBookV6.deposit.entask.t.sol => RaindexV6.deposit.entask.t.sol} (88%) rename test/concrete/ob/{OrderBookV6.deposit.t.sol => RaindexV6.deposit.t.sol} (85%) rename test/concrete/ob/{OrderBookV6.entask.t.sol => RaindexV6.entask.t.sol} (86%) rename test/concrete/ob/{OrderBookV6.quote.sameToken.t.sol => RaindexV6.quote.sameToken.t.sol} (76%) rename test/concrete/ob/{OrderBookV6.quote.t.sol => RaindexV6.quote.t.sol} (94%) rename test/concrete/ob/{OrderBookV6.removeOrder.entask.t.sol => RaindexV6.removeOrder.entask.t.sol} (92%) rename test/concrete/ob/{OrderBookV6.removeOrder.mock.t.sol => RaindexV6.removeOrder.mock.t.sol} (88%) create mode 100644 test/concrete/ob/RaindexV6.removeOrder.owner.t.sol rename test/concrete/ob/{OrderBookV6.takeOrder.badStack.t.sol => RaindexV6.takeOrder.badStack.t.sol} (85%) rename test/concrete/ob/{OrderBookV6.takeOrder.exceedsMaxRatio.t.sol => RaindexV6.takeOrder.exceedsMaxRatio.t.sol} (86%) rename test/concrete/ob/{OrderBookV6.takeOrder.handleIO.revert.t.sol => RaindexV6.takeOrder.handleIO.revert.t.sol} (93%) rename test/concrete/ob/{OrderBookV6.takeOrder.maximumInput.t.sol => RaindexV6.takeOrder.maximumInput.t.sol} (95%) rename test/concrete/ob/{OrderBookV6.takeOrder.maximumOutput.t.sol => RaindexV6.takeOrder.maximumOutput.t.sol} (97%) rename test/concrete/ob/{OrderBookV6.takeOrder.minimumIO.t.sol => RaindexV6.takeOrder.minimumIO.t.sol} (85%) rename test/concrete/ob/{OrderBookV6.takeOrder.noop.t.sol => RaindexV6.takeOrder.noop.t.sol} (91%) rename test/concrete/ob/{OrderBookV6.takeOrder.precision.t.sol => RaindexV6.takeOrder.precision.t.sol} (91%) rename test/concrete/ob/{OrderBookV6.takeOrder.sameToken.t.sol => RaindexV6.takeOrder.sameToken.t.sol} (82%) rename test/concrete/ob/{OrderBookV6.takeOrder.tokenMismatch.t.sol => RaindexV6.takeOrder.tokenMismatch.t.sol} (90%) rename test/concrete/ob/{OrderBookV6.vaultBalance.t.sol => RaindexV6.vaultBalance.t.sol} (69%) rename test/concrete/ob/{OrderBookV6.withdraw.entask.t.sol => RaindexV6.withdraw.entask.t.sol} (91%) rename test/concrete/ob/{OrderBookV6.withdraw.t.sol => RaindexV6.withdraw.t.sol} (82%) delete mode 100644 test/concrete/parser/OrderBookV6SubParser.describedByMeta.t.sol rename test/concrete/parser/{OrderBookV6SubParser.contextCalculatedIORatio.t.sol => RaindexV6SubParser.contextCalculatedIORatio.t.sol} (57%) rename test/concrete/parser/{OrderBookV6SubParser.contextCalculatedMaxOutput.t.sol => RaindexV6SubParser.contextCalculatedMaxOutput.t.sol} (57%) rename test/concrete/parser/{OrderBookV6SubParser.contextInputToken.t.sol => RaindexV6SubParser.contextInputToken.t.sol} (57%) rename test/concrete/parser/{OrderBookV6SubParser.contextInputTokenDecimals.t.sol => RaindexV6SubParser.contextInputTokenDecimals.t.sol} (57%) rename test/concrete/parser/{OrderBookV6SubParser.contextInputVaultBalanceBefore.t.sol => RaindexV6SubParser.contextInputVaultBalanceBefore.t.sol} (56%) rename test/concrete/parser/{OrderBookV6SubParser.contextInputVaultBalanceIncrease.t.sol => RaindexV6SubParser.contextInputVaultBalanceIncrease.t.sol} (56%) rename test/concrete/parser/{OrderBookV6SubParser.contextInputVaultId.t.sol => RaindexV6SubParser.contextInputVaultId.t.sol} (57%) rename test/concrete/parser/{OrderBookV6SubParser.contextOrderClearer.t.sol => RaindexV6SubParser.contextOrderClearer.t.sol} (57%) rename test/concrete/parser/{OrderBookV6SubParser.contextOrderCounterparty.t.sol => RaindexV6SubParser.contextOrderCounterparty.t.sol} (57%) rename test/concrete/parser/{OrderBookV6SubParser.contextOrderHash.t.sol => RaindexV6SubParser.contextOrderHash.t.sol} (57%) rename test/concrete/parser/{OrderBookV6SubParser.contextOrderOwner.t.sol => RaindexV6SubParser.contextOrderOwner.t.sol} (57%) rename test/concrete/parser/{OrderBookV6SubParser.contextOutputToken.t.sol => RaindexV6SubParser.contextOutputToken.t.sol} (57%) rename test/concrete/parser/{OrderBookV6SubParser.contextOutputTokenDecimals.t.sol => RaindexV6SubParser.contextOutputTokenDecimals.t.sol} (57%) rename test/concrete/parser/{OrderBookV6SubParser.contextOutputVaultBalanceBefore.t.sol => RaindexV6SubParser.contextOutputVaultBalanceBefore.t.sol} (56%) rename test/concrete/parser/{OrderBookV6SubParser.contextOutputVaultBalanceDecrease.t.sol => RaindexV6SubParser.contextOutputVaultBalanceDecrease.t.sol} (56%) rename test/concrete/parser/{OrderBookV6SubParser.contextOutputVaultId.t.sol => RaindexV6SubParser.contextOutputVaultId.t.sol} (57%) rename test/concrete/parser/{OrderBookV6SubParser.contextOrderBook.t.sol => RaindexV6SubParser.contextRaindex.t.sol} (50%) create mode 100644 test/concrete/parser/RaindexV6SubParser.describedByMeta.t.sol rename test/concrete/parser/{OrderBookV6SubParser.ierc165.t.sol => RaindexV6SubParser.ierc165.t.sol} (73%) rename test/concrete/parser/{OrderBookV6SubParser.pointers.t.sol => RaindexV6SubParser.pointers.t.sol} (70%) rename test/concrete/parser/{OrderBookV6SubParser.signedContext.t.sol => RaindexV6SubParser.signedContext.t.sol} (71%) rename test/concrete/parser/{OrderBookV6SubParser.signers.t.sol => RaindexV6SubParser.signers.t.sol} (70%) rename test/lib/{LibOrderBookArb.finalizeArbNativeGas.t.sol => LibRaindexArb.finalizeArbNativeGas.t.sol} (95%) rename test/lib/{LibOrderBookArb.finalizeArbOutputTokenProfit.t.sol => LibRaindexArb.finalizeArbOutputTokenProfit.t.sol} (89%) rename test/lib/{LibOrderBookArb.finalizeArbTaskContext.t.sol => LibRaindexArb.finalizeArbTaskContext.t.sol} (95%) rename test/lib/{LibOrderBookArb.finalizeArbTokenTransfers.t.sol => LibRaindexArb.finalizeArbTokenTransfers.t.sol} (88%) delete mode 100644 test/lib/deploy/LibOrderBookDeploy.t.sol create mode 100644 test/lib/deploy/LibRaindexDeploy.t.sol rename test/lib/deploy/{LibOrderBookDeployIsStartBlockArbitrum.t.sol => LibRaindexDeployIsStartBlockArbitrum.t.sol} (69%) rename test/lib/deploy/{LibOrderBookDeployIsStartBlockBase.t.sol => LibRaindexDeployIsStartBlockBase.t.sol} (63%) rename test/lib/deploy/{LibOrderBookDeployIsStartBlockFlare.t.sol => LibRaindexDeployIsStartBlockFlare.t.sol} (63%) rename test/lib/deploy/{LibOrderBookDeployIsStartBlockPolygon.t.sol => LibRaindexDeployIsStartBlockPolygon.t.sol} (63%) rename test/lib/deploy/{LibOrderBookDeployNetworksJsonAddresses.t.sol => LibRaindexDeployNetworksJsonAddresses.t.sol} (72%) rename test/lib/deploy/{LibOrderBookDeployNetworksJsonStartBlockArbitrum.t.sol => LibRaindexDeployNetworksJsonStartBlockArbitrum.t.sol} (66%) rename test/lib/deploy/{LibOrderBookDeployNetworksJsonStartBlockBase.t.sol => LibRaindexDeployNetworksJsonStartBlockBase.t.sol} (57%) rename test/lib/deploy/{LibOrderBookDeployNetworksJsonStartBlockFlare.t.sol => LibRaindexDeployNetworksJsonStartBlockFlare.t.sol} (57%) rename test/lib/deploy/{LibOrderBookDeployNetworksJsonStartBlockPolygon.t.sol => LibRaindexDeployNetworksJsonStartBlockPolygon.t.sol} (58%) rename test/lib/deploy/{LibOrderBookDeployProd.t.sol => LibRaindexDeployProd.t.sol} (50%) rename test/lib/deploy/{LibOrderBookDeployStartBlockArbitrum.t.sol => LibRaindexDeployStartBlockArbitrum.t.sol} (64%) rename test/lib/deploy/{LibOrderBookDeployStartBlockBase.t.sol => LibRaindexDeployStartBlockBase.t.sol} (56%) rename test/lib/deploy/{LibOrderBookDeployStartBlockFlare.t.sol => LibRaindexDeployStartBlockFlare.t.sol} (56%) rename test/lib/deploy/{LibOrderBookDeployStartBlockPolygon.t.sol => LibRaindexDeployStartBlockPolygon.t.sol} (56%) rename test/lib/deploy/{LibOrderBookDeploySubgraphYamlAddress.t.sol => LibRaindexDeploySubgraphYamlAddress.t.sol} (62%) rename test/util/abstract/{GenericPoolOrderBookV6ArbOrderTakerTest.sol => GenericPoolRaindexV6ArbOrderTakerTest.sol} (53%) rename test/util/abstract/{MockOrderBookBase.sol => MockRaindexBase.sol} (94%) rename test/util/abstract/{OrderBookV6ExternalMockTest.sol => RaindexV6ExternalMockTest.sol} (82%) rename test/util/abstract/{OrderBookV6ExternalRealTest.sol => RaindexV6ExternalRealTest.sol} (83%) rename test/util/abstract/{OrderBookV6SelfTest.sol => RaindexV6SelfTest.sol} (62%) rename test/util/abstract/{OrderBookV6SubParserContextTest.sol => RaindexV6SubParserContextTest.sol} (68%) rename test/util/abstract/{RouteProcessorOrderBookV6ArbOrderTakerTest.sol => RouteProcessorRaindexV6ArbOrderTakerTest.sol} (53%) rename test/util/concrete/{ChildOrderBookV6ArbOrderTaker.sol => ChildRaindexV6ArbOrderTaker.sol} (62%) rename test/util/concrete/{ChildOrderBookV6ArbTaskGated.sol => ChildRaindexV6ArbTaskGated.sol} (63%) rename test/util/concrete/{FlashLendingMockOrderBook.sol => FlashLendingMockRaindex.sol} (97%) rename test/util/concrete/{MaliciousOrderBook.sol => MaliciousRaindex.sol} (85%) rename test/util/concrete/{RealisticFlashLendingMockOrderBook.sol => RealisticFlashLendingMockRaindex.sol} (89%) rename test/util/concrete/{RealisticOrderTakerMockOrderBook.sol => RealisticOrderTakerMockRaindex.sol} (89%) rename test/util/concrete/{ReentrantMockOrderBook.sol => ReentrantMockRaindex.sol} (84%) rename test/util/fixture/{LibOrderBookSubParserContextFixture.sol => LibRaindexSubParserContextFixture.sol} (97%) delete mode 100644 test/util/lib/LibEtchOrderBook.sol create mode 100644 test/util/lib/LibEtchRaindex.sol diff --git a/test/abstract/OrderBookV6FlashLender.fee.t.sol b/test/abstract/OrderBookV6FlashLender.fee.t.sol deleted file mode 100644 index 7d5e57be45..0000000000 --- a/test/abstract/OrderBookV6FlashLender.fee.t.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity =0.8.25; - -import {OrderBookV6ExternalMockTest} from "test/util/abstract/OrderBookV6ExternalMockTest.sol"; - -/// @title OrderBookV6FlashLenderFeeTest -/// Tests the fee charged by `OrderBookV6FlashLender`. -contract OrderBookV6FlashLenderFeeTest is OrderBookV6ExternalMockTest { - /// Tests that the fee charged by `OrderBookV6FlashLender` is 0. - function testFlashFee(address token, uint256 amount) public view { - assertEq(iOrderbook.flashFee(token, amount), 0); - } -} diff --git a/test/abstract/OrderBookV6FlashLender.maxFlashLoan.t.sol b/test/abstract/OrderBookV6FlashLender.maxFlashLoan.t.sol deleted file mode 100644 index a7fd76e14f..0000000000 --- a/test/abstract/OrderBookV6FlashLender.maxFlashLoan.t.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity =0.8.25; - -import {OrderBookV6ExternalMockTest} from "test/util/abstract/OrderBookV6ExternalMockTest.sol"; -import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; - -/// @title OrderBookV6FlashLenderMaxFlashLoanTest -/// Tests the maximum flash loan amount for `OrderBookV6FlashLender`. -contract OrderBookV6FlashLenderMaxFlashLoanTest is OrderBookV6ExternalMockTest { - /// Tests that the maximum flash loan amount for `OrderBookV6FlashLender` is - /// the balance of the token in the order book. - function testFlashMaxLoan(uint256 amount) public { - vm.mockCall( - address(iToken0), abi.encodeWithSelector(IERC20.balanceOf.selector, address(iOrderbook)), abi.encode(amount) - ); - assertEq(iOrderbook.maxFlashLoan(address(iToken0)), amount); - } -} diff --git a/test/abstract/OrderBookV6ArbCommon.fallback.t.sol b/test/abstract/RaindexV6ArbCommon.fallback.t.sol similarity index 82% rename from test/abstract/OrderBookV6ArbCommon.fallback.t.sol rename to test/abstract/RaindexV6ArbCommon.fallback.t.sol index 234bb8ebc1..b68a46e6a7 100644 --- a/test/abstract/OrderBookV6ArbCommon.fallback.t.sol +++ b/test/abstract/RaindexV6ArbCommon.fallback.t.sol @@ -2,13 +2,13 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {GenericPoolOrderBookV6ArbOrderTakerTest} from "test/util/abstract/GenericPoolOrderBookV6ArbOrderTakerTest.sol"; -import {GenericPoolOrderBookV6ArbOrderTaker} from "../../src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol"; +import {GenericPoolRaindexV6ArbOrderTakerTest} from "test/util/abstract/GenericPoolRaindexV6ArbOrderTakerTest.sol"; +import {GenericPoolRaindexV6ArbOrderTaker} from "../../src/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.sol"; import {ArbTest} from "test/util/abstract/ArbTest.sol"; -import {GenericPoolOrderBookV6FlashBorrower} from "../../src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol"; +import {GenericPoolRaindexV6FlashBorrower} from "../../src/concrete/arb/GenericPoolRaindexV6FlashBorrower.sol"; /// @dev Tests fallback behavior on the order taker arb contract. -contract OrderBookV6ArbOrderTakerFallbackTest is GenericPoolOrderBookV6ArbOrderTakerTest { +contract RaindexV6ArbOrderTakerFallbackTest is GenericPoolRaindexV6ArbOrderTakerTest { /// The fallback MUST accept calldata that does not match any selector. function testFallbackAcceptsCalldata() external { // 0xdeadbeef does not match any function selector on the arb contracts. @@ -38,9 +38,9 @@ contract OrderBookV6ArbOrderTakerFallbackTest is GenericPoolOrderBookV6ArbOrderT } /// @dev Tests fallback behavior on the flash borrower arb contract. -contract OrderBookV6FlashBorrowerFallbackTest is ArbTest { +contract RaindexV6FlashBorrowerFallbackTest is ArbTest { function buildArb() internal override returns (address payable) { - return payable(address(new GenericPoolOrderBookV6FlashBorrower())); + return payable(address(new GenericPoolRaindexV6FlashBorrower())); } constructor() ArbTest() {} diff --git a/test/abstract/OrderBookV6ArbOrderTaker.context.t.sol b/test/abstract/RaindexV6ArbOrderTaker.context.t.sol similarity index 89% rename from test/abstract/OrderBookV6ArbOrderTaker.context.t.sol rename to test/abstract/RaindexV6ArbOrderTaker.context.t.sol index 3f414fdd9c..5d73f91d79 100644 --- a/test/abstract/OrderBookV6ArbOrderTaker.context.t.sol +++ b/test/abstract/RaindexV6ArbOrderTaker.context.t.sol @@ -2,9 +2,9 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {ChildOrderBookV6ArbOrderTaker} from "../util/concrete/ChildOrderBookV6ArbOrderTaker.sol"; +import {ChildRaindexV6ArbOrderTaker} from "../util/concrete/ChildRaindexV6ArbOrderTaker.sol"; import {TaskV2, SignedContextV1, EvaluableV4} from "rain.raindex.interface/interface/IRaindexV6.sol"; -import {OrderBookV6ExternalRealTest} from "../util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest} from "../util/abstract/RaindexV6ExternalRealTest.sol"; import { TakeOrdersConfigV5, TakeOrderConfigV4, @@ -15,14 +15,14 @@ import { } from "rain.raindex.interface/interface/IRaindexV6.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {StateNamespace, LibNamespace} from "../../src/concrete/ob/OrderBookV6.sol"; +import {StateNamespace, LibNamespace} from "../../src/concrete/ob/RaindexV6.sol"; import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; -contract OrderBookV6ArbOrderTakerContextTest is OrderBookV6ExternalRealTest { - function testOrderBookV6ArbOrderTakerContext() external { +contract RaindexV6ArbOrderTakerContextTest is RaindexV6ExternalRealTest { + function testRaindexV6ArbOrderTakerContext() external { address alice = address(999999); address bob = address(999998); - ChildOrderBookV6ArbOrderTaker arbOrderTaker = new ChildOrderBookV6ArbOrderTaker(); + ChildRaindexV6ArbOrderTaker arbOrderTaker = new ChildRaindexV6ArbOrderTaker(); OrderConfigV4 memory aliceOrderConfig; { IOV2[] memory aliceValidInputs = new IOV2[](1); @@ -101,6 +101,6 @@ contract OrderBookV6ArbOrderTakerContextTest is OrderBookV6ExternalRealTest { // 5e18 is 5 eth as wei is 18 decimals. vm.deal(address(arbOrderTaker), 5e18); vm.prank(bob); - arbOrderTaker.arb5(iOrderbook, takeOrdersConfig, task); + arbOrderTaker.arb5(iRaindex, takeOrdersConfig, task); } } diff --git a/test/abstract/OrderBookV6ArbOrderTaker.ierc165.t.sol b/test/abstract/RaindexV6ArbOrderTaker.ierc165.t.sol similarity index 77% rename from test/abstract/OrderBookV6ArbOrderTaker.ierc165.t.sol rename to test/abstract/RaindexV6ArbOrderTaker.ierc165.t.sol index 5e90148105..459296413d 100644 --- a/test/abstract/OrderBookV6ArbOrderTaker.ierc165.t.sol +++ b/test/abstract/RaindexV6ArbOrderTaker.ierc165.t.sol @@ -6,17 +6,17 @@ import {Test} from "forge-std/Test.sol"; import {IERC165} from "openzeppelin-contracts/contracts/utils/introspection/IERC165.sol"; import {IRaindexV6ArbOrderTaker} from "rain.raindex.interface/interface/IRaindexV6ArbOrderTaker.sol"; import {IRaindexV6OrderTaker} from "rain.raindex.interface/interface/IRaindexV6OrderTaker.sol"; -import {ChildOrderBookV6ArbOrderTaker} from "../util/concrete/ChildOrderBookV6ArbOrderTaker.sol"; +import {ChildRaindexV6ArbOrderTaker} from "../util/concrete/ChildRaindexV6ArbOrderTaker.sol"; -contract OrderBookV6ArbOrderTakerIERC165Test is Test { +contract RaindexV6ArbOrderTakerIERC165Test is Test { /// Test that ERC165 and IRaindexV6ArbOrderTaker are supported interfaces /// as per ERC165. - function testOrderBookV6ArbOrderTakerIERC165(bytes4 badInterfaceId) external { + function testRaindexV6ArbOrderTakerIERC165(bytes4 badInterfaceId) external { vm.assume(badInterfaceId != type(IERC165).interfaceId); vm.assume(badInterfaceId != type(IRaindexV6ArbOrderTaker).interfaceId); vm.assume(badInterfaceId != type(IRaindexV6OrderTaker).interfaceId); - ChildOrderBookV6ArbOrderTaker arbOrderTaker = new ChildOrderBookV6ArbOrderTaker(); + ChildRaindexV6ArbOrderTaker arbOrderTaker = new ChildRaindexV6ArbOrderTaker(); assertTrue(arbOrderTaker.supportsInterface(type(IERC165).interfaceId)); assertTrue(arbOrderTaker.supportsInterface(type(IRaindexV6ArbOrderTaker).interfaceId)); assertTrue(arbOrderTaker.supportsInterface(type(IRaindexV6OrderTaker).interfaceId)); diff --git a/test/abstract/OrderBookV6ArbOrderTaker.noOrders.t.sol b/test/abstract/RaindexV6ArbOrderTaker.noOrders.t.sol similarity index 79% rename from test/abstract/OrderBookV6ArbOrderTaker.noOrders.t.sol rename to test/abstract/RaindexV6ArbOrderTaker.noOrders.t.sol index 99236fbd5d..4654b6d46a 100644 --- a/test/abstract/OrderBookV6ArbOrderTaker.noOrders.t.sol +++ b/test/abstract/RaindexV6ArbOrderTaker.noOrders.t.sol @@ -2,9 +2,9 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {GenericPoolOrderBookV6ArbOrderTakerTest} from "test/util/abstract/GenericPoolOrderBookV6ArbOrderTakerTest.sol"; +import {GenericPoolRaindexV6ArbOrderTakerTest} from "test/util/abstract/GenericPoolRaindexV6ArbOrderTakerTest.sol"; -import {GenericPoolOrderBookV6ArbOrderTaker} from "../../src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol"; +import {GenericPoolRaindexV6ArbOrderTaker} from "../../src/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.sol"; import { IRaindexV6, EvaluableV4, @@ -18,15 +18,15 @@ import { import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibInterpreterDeploy} from "rain.interpreter/lib/deploy/LibInterpreterDeploy.sol"; -contract OrderBookV6ArbOrderTakerNoOrdersTest is GenericPoolOrderBookV6ArbOrderTakerTest { +contract RaindexV6ArbOrderTakerNoOrdersTest is GenericPoolRaindexV6ArbOrderTakerTest { /// arb5 MUST revert with NoOrders when given an empty orders array. function testArb5NoOrders() external { TakeOrderConfigV4[] memory orders = new TakeOrderConfigV4[](0); vm.expectRevert(abi.encodeWithSelector(IRaindexV6.NoOrders.selector)); - GenericPoolOrderBookV6ArbOrderTaker(iArb) + GenericPoolRaindexV6ArbOrderTaker(iArb) .arb5( - iOrderBook, + iRaindex, TakeOrdersConfigV5({ minimumIO: LibDecimalFloat.packLossless(0, 0), maximumIO: LibDecimalFloat.packLossless(type(int224).max, 0), diff --git a/test/abstract/OrderBookV6ArbOrderTaker.onTakeOrders2.t.sol b/test/abstract/RaindexV6ArbOrderTaker.onTakeOrders2.t.sol similarity index 84% rename from test/abstract/OrderBookV6ArbOrderTaker.onTakeOrders2.t.sol rename to test/abstract/RaindexV6ArbOrderTaker.onTakeOrders2.t.sol index e292b9c74f..27372c3ac8 100644 --- a/test/abstract/OrderBookV6ArbOrderTaker.onTakeOrders2.t.sol +++ b/test/abstract/RaindexV6ArbOrderTaker.onTakeOrders2.t.sol @@ -5,7 +5,7 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import {GenericPoolOrderBookV6ArbOrderTaker} from "../../src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol"; +import {GenericPoolRaindexV6ArbOrderTaker} from "../../src/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.sol"; import { IRaindexV6, TakeOrdersConfigV5, @@ -24,9 +24,9 @@ import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; import {LibTOFUTokenDecimals} from "rain.tofu.erc20-decimals/lib/LibTOFUTokenDecimals.sol"; import {MockToken} from "test/util/concrete/MockToken.sol"; import {MockExchange} from "test/util/concrete/MockExchange.sol"; -import {RealisticOrderTakerMockOrderBook} from "test/util/concrete/RealisticOrderTakerMockOrderBook.sol"; +import {RealisticOrderTakerMockRaindex} from "test/util/concrete/RealisticOrderTakerMockRaindex.sol"; -contract OrderBookV6ArbOrderTakerOnTakeOrders2Test is Test { +contract RaindexV6ArbOrderTakerOnTakeOrders2Test is Test { /// arb5 completes a full order-taker cycle with real ERC20 transfers: /// takeOrders, onTakeOrders2 callback with exchange, and finalize. function testArb5RealTokenTransfers() external { @@ -36,13 +36,13 @@ contract OrderBookV6ArbOrderTakerOnTakeOrders2Test is Test { MockToken inputToken = new MockToken("Input", "IN", 18); MockToken outputToken = new MockToken("Output", "OUT", 18); - RealisticOrderTakerMockOrderBook orderBook = new RealisticOrderTakerMockOrderBook(100e18); + RealisticOrderTakerMockRaindex raindex = new RealisticOrderTakerMockRaindex(100e18); MockExchange exchange = new MockExchange(); - outputToken.mint(address(orderBook), 100e18); + outputToken.mint(address(raindex), 100e18); inputToken.mint(address(exchange), 100e18); - GenericPoolOrderBookV6ArbOrderTaker arb = new GenericPoolOrderBookV6ArbOrderTaker(); + GenericPoolRaindexV6ArbOrderTaker arb = new GenericPoolRaindexV6ArbOrderTaker(); IOV2[] memory validInputs = new IOV2[](1); validInputs[0] = IOV2(address(inputToken), bytes32(0)); @@ -67,7 +67,7 @@ contract OrderBookV6ArbOrderTakerOnTakeOrders2Test is Test { ); arb.arb5( - IRaindexV6(address(orderBook)), + IRaindexV6(address(raindex)), TakeOrdersConfigV5({ minimumIO: LibDecimalFloat.packLossless(100, 0), maximumIO: LibDecimalFloat.packLossless(type(int224).max, 0), @@ -83,7 +83,7 @@ contract OrderBookV6ArbOrderTakerOnTakeOrders2Test is Test { ); // OB received all inputToken from arb. - assertEq(inputToken.balanceOf(address(orderBook)), 100e18); + assertEq(inputToken.balanceOf(address(raindex)), 100e18); // Exchange received all outputToken from arb. assertEq(outputToken.balanceOf(address(exchange)), 100e18); // Arb contract has no remaining tokens. diff --git a/test/abstract/OrderBookV6ArbOrderTaker.onTakeOrders2Direct.t.sol b/test/abstract/RaindexV6ArbOrderTaker.onTakeOrders2Direct.t.sol similarity index 85% rename from test/abstract/OrderBookV6ArbOrderTaker.onTakeOrders2Direct.t.sol rename to test/abstract/RaindexV6ArbOrderTaker.onTakeOrders2Direct.t.sol index 9127040d8a..342debc540 100644 --- a/test/abstract/OrderBookV6ArbOrderTaker.onTakeOrders2Direct.t.sol +++ b/test/abstract/RaindexV6ArbOrderTaker.onTakeOrders2Direct.t.sol @@ -4,13 +4,13 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; -import {GenericPoolOrderBookV6ArbOrderTaker} from "../../src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol"; +import {GenericPoolRaindexV6ArbOrderTaker} from "../../src/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.sol"; import {Float} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; import {LibTOFUTokenDecimals} from "rain.tofu.erc20-decimals/lib/LibTOFUTokenDecimals.sol"; import {MockToken} from "test/util/concrete/MockToken.sol"; -contract OrderBookV6ArbOrderTakerOnTakeOrders2DirectTest is Test { +contract RaindexV6ArbOrderTakerOnTakeOrders2DirectTest is Test { /// Calling onTakeOrders2 directly MUST succeed (no-op) and not modify /// any state. Anyone can call it — there is no access control by design. function testOnTakeOrders2DirectCallSucceeds() external { @@ -20,7 +20,7 @@ contract OrderBookV6ArbOrderTakerOnTakeOrders2DirectTest is Test { MockToken tokenA = new MockToken("A", "A", 18); MockToken tokenB = new MockToken("B", "B", 18); - GenericPoolOrderBookV6ArbOrderTaker arb = new GenericPoolOrderBookV6ArbOrderTaker(); + GenericPoolRaindexV6ArbOrderTaker arb = new GenericPoolRaindexV6ArbOrderTaker(); // Call from an arbitrary address — should not revert. // takeOrdersData is abi.encode(spender, pool, encodedFunctionCall). diff --git a/test/abstract/OrderBookV6ArbOrderTaker.reentrancy.t.sol b/test/abstract/RaindexV6ArbOrderTaker.reentrancy.t.sol similarity index 83% rename from test/abstract/OrderBookV6ArbOrderTaker.reentrancy.t.sol rename to test/abstract/RaindexV6ArbOrderTaker.reentrancy.t.sol index d063cf00c0..341210eabc 100644 --- a/test/abstract/OrderBookV6ArbOrderTaker.reentrancy.t.sol +++ b/test/abstract/RaindexV6ArbOrderTaker.reentrancy.t.sol @@ -4,7 +4,7 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; -import {GenericPoolOrderBookV6ArbOrderTaker} from "../../src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol"; +import {GenericPoolRaindexV6ArbOrderTaker} from "../../src/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.sol"; import { IRaindexV6, TakeOrdersConfigV5, @@ -21,9 +21,9 @@ import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; import {LibTOFUTokenDecimals} from "rain.tofu.erc20-decimals/lib/LibTOFUTokenDecimals.sol"; import {MockToken} from "test/util/concrete/MockToken.sol"; -import {ReentrantMockOrderBook} from "test/util/concrete/ReentrantMockOrderBook.sol"; +import {ReentrantMockRaindex} from "test/util/concrete/ReentrantMockRaindex.sol"; -contract OrderBookV6ArbOrderTakerReentrancyTest is Test { +contract RaindexV6ArbOrderTakerReentrancyTest is Test { /// arb5 MUST revert when re-entered via the takeOrders4 callback. function testArb5Reentrancy() external { LibRainDeploy.etchZoltuFactory(vm); @@ -32,10 +32,10 @@ contract OrderBookV6ArbOrderTakerReentrancyTest is Test { MockToken inputToken = new MockToken("Input", "IN", 18); MockToken outputToken = new MockToken("Output", "OUT", 18); - ReentrantMockOrderBook orderBook = new ReentrantMockOrderBook(); - outputToken.mint(address(orderBook), 100e18); + ReentrantMockRaindex raindex = new ReentrantMockRaindex(); + outputToken.mint(address(raindex), 100e18); - GenericPoolOrderBookV6ArbOrderTaker arb = new GenericPoolOrderBookV6ArbOrderTaker(); + GenericPoolRaindexV6ArbOrderTaker arb = new GenericPoolRaindexV6ArbOrderTaker(); IOV2[] memory validInputs = new IOV2[](1); validInputs[0] = IOV2(address(inputToken), bytes32(0)); @@ -55,7 +55,7 @@ contract OrderBookV6ArbOrderTakerReentrancyTest is Test { vm.expectRevert(abi.encodeWithSelector(bytes4(keccak256("ReentrancyGuardReentrantCall()")))); arb.arb5( - IRaindexV6(address(orderBook)), + IRaindexV6(address(raindex)), TakeOrdersConfigV5({ minimumIO: LibDecimalFloat.packLossless(100, 0), maximumIO: LibDecimalFloat.packLossless(type(int224).max, 0), diff --git a/test/abstract/OrderBookV6ArbTaskGated.checkTaskHashPassMatch.t.sol b/test/abstract/RaindexV6ArbTaskGated.checkTaskHashPassMatch.t.sol similarity index 76% rename from test/abstract/OrderBookV6ArbTaskGated.checkTaskHashPassMatch.t.sol rename to test/abstract/RaindexV6ArbTaskGated.checkTaskHashPassMatch.t.sol index 3084b0db50..2d9d952e22 100644 --- a/test/abstract/OrderBookV6ArbTaskGated.checkTaskHashPassMatch.t.sol +++ b/test/abstract/RaindexV6ArbTaskGated.checkTaskHashPassMatch.t.sol @@ -3,15 +3,15 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; -import {ChildOrderBookV6ArbTaskGated} from "test/util/concrete/ChildOrderBookV6ArbTaskGated.sol"; -import {OrderBookV6ArbConfig} from "../../src/abstract/OrderBookV6ArbCommon.sol"; +import {ChildRaindexV6ArbTaskGated} from "test/util/concrete/ChildRaindexV6ArbTaskGated.sol"; +import {RaindexV6ArbConfig} from "../../src/abstract/RaindexV6ArbCommon.sol"; import {TaskV2, EvaluableV4, SignedContextV1} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {IInterpreterV4} from "rain.interpreter.interface/interface/IInterpreterV4.sol"; import {IInterpreterStoreV3} from "rain.interpreter.interface/interface/IInterpreterStoreV3.sol"; import {LibInterpreterDeploy} from "rain.interpreter/lib/deploy/LibInterpreterDeploy.sol"; /// _checkTaskHash MUST pass when the runtime task matches the configured task. -contract OrderBookV6ArbTaskGatedCheckTaskHashPassMatchTest is Test { +contract RaindexV6ArbTaskGatedCheckTaskHashPassMatchTest is Test { function testCheckTaskHashPassesWhenMatch(bytes memory bytecode) external { vm.assume(bytecode.length > 0); @@ -23,7 +23,7 @@ contract OrderBookV6ArbTaskGatedCheckTaskHashPassMatchTest is Test { ), new SignedContextV1[](0) ); - ChildOrderBookV6ArbTaskGated child = new ChildOrderBookV6ArbTaskGated(OrderBookV6ArbConfig(task)); + ChildRaindexV6ArbTaskGated child = new ChildRaindexV6ArbTaskGated(RaindexV6ArbConfig(task)); // Same task should pass. child.checkTaskHash(task); diff --git a/test/abstract/OrderBookV6ArbTaskGated.checkTaskHashPassZero.t.sol b/test/abstract/RaindexV6ArbTaskGated.checkTaskHashPassZero.t.sol similarity index 81% rename from test/abstract/OrderBookV6ArbTaskGated.checkTaskHashPassZero.t.sol rename to test/abstract/RaindexV6ArbTaskGated.checkTaskHashPassZero.t.sol index 5e2a90348d..b44a52ba6e 100644 --- a/test/abstract/OrderBookV6ArbTaskGated.checkTaskHashPassZero.t.sol +++ b/test/abstract/RaindexV6ArbTaskGated.checkTaskHashPassZero.t.sol @@ -3,8 +3,8 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; -import {ChildOrderBookV6ArbTaskGated} from "test/util/concrete/ChildOrderBookV6ArbTaskGated.sol"; -import {OrderBookV6ArbConfig} from "../../src/abstract/OrderBookV6ArbCommon.sol"; +import {ChildRaindexV6ArbTaskGated} from "test/util/concrete/ChildRaindexV6ArbTaskGated.sol"; +import {RaindexV6ArbConfig} from "../../src/abstract/RaindexV6ArbCommon.sol"; import {TaskV2, EvaluableV4, SignedContextV1} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {IInterpreterV4} from "rain.interpreter.interface/interface/IInterpreterV4.sol"; import {IInterpreterStoreV3} from "rain.interpreter.interface/interface/IInterpreterStoreV3.sol"; @@ -12,7 +12,7 @@ import {LibInterpreterDeploy} from "rain.interpreter/lib/deploy/LibInterpreterDe /// _checkTaskHash MUST pass through when iTaskHash is zero, regardless of /// the task provided at runtime. -contract OrderBookV6ArbTaskGatedCheckTaskHashPassZeroTest is Test { +contract RaindexV6ArbTaskGatedCheckTaskHashPassZeroTest is Test { function testCheckTaskHashPassesWhenZero(bytes memory runtimeBytecode) external { // Construct with empty bytecode so iTaskHash == 0. TaskV2 memory constructTask = TaskV2( @@ -23,7 +23,7 @@ contract OrderBookV6ArbTaskGatedCheckTaskHashPassZeroTest is Test { ), new SignedContextV1[](0) ); - ChildOrderBookV6ArbTaskGated child = new ChildOrderBookV6ArbTaskGated(OrderBookV6ArbConfig(constructTask)); + ChildRaindexV6ArbTaskGated child = new ChildRaindexV6ArbTaskGated(RaindexV6ArbConfig(constructTask)); // Any runtime task should pass. TaskV2 memory runtimeTask = TaskV2( diff --git a/test/abstract/OrderBookV6ArbTaskGated.checkTaskHashWrongTask.t.sol b/test/abstract/RaindexV6ArbTaskGated.checkTaskHashWrongTask.t.sol similarity index 83% rename from test/abstract/OrderBookV6ArbTaskGated.checkTaskHashWrongTask.t.sol rename to test/abstract/RaindexV6ArbTaskGated.checkTaskHashWrongTask.t.sol index f53cc72900..2ac7ec871e 100644 --- a/test/abstract/OrderBookV6ArbTaskGated.checkTaskHashWrongTask.t.sol +++ b/test/abstract/RaindexV6ArbTaskGated.checkTaskHashWrongTask.t.sol @@ -3,8 +3,8 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; -import {ChildOrderBookV6ArbTaskGated} from "test/util/concrete/ChildOrderBookV6ArbTaskGated.sol"; -import {OrderBookV6ArbConfig, WrongTask} from "../../src/abstract/OrderBookV6ArbCommon.sol"; +import {ChildRaindexV6ArbTaskGated} from "test/util/concrete/ChildRaindexV6ArbTaskGated.sol"; +import {RaindexV6ArbConfig, WrongTask} from "../../src/abstract/RaindexV6ArbCommon.sol"; import {TaskV2, EvaluableV4, SignedContextV1} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {IInterpreterV4} from "rain.interpreter.interface/interface/IInterpreterV4.sol"; import {IInterpreterStoreV3} from "rain.interpreter.interface/interface/IInterpreterStoreV3.sol"; @@ -12,7 +12,7 @@ import {LibInterpreterDeploy} from "rain.interpreter/lib/deploy/LibInterpreterDe /// _checkTaskHash MUST revert with WrongTask when iTaskHash is nonzero and /// the runtime task does not match. -contract OrderBookV6ArbTaskGatedCheckTaskHashWrongTaskTest is Test { +contract RaindexV6ArbTaskGatedCheckTaskHashWrongTaskTest is Test { function testCheckTaskHashRevertsWrongTask(bytes memory constructBytecode, bytes memory runtimeBytecode) external { vm.assume(constructBytecode.length > 0); vm.assume(runtimeBytecode.length > 0); @@ -37,7 +37,7 @@ contract OrderBookV6ArbTaskGatedCheckTaskHashWrongTaskTest is Test { // Only revert when the tasks are actually different. vm.assume(keccak256(abi.encode(constructTask)) != keccak256(abi.encode(runtimeTask))); - ChildOrderBookV6ArbTaskGated child = new ChildOrderBookV6ArbTaskGated(OrderBookV6ArbConfig(constructTask)); + ChildRaindexV6ArbTaskGated child = new ChildRaindexV6ArbTaskGated(RaindexV6ArbConfig(constructTask)); vm.expectRevert(abi.encodeWithSelector(WrongTask.selector)); child.checkTaskHash(runtimeTask); diff --git a/test/abstract/OrderBookV6ArbTaskGated.construct.t.sol b/test/abstract/RaindexV6ArbTaskGated.construct.t.sol similarity index 70% rename from test/abstract/OrderBookV6ArbTaskGated.construct.t.sol rename to test/abstract/RaindexV6ArbTaskGated.construct.t.sol index 1ca61e03d9..b271acfef5 100644 --- a/test/abstract/OrderBookV6ArbTaskGated.construct.t.sol +++ b/test/abstract/RaindexV6ArbTaskGated.construct.t.sol @@ -3,15 +3,15 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; -import {ChildOrderBookV6ArbTaskGated} from "test/util/concrete/ChildOrderBookV6ArbTaskGated.sol"; -import {OrderBookV6ArbConfig, OrderBookV6ArbCommon} from "../../src/abstract/OrderBookV6ArbCommon.sol"; +import {ChildRaindexV6ArbTaskGated} from "test/util/concrete/ChildRaindexV6ArbTaskGated.sol"; +import {RaindexV6ArbConfig, RaindexV6ArbCommon} from "../../src/abstract/RaindexV6ArbCommon.sol"; import {TaskV2, EvaluableV4, SignedContextV1} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {IInterpreterV4} from "rain.interpreter.interface/interface/IInterpreterV4.sol"; import {IInterpreterStoreV3} from "rain.interpreter.interface/interface/IInterpreterStoreV3.sol"; import {LibInterpreterDeploy} from "rain.interpreter/lib/deploy/LibInterpreterDeploy.sol"; /// Construction MUST emit the Construct event with the sender and config. -contract OrderBookV6ArbTaskGatedConstructTest is Test { +contract RaindexV6ArbTaskGatedConstructTest is Test { function testConstructEmitsEvent(bytes memory bytecode) external { TaskV2 memory task = TaskV2( EvaluableV4( @@ -21,10 +21,10 @@ contract OrderBookV6ArbTaskGatedConstructTest is Test { ), new SignedContextV1[](0) ); - OrderBookV6ArbConfig memory config = OrderBookV6ArbConfig(task); + RaindexV6ArbConfig memory config = RaindexV6ArbConfig(task); vm.expectEmit(false, false, false, true); - emit OrderBookV6ArbCommon.Construct(address(this), config); - new ChildOrderBookV6ArbTaskGated(config); + emit RaindexV6ArbCommon.Construct(address(this), config); + new ChildRaindexV6ArbTaskGated(config); } } diff --git a/test/abstract/OrderBookV6ArbTaskGated.iTaskHashNonzero.t.sol b/test/abstract/RaindexV6ArbTaskGated.iTaskHashNonzero.t.sol similarity index 77% rename from test/abstract/OrderBookV6ArbTaskGated.iTaskHashNonzero.t.sol rename to test/abstract/RaindexV6ArbTaskGated.iTaskHashNonzero.t.sol index f77995631e..2956fd2945 100644 --- a/test/abstract/OrderBookV6ArbTaskGated.iTaskHashNonzero.t.sol +++ b/test/abstract/RaindexV6ArbTaskGated.iTaskHashNonzero.t.sol @@ -3,8 +3,8 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; -import {ChildOrderBookV6ArbTaskGated} from "test/util/concrete/ChildOrderBookV6ArbTaskGated.sol"; -import {OrderBookV6ArbConfig} from "../../src/abstract/OrderBookV6ArbCommon.sol"; +import {ChildRaindexV6ArbTaskGated} from "test/util/concrete/ChildRaindexV6ArbTaskGated.sol"; +import {RaindexV6ArbConfig} from "../../src/abstract/RaindexV6ArbCommon.sol"; import {TaskV2, EvaluableV4, SignedContextV1} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {IInterpreterV4} from "rain.interpreter.interface/interface/IInterpreterV4.sol"; import {IInterpreterStoreV3} from "rain.interpreter.interface/interface/IInterpreterStoreV3.sol"; @@ -12,7 +12,7 @@ import {LibInterpreterDeploy} from "rain.interpreter/lib/deploy/LibInterpreterDe /// When constructed with non-empty bytecode the task hash MUST be the /// keccak256 of the abi-encoded task. -contract OrderBookV6ArbTaskGatedITaskHashNonzeroTest is Test { +contract RaindexV6ArbTaskGatedITaskHashNonzeroTest is Test { function testITaskHashNonzeroBytecode(bytes memory bytecode) external { vm.assume(bytecode.length > 0); @@ -24,7 +24,7 @@ contract OrderBookV6ArbTaskGatedITaskHashNonzeroTest is Test { ), new SignedContextV1[](0) ); - ChildOrderBookV6ArbTaskGated child = new ChildOrderBookV6ArbTaskGated(OrderBookV6ArbConfig(task)); + ChildRaindexV6ArbTaskGated child = new ChildRaindexV6ArbTaskGated(RaindexV6ArbConfig(task)); assertEq(child.iTaskHash(), keccak256(abi.encode(task))); } } diff --git a/test/abstract/OrderBookV6ArbTaskGated.iTaskHashZero.t.sol b/test/abstract/RaindexV6ArbTaskGated.iTaskHashZero.t.sol similarity index 75% rename from test/abstract/OrderBookV6ArbTaskGated.iTaskHashZero.t.sol rename to test/abstract/RaindexV6ArbTaskGated.iTaskHashZero.t.sol index d67e85a9df..b0779eff55 100644 --- a/test/abstract/OrderBookV6ArbTaskGated.iTaskHashZero.t.sol +++ b/test/abstract/RaindexV6ArbTaskGated.iTaskHashZero.t.sol @@ -3,15 +3,15 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; -import {ChildOrderBookV6ArbTaskGated} from "test/util/concrete/ChildOrderBookV6ArbTaskGated.sol"; -import {OrderBookV6ArbConfig} from "../../src/abstract/OrderBookV6ArbCommon.sol"; +import {ChildRaindexV6ArbTaskGated} from "test/util/concrete/ChildRaindexV6ArbTaskGated.sol"; +import {RaindexV6ArbConfig} from "../../src/abstract/RaindexV6ArbCommon.sol"; import {TaskV2, EvaluableV4, SignedContextV1} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {IInterpreterV4} from "rain.interpreter.interface/interface/IInterpreterV4.sol"; import {IInterpreterStoreV3} from "rain.interpreter.interface/interface/IInterpreterStoreV3.sol"; import {LibInterpreterDeploy} from "rain.interpreter/lib/deploy/LibInterpreterDeploy.sol"; /// When constructed with empty bytecode the task hash MUST be zero. -contract OrderBookV6ArbTaskGatedITaskHashZeroTest is Test { +contract RaindexV6ArbTaskGatedITaskHashZeroTest is Test { function testITaskHashZeroEmptyBytecode() external { TaskV2 memory task = TaskV2( EvaluableV4( @@ -21,7 +21,7 @@ contract OrderBookV6ArbTaskGatedITaskHashZeroTest is Test { ), new SignedContextV1[](0) ); - ChildOrderBookV6ArbTaskGated child = new ChildOrderBookV6ArbTaskGated(OrderBookV6ArbConfig(task)); + ChildRaindexV6ArbTaskGated child = new ChildRaindexV6ArbTaskGated(RaindexV6ArbConfig(task)); assertEq(child.iTaskHash(), bytes32(0)); } } diff --git a/test/abstract/OrderBookV6FlashBorrower.badInitiator.t.sol b/test/abstract/RaindexV6FlashBorrower.badInitiator.t.sol similarity index 55% rename from test/abstract/OrderBookV6FlashBorrower.badInitiator.t.sol rename to test/abstract/RaindexV6FlashBorrower.badInitiator.t.sol index 2ea7748bbd..71759c20e6 100644 --- a/test/abstract/OrderBookV6FlashBorrower.badInitiator.t.sol +++ b/test/abstract/RaindexV6FlashBorrower.badInitiator.t.sol @@ -4,15 +4,15 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; -import {GenericPoolOrderBookV6FlashBorrower} from "../../src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol"; -import {BadInitiator} from "../../src/abstract/OrderBookV6FlashBorrower.sol"; -import {LibOrderBookDeploy} from "../../src/lib/deploy/LibOrderBookDeploy.sol"; +import {GenericPoolRaindexV6FlashBorrower} from "../../src/concrete/arb/GenericPoolRaindexV6FlashBorrower.sol"; +import {BadInitiator} from "../../src/abstract/RaindexV6FlashBorrower.sol"; +import {LibRaindexDeploy} from "../../src/lib/deploy/LibRaindexDeploy.sol"; -contract OrderBookV6FlashBorrowerBadInitiatorTest is Test { - GenericPoolOrderBookV6FlashBorrower arb; +contract RaindexV6FlashBorrowerBadInitiatorTest is Test { + GenericPoolRaindexV6FlashBorrower arb; constructor() { - arb = new GenericPoolOrderBookV6FlashBorrower(); + arb = new GenericPoolRaindexV6FlashBorrower(); } /// onFlashLoan MUST revert with BadInitiator when called with an initiator @@ -20,9 +20,9 @@ contract OrderBookV6FlashBorrowerBadInitiatorTest is Test { function testOnFlashLoanBadInitiator(address badInitiator) external { vm.assume(badInitiator != address(arb)); - // Prank as the deterministic orderbook address to isolate the + // Prank as the deterministic raindex address to isolate the // BadInitiator check. - vm.prank(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS); + vm.prank(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS); vm.expectRevert(abi.encodeWithSelector(BadInitiator.selector, badInitiator)); arb.onFlashLoan(badInitiator, address(0), 0, 0, abi.encode(new bytes(0), new bytes(0))); } diff --git a/test/abstract/OrderBookV6FlashBorrower.badLenderApproval.t.sol b/test/abstract/RaindexV6FlashBorrower.badLenderApproval.t.sol similarity index 82% rename from test/abstract/OrderBookV6FlashBorrower.badLenderApproval.t.sol rename to test/abstract/RaindexV6FlashBorrower.badLenderApproval.t.sol index 772ef4db80..ae297e1780 100644 --- a/test/abstract/OrderBookV6FlashBorrower.badLenderApproval.t.sol +++ b/test/abstract/RaindexV6FlashBorrower.badLenderApproval.t.sol @@ -5,8 +5,8 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import {GenericPoolOrderBookV6FlashBorrower} from "../../src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol"; -import {BadLender} from "../../src/abstract/OrderBookV6FlashBorrower.sol"; +import {GenericPoolRaindexV6FlashBorrower} from "../../src/concrete/arb/GenericPoolRaindexV6FlashBorrower.sol"; +import {BadLender} from "../../src/abstract/RaindexV6FlashBorrower.sol"; import { IRaindexV6, TakeOrdersConfigV5, @@ -23,12 +23,12 @@ import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; import {LibTOFUTokenDecimals} from "rain.tofu.erc20-decimals/lib/LibTOFUTokenDecimals.sol"; import {MockToken} from "test/util/concrete/MockToken.sol"; -import {MaliciousOrderBook} from "test/util/concrete/MaliciousOrderBook.sol"; +import {MaliciousRaindex} from "test/util/concrete/MaliciousRaindex.sol"; -/// A malicious orderBook passed to arb4 gets forceApprove before the +/// A malicious raindex passed to arb4 gets forceApprove before the /// BadLender check in onFlashLoan fires. The entire tx reverts atomically, /// so the approvals never persist. -contract OrderBookV6FlashBorrowerBadLenderApprovalTest is Test { +contract RaindexV6FlashBorrowerBadLenderApprovalTest is Test { function testBadLenderRevertsWithApproval() external { LibRainDeploy.etchZoltuFactory(vm); LibRainDeploy.deployZoltu(LibTOFUTokenDecimals.TOFU_DECIMALS_EXPECTED_CREATION_CODE); @@ -36,10 +36,10 @@ contract OrderBookV6FlashBorrowerBadLenderApprovalTest is Test { MockToken inputToken = new MockToken("Input", "IN", 18); MockToken outputToken = new MockToken("Output", "OUT", 18); - MaliciousOrderBook malicious = new MaliciousOrderBook(); + MaliciousRaindex malicious = new MaliciousRaindex(); malicious.setTokens(address(inputToken), address(outputToken)); - GenericPoolOrderBookV6FlashBorrower arb = new GenericPoolOrderBookV6FlashBorrower(); + GenericPoolRaindexV6FlashBorrower arb = new GenericPoolRaindexV6FlashBorrower(); IOV2[] memory validInputs = new IOV2[](1); validInputs[0] = IOV2(address(inputToken), bytes32(0)); @@ -59,8 +59,8 @@ contract OrderBookV6FlashBorrowerBadLenderApprovalTest is Test { bytes memory exchangeData = abi.encode(address(0), address(0), ""); - // arb4 reverts with BadLender because the malicious orderbook is not - // the deterministic orderbook address. + // arb4 reverts with BadLender because the malicious raindex is not + // the deterministic raindex address. vm.expectRevert(abi.encodeWithSelector(BadLender.selector, address(malicious))); arb.arb4( IRaindexV6(address(malicious)), diff --git a/test/abstract/OrderBookV6FlashBorrower.flashLoanFailed.t.sol b/test/abstract/RaindexV6FlashBorrower.flashLoanFailed.t.sol similarity index 73% rename from test/abstract/OrderBookV6FlashBorrower.flashLoanFailed.t.sol rename to test/abstract/RaindexV6FlashBorrower.flashLoanFailed.t.sol index b8f0da639d..10d283dcc8 100644 --- a/test/abstract/OrderBookV6FlashBorrower.flashLoanFailed.t.sol +++ b/test/abstract/RaindexV6FlashBorrower.flashLoanFailed.t.sol @@ -5,8 +5,8 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import {GenericPoolOrderBookV6FlashBorrower} from "../../src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol"; -import {FlashLoanFailed} from "../../src/abstract/OrderBookV6FlashBorrower.sol"; +import {GenericPoolRaindexV6FlashBorrower} from "../../src/concrete/arb/GenericPoolRaindexV6FlashBorrower.sol"; +import {FlashLoanFailed} from "../../src/abstract/RaindexV6FlashBorrower.sol"; import { IRaindexV6, TakeOrdersConfigV5, @@ -23,15 +23,15 @@ import {IInterpreterStoreV3} from "rain.interpreter.interface/interface/IInterpr import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; import {LibTOFUTokenDecimals} from "rain.tofu.erc20-decimals/lib/LibTOFUTokenDecimals.sol"; -import {LibOrderBookDeploy} from "../../src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "../../src/lib/deploy/LibRaindexDeploy.sol"; import {MockToken} from "test/util/concrete/MockToken.sol"; -import {MockOrderBookBase} from "test/util/abstract/MockOrderBookBase.sol"; +import {MockRaindexBase} from "test/util/abstract/MockRaindexBase.sol"; -/// @dev Mock orderbook that returns false from flashLoan (inherits default stub). -contract FalseFlashLoanMockOrderBook is MockOrderBookBase {} +/// @dev Mock raindex that returns false from flashLoan (inherits default stub). +contract FalseFlashLoanMockRaindex is MockRaindexBase {} -contract OrderBookV6FlashBorrowerFlashLoanFailedTest is Test { - /// arb4 reverts with FlashLoanFailed when the orderbook's flashLoan +contract RaindexV6FlashBorrowerFlashLoanFailedTest is Test { + /// arb4 reverts with FlashLoanFailed when the raindex's flashLoan /// returns false. function testFlashLoanFailed() external { LibRainDeploy.etchZoltuFactory(vm); @@ -40,10 +40,10 @@ contract OrderBookV6FlashBorrowerFlashLoanFailedTest is Test { MockToken inputToken = new MockToken("Input", "IN", 18); MockToken outputToken = new MockToken("Output", "OUT", 18); - FalseFlashLoanMockOrderBook mockOb = new FalseFlashLoanMockOrderBook(); - vm.etch(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS, address(mockOb).code); + FalseFlashLoanMockRaindex mockOb = new FalseFlashLoanMockRaindex(); + vm.etch(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, address(mockOb).code); - GenericPoolOrderBookV6FlashBorrower arb = new GenericPoolOrderBookV6FlashBorrower(); + GenericPoolRaindexV6FlashBorrower arb = new GenericPoolRaindexV6FlashBorrower(); IOV2[] memory validInputs = new IOV2[](1); validInputs[0] = IOV2(address(inputToken), bytes32(0)); @@ -63,7 +63,7 @@ contract OrderBookV6FlashBorrowerFlashLoanFailedTest is Test { vm.expectRevert(FlashLoanFailed.selector); arb.arb4( - IRaindexV6(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS), + IRaindexV6(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS), TakeOrdersConfigV5({ minimumIO: LibDecimalFloat.packLossless(100, 0), maximumIO: LibDecimalFloat.packLossless(type(int224).max, 0), diff --git a/test/abstract/OrderBookV6FlashBorrower.ierc165.t.sol b/test/abstract/RaindexV6FlashBorrower.ierc165.t.sol similarity index 68% rename from test/abstract/OrderBookV6FlashBorrower.ierc165.t.sol rename to test/abstract/RaindexV6FlashBorrower.ierc165.t.sol index db5f47b8dd..76cc6d9348 100644 --- a/test/abstract/OrderBookV6FlashBorrower.ierc165.t.sol +++ b/test/abstract/RaindexV6FlashBorrower.ierc165.t.sol @@ -4,22 +4,22 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {IERC165} from "openzeppelin-contracts/contracts/utils/introspection/IERC165.sol"; -import {OrderBookV6FlashBorrower, IERC3156FlashBorrower} from "../../src/abstract/OrderBookV6FlashBorrower.sol"; +import {RaindexV6FlashBorrower, IERC3156FlashBorrower} from "../../src/abstract/RaindexV6FlashBorrower.sol"; /// @dev We need a contract that is deployable in order to test the abstract /// base contract. -contract ChildOrderBookV6FlashBorrower is OrderBookV6FlashBorrower { +contract ChildRaindexV6FlashBorrower is RaindexV6FlashBorrower { constructor() {} } -contract OrderBookV6FlashBorrowerIERC165Test is Test { +contract RaindexV6FlashBorrowerIERC165Test is Test { /// Test that ERC165 and IERC3156FlashBorrower are supported interfaces /// as per ERC165. - function testOrderBookV6FlashBorrowerIERC165(bytes4 badInterfaceId) external { + function testRaindexV6FlashBorrowerIERC165(bytes4 badInterfaceId) external { vm.assume(badInterfaceId != type(IERC165).interfaceId); vm.assume(badInterfaceId != type(IERC3156FlashBorrower).interfaceId); - ChildOrderBookV6FlashBorrower flashBorrower = new ChildOrderBookV6FlashBorrower(); + ChildRaindexV6FlashBorrower flashBorrower = new ChildRaindexV6FlashBorrower(); assertTrue(flashBorrower.supportsInterface(type(IERC165).interfaceId)); assertTrue(flashBorrower.supportsInterface(type(IERC3156FlashBorrower).interfaceId)); assertFalse(flashBorrower.supportsInterface(badInterfaceId)); diff --git a/test/abstract/OrderBookV6FlashBorrower.lenderValidation.t.sol b/test/abstract/RaindexV6FlashBorrower.lenderValidation.t.sol similarity index 64% rename from test/abstract/OrderBookV6FlashBorrower.lenderValidation.t.sol rename to test/abstract/RaindexV6FlashBorrower.lenderValidation.t.sol index e5a7df95eb..09523b041c 100644 --- a/test/abstract/OrderBookV6FlashBorrower.lenderValidation.t.sol +++ b/test/abstract/RaindexV6FlashBorrower.lenderValidation.t.sol @@ -4,18 +4,18 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; -import {GenericPoolOrderBookV6FlashBorrower} from "../../src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol"; -import {BadLender} from "../../src/abstract/OrderBookV6FlashBorrower.sol"; +import {GenericPoolRaindexV6FlashBorrower} from "../../src/concrete/arb/GenericPoolRaindexV6FlashBorrower.sol"; +import {BadLender} from "../../src/abstract/RaindexV6FlashBorrower.sol"; import {MaliciousLender} from "test/util/concrete/MaliciousLender.sol"; import {MockToken} from "test/util/concrete/MockToken.sol"; -contract OrderBookV6FlashBorrowerLenderValidationTest is Test { +contract RaindexV6FlashBorrowerLenderValidationTest is Test { /// A malicious lender calls onFlashLoan directly. The call reverts with - /// BadLender because msg.sender is not the configured orderbook. + /// BadLender because msg.sender is not the configured raindex. function testMaliciousLenderCannotExploitOnFlashLoan() external { MockToken token = new MockToken("Token", "TKN", 18); - GenericPoolOrderBookV6FlashBorrower arb = new GenericPoolOrderBookV6FlashBorrower(); + GenericPoolRaindexV6FlashBorrower arb = new GenericPoolRaindexV6FlashBorrower(); MaliciousLender attacker = new MaliciousLender(); diff --git a/test/abstract/OrderBookV6FlashBorrower.mixedDecimals.t.sol b/test/abstract/RaindexV6FlashBorrower.mixedDecimals.t.sol similarity index 78% rename from test/abstract/OrderBookV6FlashBorrower.mixedDecimals.t.sol rename to test/abstract/RaindexV6FlashBorrower.mixedDecimals.t.sol index 5528eb70b4..22f967ed36 100644 --- a/test/abstract/OrderBookV6FlashBorrower.mixedDecimals.t.sol +++ b/test/abstract/RaindexV6FlashBorrower.mixedDecimals.t.sol @@ -5,7 +5,7 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import {GenericPoolOrderBookV6FlashBorrower} from "../../src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol"; +import {GenericPoolRaindexV6FlashBorrower} from "../../src/concrete/arb/GenericPoolRaindexV6FlashBorrower.sol"; import { IRaindexV6, TakeOrdersConfigV5, @@ -22,12 +22,12 @@ import {IInterpreterStoreV3} from "rain.interpreter.interface/interface/IInterpr import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; import {LibTOFUTokenDecimals} from "rain.tofu.erc20-decimals/lib/LibTOFUTokenDecimals.sol"; -import {LibOrderBookDeploy} from "../../src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "../../src/lib/deploy/LibRaindexDeploy.sol"; import {MockToken} from "test/util/concrete/MockToken.sol"; import {MockExchange} from "test/util/concrete/MockExchange.sol"; -import {RealisticFlashLendingMockOrderBook} from "test/util/concrete/RealisticFlashLendingMockOrderBook.sol"; +import {RealisticFlashLendingMockRaindex} from "test/util/concrete/RealisticFlashLendingMockRaindex.sol"; -contract OrderBookV6FlashBorrowerMixedDecimalsTest is Test { +contract RaindexV6FlashBorrowerMixedDecimalsTest is Test { /// arb4 with mixed-decimal tokens: 6-decimal output (USDT-like) and /// 18-decimal input (DAI-like). The flash loan amount must use /// outputDecimals, not inputDecimals. @@ -38,18 +38,18 @@ contract OrderBookV6FlashBorrowerMixedDecimalsTest is Test { MockToken inputToken = new MockToken("DAI", "DAI", 18); MockToken outputToken = new MockToken("USDT", "USDT", 6); - RealisticFlashLendingMockOrderBook mockOb = new RealisticFlashLendingMockOrderBook(); - vm.etch(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS, address(mockOb).code); - RealisticFlashLendingMockOrderBook orderBook = - RealisticFlashLendingMockOrderBook(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS); + RealisticFlashLendingMockRaindex mockOb = new RealisticFlashLendingMockRaindex(); + vm.etch(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, address(mockOb).code); + RealisticFlashLendingMockRaindex raindex = + RealisticFlashLendingMockRaindex(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS); MockExchange exchange = new MockExchange(); // OB needs outputToken for both the flash loan and takeOrders4. - outputToken.mint(address(orderBook), 1000e6); + outputToken.mint(address(raindex), 1000e6); // Exchange has 100e6 of inputToken for the swap. inputToken.mint(address(exchange), 100e6); - GenericPoolOrderBookV6FlashBorrower arb = new GenericPoolOrderBookV6FlashBorrower(); + GenericPoolRaindexV6FlashBorrower arb = new GenericPoolRaindexV6FlashBorrower(); IOV2[] memory validInputs = new IOV2[](1); validInputs[0] = IOV2(address(inputToken), bytes32(0)); @@ -74,7 +74,7 @@ contract OrderBookV6FlashBorrowerMixedDecimalsTest is Test { ); arb.arb4( - IRaindexV6(address(orderBook)), + IRaindexV6(address(raindex)), TakeOrdersConfigV5({ minimumIO: LibDecimalFloat.packLossless(100, 0), maximumIO: LibDecimalFloat.packLossless(type(int224).max, 0), diff --git a/test/abstract/OrderBookV6FlashBorrower.noOrders.t.sol b/test/abstract/RaindexV6FlashBorrower.noOrders.t.sol similarity index 84% rename from test/abstract/OrderBookV6FlashBorrower.noOrders.t.sol rename to test/abstract/RaindexV6FlashBorrower.noOrders.t.sol index 7d8858d6af..d0e52a4107 100644 --- a/test/abstract/OrderBookV6FlashBorrower.noOrders.t.sol +++ b/test/abstract/RaindexV6FlashBorrower.noOrders.t.sol @@ -4,7 +4,7 @@ pragma solidity =0.8.25; import {ArbTest} from "test/util/abstract/ArbTest.sol"; -import {GenericPoolOrderBookV6FlashBorrower} from "../../src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol"; +import {GenericPoolRaindexV6FlashBorrower} from "../../src/concrete/arb/GenericPoolRaindexV6FlashBorrower.sol"; import { IRaindexV6, EvaluableV4, @@ -18,9 +18,9 @@ import { import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibInterpreterDeploy} from "rain.interpreter/lib/deploy/LibInterpreterDeploy.sol"; -contract OrderBookV6FlashBorrowerNoOrdersTest is ArbTest { +contract RaindexV6FlashBorrowerNoOrdersTest is ArbTest { function buildArb() internal override returns (address payable) { - return payable(address(new GenericPoolOrderBookV6FlashBorrower())); + return payable(address(new GenericPoolRaindexV6FlashBorrower())); } constructor() ArbTest() {} @@ -30,9 +30,9 @@ contract OrderBookV6FlashBorrowerNoOrdersTest is ArbTest { TakeOrderConfigV4[] memory orders = new TakeOrderConfigV4[](0); vm.expectRevert(abi.encodeWithSelector(IRaindexV6.NoOrders.selector)); - GenericPoolOrderBookV6FlashBorrower(iArb) + GenericPoolRaindexV6FlashBorrower(iArb) .arb4( - iOrderBook, + iRaindex, TakeOrdersConfigV5({ minimumIO: LibDecimalFloat.packLossless(0, 0), maximumIO: LibDecimalFloat.packLossless(type(int224).max, 0), diff --git a/test/abstract/OrderBookV6FlashBorrower.realTokenTransfers.t.sol b/test/abstract/RaindexV6FlashBorrower.realTokenTransfers.t.sol similarity index 78% rename from test/abstract/OrderBookV6FlashBorrower.realTokenTransfers.t.sol rename to test/abstract/RaindexV6FlashBorrower.realTokenTransfers.t.sol index 94fcbec525..066097bb35 100644 --- a/test/abstract/OrderBookV6FlashBorrower.realTokenTransfers.t.sol +++ b/test/abstract/RaindexV6FlashBorrower.realTokenTransfers.t.sol @@ -5,7 +5,7 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import {GenericPoolOrderBookV6FlashBorrower} from "../../src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol"; +import {GenericPoolRaindexV6FlashBorrower} from "../../src/concrete/arb/GenericPoolRaindexV6FlashBorrower.sol"; import { IRaindexV6, TakeOrdersConfigV5, @@ -22,12 +22,12 @@ import {IInterpreterStoreV3} from "rain.interpreter.interface/interface/IInterpr import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; import {LibTOFUTokenDecimals} from "rain.tofu.erc20-decimals/lib/LibTOFUTokenDecimals.sol"; -import {LibOrderBookDeploy} from "../../src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "../../src/lib/deploy/LibRaindexDeploy.sol"; import {MockToken} from "test/util/concrete/MockToken.sol"; import {MockExchange} from "test/util/concrete/MockExchange.sol"; -import {RealisticFlashLendingMockOrderBook} from "test/util/concrete/RealisticFlashLendingMockOrderBook.sol"; +import {RealisticFlashLendingMockRaindex} from "test/util/concrete/RealisticFlashLendingMockRaindex.sol"; -contract OrderBookV6FlashBorrowerRealTokenTransfersTest is Test { +contract RaindexV6FlashBorrowerRealTokenTransfersTest is Test { /// arb4 completes a full flash loan cycle with real ERC20 transfers: /// flash loan, exchange, take orders, repayment, and finalize. function testArb4RealTokenTransfers() external { @@ -37,16 +37,16 @@ contract OrderBookV6FlashBorrowerRealTokenTransfersTest is Test { MockToken inputToken = new MockToken("Input", "IN", 18); MockToken outputToken = new MockToken("Output", "OUT", 18); - RealisticFlashLendingMockOrderBook mockOb = new RealisticFlashLendingMockOrderBook(); - vm.etch(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS, address(mockOb).code); - RealisticFlashLendingMockOrderBook orderBook = - RealisticFlashLendingMockOrderBook(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS); + RealisticFlashLendingMockRaindex mockOb = new RealisticFlashLendingMockRaindex(); + vm.etch(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, address(mockOb).code); + RealisticFlashLendingMockRaindex raindex = + RealisticFlashLendingMockRaindex(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS); MockExchange exchange = new MockExchange(); - outputToken.mint(address(orderBook), 1000e18); + outputToken.mint(address(raindex), 1000e18); inputToken.mint(address(exchange), 100e18); - GenericPoolOrderBookV6FlashBorrower arb = new GenericPoolOrderBookV6FlashBorrower(); + GenericPoolRaindexV6FlashBorrower arb = new GenericPoolRaindexV6FlashBorrower(); IOV2[] memory validInputs = new IOV2[](1); validInputs[0] = IOV2(address(inputToken), bytes32(0)); @@ -71,7 +71,7 @@ contract OrderBookV6FlashBorrowerRealTokenTransfersTest is Test { ); arb.arb4( - IRaindexV6(address(orderBook)), + IRaindexV6(address(raindex)), TakeOrdersConfigV5({ minimumIO: LibDecimalFloat.packLossless(100, 0), maximumIO: LibDecimalFloat.packLossless(type(int224).max, 0), @@ -88,7 +88,7 @@ contract OrderBookV6FlashBorrowerRealTokenTransfersTest is Test { ); // OB received all inputToken from arb. - assertEq(inputToken.balanceOf(address(orderBook)), 100e18); + assertEq(inputToken.balanceOf(address(raindex)), 100e18); // Exchange received outputToken from arb (100e18 of the 1000e18 OB had). assertEq(outputToken.balanceOf(address(exchange)), 100e18); // Arb contract has no remaining tokens. diff --git a/test/abstract/OrderBookV6FlashBorrower.reentrancy.t.sol b/test/abstract/RaindexV6FlashBorrower.reentrancy.t.sol similarity index 75% rename from test/abstract/OrderBookV6FlashBorrower.reentrancy.t.sol rename to test/abstract/RaindexV6FlashBorrower.reentrancy.t.sol index 7e9d115dfc..93c761359b 100644 --- a/test/abstract/OrderBookV6FlashBorrower.reentrancy.t.sol +++ b/test/abstract/RaindexV6FlashBorrower.reentrancy.t.sol @@ -4,7 +4,7 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; -import {GenericPoolOrderBookV6FlashBorrower} from "../../src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol"; +import {GenericPoolRaindexV6FlashBorrower} from "../../src/concrete/arb/GenericPoolRaindexV6FlashBorrower.sol"; import { IRaindexV6, TakeOrdersConfigV5, @@ -20,12 +20,12 @@ import {IInterpreterStoreV3} from "rain.interpreter.interface/interface/IInterpr import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; import {LibTOFUTokenDecimals} from "rain.tofu.erc20-decimals/lib/LibTOFUTokenDecimals.sol"; -import {LibOrderBookDeploy} from "../../src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "../../src/lib/deploy/LibRaindexDeploy.sol"; import {MockToken} from "test/util/concrete/MockToken.sol"; -import {FlashLendingMockOrderBook} from "test/util/concrete/FlashLendingMockOrderBook.sol"; +import {FlashLendingMockRaindex} from "test/util/concrete/FlashLendingMockRaindex.sol"; import {ReentrantExchange} from "test/util/concrete/ReentrantExchange.sol"; -contract OrderBookV6FlashBorrowerReentrancyTest is Test { +contract RaindexV6FlashBorrowerReentrancyTest is Test { /// arb4 MUST revert when re-entered via the pool call in _exchange. function testArb4Reentrancy() external { LibRainDeploy.etchZoltuFactory(vm); @@ -34,19 +34,19 @@ contract OrderBookV6FlashBorrowerReentrancyTest is Test { MockToken inputToken = new MockToken("Input", "IN", 18); MockToken outputToken = new MockToken("Output", "OUT", 18); - // The flash borrower checks msg.sender == ORDERBOOK_DEPLOYED_ADDRESS in - // onFlashLoan. Deploy a FlashLendingMockOrderBook and etch it there. - FlashLendingMockOrderBook orderBook = new FlashLendingMockOrderBook(); - vm.etch(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS, address(orderBook).code); + // The flash borrower checks msg.sender == RAINDEX_DEPLOYED_ADDRESS in + // onFlashLoan. Deploy a FlashLendingMockRaindex and etch it there. + FlashLendingMockRaindex raindex = new FlashLendingMockRaindex(); + vm.etch(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, address(raindex).code); // Mint output tokens to the etched OB so it can flash-lend them. - outputToken.mint(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS, 100e18); + outputToken.mint(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, 100e18); - GenericPoolOrderBookV6FlashBorrower arb = new GenericPoolOrderBookV6FlashBorrower(); + GenericPoolRaindexV6FlashBorrower arb = new GenericPoolRaindexV6FlashBorrower(); // Deploy the reentrant exchange that will call arb4 when invoked. ReentrantExchange exchange = - new ReentrantExchange(arb, IRaindexV6(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS)); + new ReentrantExchange(arb, IRaindexV6(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS)); IOV2[] memory validInputs = new IOV2[](1); validInputs[0] = IOV2(address(inputToken), bytes32(0)); @@ -69,7 +69,7 @@ contract OrderBookV6FlashBorrowerReentrancyTest is Test { vm.expectRevert(abi.encodeWithSelector(bytes4(keccak256("ReentrancyGuardReentrantCall()")))); arb.arb4( - IRaindexV6(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS), + IRaindexV6(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS), TakeOrdersConfigV5({ minimumIO: LibDecimalFloat.packLossless(100, 0), maximumIO: LibDecimalFloat.packLossless(type(int224).max, 0), diff --git a/test/abstract/RaindexV6FlashLender.fee.t.sol b/test/abstract/RaindexV6FlashLender.fee.t.sol new file mode 100644 index 0000000000..3c1ea4157d --- /dev/null +++ b/test/abstract/RaindexV6FlashLender.fee.t.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity =0.8.25; + +import {RaindexV6ExternalMockTest} from "test/util/abstract/RaindexV6ExternalMockTest.sol"; + +/// @title RaindexV6FlashLenderFeeTest +/// Tests the fee charged by `RaindexV6FlashLender`. +contract RaindexV6FlashLenderFeeTest is RaindexV6ExternalMockTest { + /// Tests that the fee charged by `RaindexV6FlashLender` is 0. + function testFlashFee(address token, uint256 amount) public view { + assertEq(iRaindex.flashFee(token, amount), 0); + } +} diff --git a/test/abstract/OrderBookV6FlashLender.griefRecipient.t.sol b/test/abstract/RaindexV6FlashLender.griefRecipient.t.sol similarity index 76% rename from test/abstract/OrderBookV6FlashLender.griefRecipient.t.sol rename to test/abstract/RaindexV6FlashLender.griefRecipient.t.sol index b6f4ab9e43..d19bbf4fec 100644 --- a/test/abstract/OrderBookV6FlashLender.griefRecipient.t.sol +++ b/test/abstract/RaindexV6FlashLender.griefRecipient.t.sol @@ -2,20 +2,20 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalMockTest} from "test/util/abstract/OrderBookV6ExternalMockTest.sol"; +import {RaindexV6ExternalMockTest} from "test/util/abstract/RaindexV6ExternalMockTest.sol"; import { IERC3156FlashBorrower, ON_FLASH_LOAN_CALLBACK_SUCCESS } from "rain.raindex.interface/interface/ierc3156/IERC3156FlashBorrower.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import {FlashLenderCallbackFailed} from "../../src/abstract/OrderBookV6FlashLender.sol"; +import {FlashLenderCallbackFailed} from "../../src/abstract/RaindexV6FlashLender.sol"; -/// @title OrderBookV6FlashLenderGriefRecipientTest +/// @title RaindexV6FlashLenderGriefRecipientTest /// Try to grief the recipient of the flash loan. -contract OrderBookV6FlashLenderGriefRecipientTest is OrderBookV6ExternalMockTest { +contract RaindexV6FlashLenderGriefRecipientTest is RaindexV6ExternalMockTest { /// Tests that no matter who the receiver is, and no matter what happens with /// the tokens, the flash loan will revert if the receiver is not - /// `OrderBookV6FlashBorrower`. + /// `RaindexV6FlashBorrower`. function testFlashLoanToNonReceiver( uint256 amount, bytes memory data, @@ -32,7 +32,7 @@ contract OrderBookV6FlashLenderGriefRecipientTest is OrderBookV6ExternalMockTest // A call to an EOA will revert with no data. address receiver = address(0xDEADBEEF); vm.expectRevert(); - iOrderbook.flashLoan(IERC3156FlashBorrower(receiver), address(iToken0), amount, data); + iRaindex.flashLoan(IERC3156FlashBorrower(receiver), address(iToken0), amount, data); // A call to a contract that does not implement `IERC3156FlashBorrower` // will revert with `FlashLenderCallbackFailed`. @@ -43,7 +43,7 @@ contract OrderBookV6FlashLenderGriefRecipientTest is OrderBookV6ExternalMockTest abi.encode(notFlashLoanSuccess) ); vm.expectRevert(abi.encodeWithSelector(FlashLenderCallbackFailed.selector, notFlashLoanSuccess)); - iOrderbook.flashLoan(IERC3156FlashBorrower(receiver), address(iToken0), amount, data); + iRaindex.flashLoan(IERC3156FlashBorrower(receiver), address(iToken0), amount, data); // A call to a contract that does not implement `IERC3156FlashBorrower` // will revert with no data if the return value is not `bytes32`. @@ -51,6 +51,6 @@ contract OrderBookV6FlashLenderGriefRecipientTest is OrderBookV6ExternalMockTest receiver, abi.encodeWithSelector(IERC3156FlashBorrower.onFlashLoan.selector), notFlashLoanSuccessBytes ); vm.expectRevert(); - iOrderbook.flashLoan(IERC3156FlashBorrower(receiver), address(iToken0), amount, data); + iRaindex.flashLoan(IERC3156FlashBorrower(receiver), address(iToken0), amount, data); } } diff --git a/test/abstract/OrderBookV6FlashLender.ierc165.t.sol b/test/abstract/RaindexV6FlashLender.ierc165.t.sol similarity index 66% rename from test/abstract/OrderBookV6FlashLender.ierc165.t.sol rename to test/abstract/RaindexV6FlashLender.ierc165.t.sol index 3328605553..282cf84990 100644 --- a/test/abstract/OrderBookV6FlashLender.ierc165.t.sol +++ b/test/abstract/RaindexV6FlashLender.ierc165.t.sol @@ -4,22 +4,22 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {IERC165} from "openzeppelin-contracts/contracts/utils/introspection/IERC165.sol"; -import {OrderBookV6FlashLender, IERC3156FlashLender} from "../../src/abstract/OrderBookV6FlashLender.sol"; +import {RaindexV6FlashLender, IERC3156FlashLender} from "../../src/abstract/RaindexV6FlashLender.sol"; /// @dev We need a contract that is deployable in order to test the abstract /// base contract. -contract ChildOrderBookV6FlashLender is OrderBookV6FlashLender { - constructor() OrderBookV6FlashLender() {} +contract ChildRaindexV6FlashLender is RaindexV6FlashLender { + constructor() RaindexV6FlashLender() {} } -contract OrderBookV6FlashLenderIERC165Test is Test { +contract RaindexV6FlashLenderIERC165Test is Test { /// Test that ERC165 and IERC3156FlashLender are supported interfaces /// as per ERC165. - function testOrderBookV6FlashLenderIERC165(bytes4 badInterfaceId) external { + function testRaindexV6FlashLenderIERC165(bytes4 badInterfaceId) external { vm.assume(badInterfaceId != type(IERC165).interfaceId); vm.assume(badInterfaceId != type(IERC3156FlashLender).interfaceId); - ChildOrderBookV6FlashLender flashLender = new ChildOrderBookV6FlashLender(); + ChildRaindexV6FlashLender flashLender = new ChildRaindexV6FlashLender(); assertTrue(flashLender.supportsInterface(type(IERC165).interfaceId)); assertTrue(flashLender.supportsInterface(type(IERC3156FlashLender).interfaceId)); assertFalse(flashLender.supportsInterface(badInterfaceId)); diff --git a/test/abstract/RaindexV6FlashLender.maxFlashLoan.t.sol b/test/abstract/RaindexV6FlashLender.maxFlashLoan.t.sol new file mode 100644 index 0000000000..0ff8ef4ff2 --- /dev/null +++ b/test/abstract/RaindexV6FlashLender.maxFlashLoan.t.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity =0.8.25; + +import {RaindexV6ExternalMockTest} from "test/util/abstract/RaindexV6ExternalMockTest.sol"; +import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; + +/// @title RaindexV6FlashLenderMaxFlashLoanTest +/// Tests the maximum flash loan amount for `RaindexV6FlashLender`. +contract RaindexV6FlashLenderMaxFlashLoanTest is RaindexV6ExternalMockTest { + /// Tests that the maximum flash loan amount for `RaindexV6FlashLender` is + /// the balance of the token in the order book. + function testFlashMaxLoan(uint256 amount) public { + vm.mockCall( + address(iToken0), abi.encodeWithSelector(IERC20.balanceOf.selector, address(iRaindex)), abi.encode(amount) + ); + assertEq(iRaindex.maxFlashLoan(address(iToken0)), amount); + } +} diff --git a/test/abstract/OrderBookV6FlashLender.mockSuccess.t.sol b/test/abstract/RaindexV6FlashLender.mockSuccess.t.sol similarity index 72% rename from test/abstract/OrderBookV6FlashLender.mockSuccess.t.sol rename to test/abstract/RaindexV6FlashLender.mockSuccess.t.sol index 5e0eaa39d0..29734fea43 100644 --- a/test/abstract/OrderBookV6FlashLender.mockSuccess.t.sol +++ b/test/abstract/RaindexV6FlashLender.mockSuccess.t.sol @@ -2,18 +2,18 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalMockTest} from "test/util/abstract/OrderBookV6ExternalMockTest.sol"; +import {RaindexV6ExternalMockTest} from "test/util/abstract/RaindexV6ExternalMockTest.sol"; import { IERC3156FlashBorrower, ON_FLASH_LOAN_CALLBACK_SUCCESS } from "rain.raindex.interface/interface/ierc3156/IERC3156FlashBorrower.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -/// @title OrderBookV6FlashLenderMockSuccessTest -/// Show that if the receiver is `OrderBookV6FlashBorrower` and the token +/// @title RaindexV6FlashLenderMockSuccessTest +/// Show that if the receiver is `RaindexV6FlashBorrower` and the token /// movements do not error, then the flash loan will succeed. -contract OrderBookV6FlashLenderMockSuccessTest is OrderBookV6ExternalMockTest { - /// Tests that if the receiver is `OrderBookV6FlashBorrower` and the token +contract RaindexV6FlashLenderMockSuccessTest is RaindexV6ExternalMockTest { + /// Tests that if the receiver is `RaindexV6FlashBorrower` and the token /// movements do not error, then the flash loan will succeed. function testFlashLoanToReceiver(uint256 amount, bytes memory data) public { // Return true for all transfers. @@ -29,6 +29,6 @@ contract OrderBookV6FlashLenderMockSuccessTest is OrderBookV6ExternalMockTest { abi.encodeWithSelector(IERC3156FlashBorrower.onFlashLoan.selector), abi.encode(ON_FLASH_LOAN_CALLBACK_SUCCESS) ); - assertTrue(iOrderbook.flashLoan(IERC3156FlashBorrower(receiver), address(iToken0), amount, data)); + assertTrue(iRaindex.flashLoan(IERC3156FlashBorrower(receiver), address(iToken0), amount, data)); } } diff --git a/test/abstract/OrderBookV6FlashLender.reentrant.t.sol b/test/abstract/RaindexV6FlashLender.reentrant.t.sol similarity index 92% rename from test/abstract/OrderBookV6FlashLender.reentrant.t.sol rename to test/abstract/RaindexV6FlashLender.reentrant.t.sol index fc33fbc1c6..db8773a0fa 100644 --- a/test/abstract/OrderBookV6FlashLender.reentrant.t.sol +++ b/test/abstract/RaindexV6FlashLender.reentrant.t.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalRealTest} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import {Reenteroor} from "test/util/concrete/Reenteroor.sol"; import { IRaindexV6, @@ -19,10 +19,10 @@ import {LibTestTakeOrder} from "test/util/lib/LibTestTakeOrder.sol"; import {EvaluableV4, SignedContextV1} from "rain.interpreter.interface/interface/IInterpreterCallerV4.sol"; import {Float, LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; -/// @title OrderBookV6FlashLenderReentrant -/// Test that flash borrowers can reenter the orderbook, which is necessary for +/// @title RaindexV6FlashLenderReentrant +/// Test that flash borrowers can reenter the raindex, which is necessary for /// trading etc. against it while the loan is active. -contract OrderBookV6FlashLenderReentrant is OrderBookV6ExternalRealTest { +contract RaindexV6FlashLenderReentrant is RaindexV6ExternalRealTest { function checkFlashLoanNotRevert(Reenteroor borrower, bytes memory encodedCall, uint256 loanAmount) internal { borrower.reenterWith(encodedCall); vm.mockCall( @@ -32,17 +32,17 @@ contract OrderBookV6FlashLenderReentrant is OrderBookV6ExternalRealTest { ); vm.mockCall( address(iToken0), - abi.encodeWithSelector(IERC20.approve.selector, address(iOrderbook), loanAmount), + abi.encodeWithSelector(IERC20.approve.selector, address(iRaindex), loanAmount), abi.encode(true) ); vm.mockCall( address(iToken0), - abi.encodeWithSelector(IERC20.transferFrom.selector, borrower, address(iOrderbook), loanAmount), + abi.encodeWithSelector(IERC20.transferFrom.selector, borrower, address(iRaindex), loanAmount), abi.encode(true) ); // Create a flash loan. - iOrderbook.flashLoan(IERC3156FlashBorrower(address(borrower)), address(iToken0), loanAmount, ""); + iRaindex.flashLoan(IERC3156FlashBorrower(address(borrower)), address(iToken0), loanAmount, ""); } /// Can reenter and read vault balances from within a flash loan. @@ -80,7 +80,7 @@ contract OrderBookV6FlashLenderReentrant is OrderBookV6ExternalRealTest { Reenteroor borrower = new Reenteroor(); vm.mockCall( address(iToken0), - abi.encodeWithSelector(IERC20.transferFrom.selector, borrower, address(iOrderbook), depositAmount18), + abi.encodeWithSelector(IERC20.transferFrom.selector, borrower, address(iRaindex), depositAmount18), abi.encode(true) ); checkFlashLoanNotRevert( @@ -149,7 +149,7 @@ contract OrderBookV6FlashLenderReentrant is OrderBookV6ExternalRealTest { config.evaluable.bytecode = iParserV2.parse2("_ _:max-positive-value() 1;:;"); vm.recordLogs(); - iOrderbook.addOrder4(config, new TaskV2[](0)); + iRaindex.addOrder4(config, new TaskV2[](0)); OrderV4 memory order = LibTestTakeOrder.extractOrderFromLogs(vm.getRecordedLogs()); TakeOrdersConfigV5 memory takeOrdersConfig = @@ -187,19 +187,19 @@ contract OrderBookV6FlashLenderReentrant is OrderBookV6ExternalRealTest { vm.recordLogs(); vm.prank(alice); - iOrderbook.addOrder4(aliceConfig, new TaskV2[](0)); + iRaindex.addOrder4(aliceConfig, new TaskV2[](0)); OrderV4 memory aliceOrder = LibTestTakeOrder.extractOrderFromLogs(vm.getRecordedLogs()); vm.recordLogs(); vm.prank(bob); - iOrderbook.addOrder4(bobConfig, new TaskV2[](0)); + iRaindex.addOrder4(bobConfig, new TaskV2[](0)); OrderV4 memory bobOrder = LibTestTakeOrder.extractOrderFromLogs(vm.getRecordedLogs()); ClearConfigV2 memory clearConfig = ClearConfigV2(0, 0, 0, 0, 0, 0); vm.mockCall(aliceOrder.validOutputs[0].token, bytes(""), abi.encode(true)); vm.prank(aliceOrder.owner); - iOrderbook.deposit4( + iRaindex.deposit4( aliceOrder.validOutputs[0].token, aliceOrder.validOutputs[0].vaultId, LibDecimalFloat.packLossless(type(int64).max, 0), @@ -207,7 +207,7 @@ contract OrderBookV6FlashLenderReentrant is OrderBookV6ExternalRealTest { ); vm.mockCall(bobOrder.validOutputs[0].token, bytes(""), abi.encode(true)); vm.prank(bobOrder.owner); - iOrderbook.deposit4( + iRaindex.deposit4( bobOrder.validOutputs[0].token, bobOrder.validOutputs[0].vaultId, LibDecimalFloat.packLossless(type(int64).max, 0), diff --git a/test/abstract/OrderBookV6FlashLender.transfers.t.sol b/test/abstract/RaindexV6FlashLender.transfers.t.sol similarity index 85% rename from test/abstract/OrderBookV6FlashLender.transfers.t.sol rename to test/abstract/RaindexV6FlashLender.transfers.t.sol index 481b895709..d50933680f 100644 --- a/test/abstract/OrderBookV6FlashLender.transfers.t.sol +++ b/test/abstract/RaindexV6FlashLender.transfers.t.sol @@ -3,7 +3,7 @@ pragma solidity =0.8.25; import {stdError} from "forge-std/Test.sol"; -import {OrderBookV6ExternalMockTest} from "test/util/abstract/OrderBookV6ExternalMockTest.sol"; +import {RaindexV6ExternalMockTest} from "test/util/abstract/RaindexV6ExternalMockTest.sol"; import {ERC20, IERC20Errors} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; @@ -13,7 +13,7 @@ import { ON_FLASH_LOAN_CALLBACK_SUCCESS } from "rain.raindex.interface/interface/ierc3156/IERC3156FlashBorrower.sol"; import {IERC3156FlashLender} from "rain.raindex.interface/interface/ierc3156/IERC3156FlashLender.sol"; -import {FlashLenderCallbackFailed} from "../../src/abstract/OrderBookV6FlashLender.sol"; +import {FlashLenderCallbackFailed} from "../../src/abstract/RaindexV6FlashLender.sol"; contract TKN is ERC20 { constructor(address recipient, uint256 supply) ERC20("TKN", "TKN") { @@ -79,14 +79,14 @@ contract Carol is IPull { } } -/// @title OrderBookV6FlashLenderTransferTest -/// Tests the `OrderBookV6FlashLender` transfer functions. -contract OrderBookV6FlashLenderTransferTest is OrderBookV6ExternalMockTest { +/// @title RaindexV6FlashLenderTransferTest +/// Tests the `RaindexV6FlashLender` transfer functions. +contract RaindexV6FlashLenderTransferTest is RaindexV6ExternalMockTest { /// Alice can send tokens to Bob, who will return them and then the loan will /// be repaid. /// forge-config: default.fuzz.runs = 100 function testFlashLoanTransferSuccess(uint256 amount, bool success) public { - TKN tkn = new TKN(address(iOrderbook), amount); + TKN tkn = new TKN(address(iRaindex), amount); Bob bob = new Bob(); Alice alice = new Alice(IPull(address(bob)), success); @@ -94,7 +94,7 @@ contract OrderBookV6FlashLenderTransferTest is OrderBookV6ExternalMockTest { if (!success) { vm.expectRevert(abi.encodeWithSelector(FlashLenderCallbackFailed.selector, bytes32(0))); } - bool result = iOrderbook.flashLoan(IERC3156FlashBorrower(address(alice)), address(tkn), amount, ""); + bool result = iRaindex.flashLoan(IERC3156FlashBorrower(address(alice)), address(tkn), amount, ""); if (success) { assertTrue(result); } @@ -106,7 +106,7 @@ contract OrderBookV6FlashLenderTransferTest is OrderBookV6ExternalMockTest { function testFlashLoanTransferFail(uint256 amount, uint256 amountWithheld, bool success) public { amount = bound(amount, 1, type(uint256).max); amountWithheld = bound(amountWithheld, 1, amount); - TKN tkn = new TKN(address(iOrderbook), amount); + TKN tkn = new TKN(address(iRaindex), amount); Carol carol = new Carol(amountWithheld); Alice alice = new Alice(IPull(address(carol)), success); @@ -120,6 +120,6 @@ contract OrderBookV6FlashLenderTransferTest is OrderBookV6ExternalMockTest { ) ); } - iOrderbook.flashLoan(IERC3156FlashBorrower(address(alice)), address(tkn), amount, ""); + iRaindex.flashLoan(IERC3156FlashBorrower(address(alice)), address(tkn), amount, ""); } } diff --git a/test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.approvalRevoked.t.sol b/test/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.approvalRevoked.t.sol similarity index 87% rename from test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.approvalRevoked.t.sol rename to test/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.approvalRevoked.t.sol index 751994f26f..ec2097de67 100644 --- a/test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.approvalRevoked.t.sol +++ b/test/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.approvalRevoked.t.sol @@ -8,12 +8,12 @@ import {AllowanceCheckingExchange} from "test/util/concrete/AllowanceCheckingExc /// After a successful arb5, the spender's allowance on the output token /// from the arb contract must be zero (approve-call-revoke). -contract GenericPoolOrderBookV6ArbOrderTakerApprovalRevokedTest is Test { +contract GenericPoolRaindexV6ArbOrderTakerApprovalRevokedTest is Test { function testApprovalRevokedAfterOnTakeOrders2() external { AllowanceCheckingExchange exchange = new AllowanceCheckingExchange(); OrderTakerSetup memory setup = LibTestArb.setup(vm, address(exchange), 100e18); - setup.arb.arb5(setup.orderBook, setup.takeOrdersConfig, LibTestArb.noopTask()); + setup.arb.arb5(setup.raindex, setup.takeOrdersConfig, LibTestArb.noopTask()); // During the call the exchange saw max approval. assertEq(exchange.lastAllowance(), type(uint256).max, "exchange saw max allowance during call"); diff --git a/test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.exchangeRevert.t.sol b/test/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.exchangeRevert.t.sol similarity index 81% rename from test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.exchangeRevert.t.sol rename to test/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.exchangeRevert.t.sol index 4f2c0829fa..7c51a62d5e 100644 --- a/test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.exchangeRevert.t.sol +++ b/test/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.exchangeRevert.t.sol @@ -8,12 +8,12 @@ import {RevertingExchange} from "test/util/concrete/RevertingExchange.sol"; /// If the exchange call reverts, the entire arb5 reverts with the /// exchange's revert reason bubbled up. -contract GenericPoolOrderBookV6ArbOrderTakerExchangeRevertTest is Test { +contract GenericPoolRaindexV6ArbOrderTakerExchangeRevertTest is Test { function testExchangeRevertPropagates() external { RevertingExchange exchange = new RevertingExchange(); OrderTakerSetup memory setup = LibTestArb.setup(vm, address(exchange), 100e18); vm.expectRevert("exchange failed"); - setup.arb.arb5(setup.orderBook, setup.takeOrdersConfig, LibTestArb.noopTask()); + setup.arb.arb5(setup.raindex, setup.takeOrdersConfig, LibTestArb.noopTask()); } } diff --git a/test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sender.t.sol b/test/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.sender.t.sol similarity index 79% rename from test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sender.t.sol rename to test/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.sender.t.sol index 54968a4a19..c49653ed30 100644 --- a/test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sender.t.sol +++ b/test/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.sender.t.sol @@ -2,9 +2,9 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {GenericPoolOrderBookV6ArbOrderTakerTest} from "test/util/abstract/GenericPoolOrderBookV6ArbOrderTakerTest.sol"; +import {GenericPoolRaindexV6ArbOrderTakerTest} from "test/util/abstract/GenericPoolRaindexV6ArbOrderTakerTest.sol"; -import {GenericPoolOrderBookV6ArbOrderTaker} from "../../../src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol"; +import {GenericPoolRaindexV6ArbOrderTaker} from "../../../src/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.sol"; import { OrderV4, EvaluableV4, @@ -18,14 +18,14 @@ import { import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibInterpreterDeploy} from "rain.interpreter/lib/deploy/LibInterpreterDeploy.sol"; -contract GenericPoolOrderBookV6ArbOrderTakerSenderTest is GenericPoolOrderBookV6ArbOrderTakerTest { +contract GenericPoolRaindexV6ArbOrderTakerSenderTest is GenericPoolRaindexV6ArbOrderTakerTest { /// forge-config: default.fuzz.runs = 10 function testGenericPoolTakeOrdersSender(OrderV4 memory order, uint256 inputIOIndex, uint256 outputIOIndex) public { TakeOrderConfigV4[] memory orders = buildTakeOrderConfig(order, inputIOIndex, outputIOIndex); - GenericPoolOrderBookV6ArbOrderTaker(iArb) + GenericPoolRaindexV6ArbOrderTaker(iArb) .arb5( - iOrderBook, + iRaindex, TakeOrdersConfigV5({ minimumIO: LibDecimalFloat.packLossless(0, 0), maximumIO: LibDecimalFloat.packLossless(type(int224).max, 0), diff --git a/test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.approvalRevoked.t.sol b/test/concrete/arb/GenericPoolRaindexV6FlashBorrower.approvalRevoked.t.sol similarity index 85% rename from test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.approvalRevoked.t.sol rename to test/concrete/arb/GenericPoolRaindexV6FlashBorrower.approvalRevoked.t.sol index 03529d7135..8c45400b1b 100644 --- a/test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.approvalRevoked.t.sol +++ b/test/concrete/arb/GenericPoolRaindexV6FlashBorrower.approvalRevoked.t.sol @@ -9,12 +9,12 @@ import {AllowanceCheckingExchange} from "test/util/concrete/AllowanceCheckingExc /// After a successful arb4, the spender's allowance on the borrowed token /// from the arb contract must be zero (approve-call-revoke). -contract GenericPoolOrderBookV6FlashBorrowerApprovalRevokedTest is Test { +contract GenericPoolRaindexV6FlashBorrowerApprovalRevokedTest is Test { function testApprovalRevokedAfterExchange() external { AllowanceCheckingExchange exchange = new AllowanceCheckingExchange(); FlashBorrowerSetup memory setup = LibTestFlashBorrowerArb.setup(vm, address(exchange), 100e18); - setup.arb.arb4(setup.orderBook, setup.takeOrdersConfig, setup.exchangeData, LibTestArb.noopTask()); + setup.arb.arb4(setup.raindex, setup.takeOrdersConfig, setup.exchangeData, LibTestArb.noopTask()); // During the call the exchange saw max approval. assertEq(exchange.lastAllowance(), type(uint256).max); diff --git a/test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.ethForwarded.t.sol b/test/concrete/arb/GenericPoolRaindexV6FlashBorrower.ethForwarded.t.sol similarity index 87% rename from test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.ethForwarded.t.sol rename to test/concrete/arb/GenericPoolRaindexV6FlashBorrower.ethForwarded.t.sol index cf7e5c16a9..eb63f98c16 100644 --- a/test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.ethForwarded.t.sol +++ b/test/concrete/arb/GenericPoolRaindexV6FlashBorrower.ethForwarded.t.sol @@ -9,7 +9,7 @@ import {AllowanceCheckingExchange} from "test/util/concrete/AllowanceCheckingExc /// When the arb contract holds ETH, functionCallWithValue forwards it /// to the pool during _exchange. -contract GenericPoolOrderBookV6FlashBorrowerEthForwardedTest is Test { +contract GenericPoolRaindexV6FlashBorrowerEthForwardedTest is Test { receive() external payable {} function testEthForwardedToExchangeDuringExchange() external { @@ -19,7 +19,7 @@ contract GenericPoolOrderBookV6FlashBorrowerEthForwardedTest is Test { // Send ETH to the arb contract before calling arb4. vm.deal(address(setup.arb), 1 ether); - setup.arb.arb4(setup.orderBook, setup.takeOrdersConfig, setup.exchangeData, LibTestArb.noopTask()); + setup.arb.arb4(setup.raindex, setup.takeOrdersConfig, setup.exchangeData, LibTestArb.noopTask()); // The exchange received the ETH during the call. assertEq(exchange.lastEthReceived(), 1 ether); diff --git a/test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.exchangeRevert.t.sol b/test/concrete/arb/GenericPoolRaindexV6FlashBorrower.exchangeRevert.t.sol similarity index 81% rename from test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.exchangeRevert.t.sol rename to test/concrete/arb/GenericPoolRaindexV6FlashBorrower.exchangeRevert.t.sol index aa6ee55c38..8d8f8b8784 100644 --- a/test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.exchangeRevert.t.sol +++ b/test/concrete/arb/GenericPoolRaindexV6FlashBorrower.exchangeRevert.t.sol @@ -9,12 +9,12 @@ import {RevertingExchange} from "test/util/concrete/RevertingExchange.sol"; /// If the exchange call reverts, the entire arb4 reverts with the /// exchange's revert reason bubbled up. -contract GenericPoolOrderBookV6FlashBorrowerExchangeRevertTest is Test { +contract GenericPoolRaindexV6FlashBorrowerExchangeRevertTest is Test { function testExchangeRevertPropagates() external { RevertingExchange exchange = new RevertingExchange(); FlashBorrowerSetup memory setup = LibTestFlashBorrowerArb.setup(vm, address(exchange), 100e18); vm.expectRevert("exchange failed"); - setup.arb.arb4(setup.orderBook, setup.takeOrdersConfig, setup.exchangeData, LibTestArb.noopTask()); + setup.arb.arb4(setup.raindex, setup.takeOrdersConfig, setup.exchangeData, LibTestArb.noopTask()); } } diff --git a/test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sender.t.sol b/test/concrete/arb/GenericPoolRaindexV6FlashBorrower.sender.t.sol similarity index 81% rename from test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sender.t.sol rename to test/concrete/arb/GenericPoolRaindexV6FlashBorrower.sender.t.sol index 12908def86..e6bb8e83c1 100644 --- a/test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sender.t.sol +++ b/test/concrete/arb/GenericPoolRaindexV6FlashBorrower.sender.t.sol @@ -4,7 +4,7 @@ pragma solidity =0.8.25; import {ArbTest} from "test/util/abstract/ArbTest.sol"; -import {GenericPoolOrderBookV6FlashBorrower} from "../../../src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol"; +import {GenericPoolRaindexV6FlashBorrower} from "../../../src/concrete/arb/GenericPoolRaindexV6FlashBorrower.sol"; import { OrderV4, TakeOrderConfigV4, @@ -18,24 +18,24 @@ import { import {LibDecimalFloat, Float} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibInterpreterDeploy} from "rain.interpreter/lib/deploy/LibInterpreterDeploy.sol"; -contract GenericPoolOrderBookV6FlashBorrowerTest is ArbTest { +contract GenericPoolRaindexV6FlashBorrowerTest is ArbTest { function buildArb() internal override returns (address payable) { - return payable(address(new GenericPoolOrderBookV6FlashBorrower())); + return payable(address(new GenericPoolRaindexV6FlashBorrower())); } constructor() ArbTest() {} /// forge-config: default.fuzz.runs = 10 - function testGenericPoolOrderBookV6FlashBorrowerTakeOrdersSender( + function testGenericPoolRaindexV6FlashBorrowerTakeOrdersSender( OrderV4 memory order, uint256 inputIOIndex, uint256 outputIOIndex ) public { TakeOrderConfigV4[] memory orders = buildTakeOrderConfig(order, inputIOIndex, outputIOIndex); - GenericPoolOrderBookV6FlashBorrower(iArb) + GenericPoolRaindexV6FlashBorrower(iArb) .arb4( - iOrderBook, + iRaindex, TakeOrdersConfigV5({ minimumIO: LibDecimalFloat.packLossless(0, 0), maximumIO: LibDecimalFloat.packLossless(type(int224).max, 0), diff --git a/test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.lossyRounding.t.sol b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.lossyRounding.t.sol similarity index 78% rename from test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.lossyRounding.t.sol rename to test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.lossyRounding.t.sol index 8c751f986c..591c1bebc4 100644 --- a/test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.lossyRounding.t.sol +++ b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.lossyRounding.t.sol @@ -6,22 +6,22 @@ import {Test} from "forge-std/Test.sol"; import {IRouteProcessor} from "sushixswap-v2/src/interfaces/IRouteProcessor.sol"; import { - RouteProcessorOrderBookV6ArbOrderTaker -} from "../../../src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol"; + RouteProcessorRaindexV6ArbOrderTaker +} from "../../../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; import {Float} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; import {LibTOFUTokenDecimals} from "rain.tofu.erc20-decimals/lib/LibTOFUTokenDecimals.sol"; -import {LibOrderBookDeploy} from "../../../src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "../../../src/lib/deploy/LibRaindexDeploy.sol"; import {MockToken} from "test/util/concrete/MockToken.sol"; import {MockRouteProcessor} from "test/util/concrete/MockRouteProcessor.sol"; /// When toFixedDecimalLossy produces a lossy conversion for the output /// amount, onTakeOrders2 MUST increment the output amount by 1 (round up). -contract RouteProcessorOrderBookV6ArbOrderTakerLossyRoundingTest is Test { +contract RouteProcessorRaindexV6ArbOrderTakerLossyRoundingTest is Test { MockToken internal iInputToken; MockToken internal iOutputToken; - RouteProcessorOrderBookV6ArbOrderTaker internal iArb; + RouteProcessorRaindexV6ArbOrderTaker internal iArb; function setUp() external { LibRainDeploy.etchZoltuFactory(vm); @@ -31,16 +31,16 @@ contract RouteProcessorOrderBookV6ArbOrderTakerLossyRoundingTest is Test { iOutputToken = new MockToken("OUT", "OUT", 6); MockRouteProcessor mockRp = new MockRouteProcessor(); - vm.etch(LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS, address(mockRp).code); + vm.etch(LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS, address(mockRp).code); - iArb = new RouteProcessorOrderBookV6ArbOrderTaker(); + iArb = new RouteProcessorRaindexV6ArbOrderTaker(); } function testOnTakeOrders2LossyOutputRoundsUp() external { // Give the arb contract input tokens for the swap. iInputToken.mint(address(iArb), 1e18); // Give the route processor output tokens to send back. - iOutputToken.mint(LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS, 1); + iOutputToken.mint(LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS, 1); // 1e-7 at 6 decimals = 0.1 of smallest unit → lossy, rounds to 0, // then incremented to 1. @@ -56,7 +56,7 @@ contract RouteProcessorOrderBookV6ArbOrderTakerLossyRoundingTest is Test { // Expect processRoute called with amountOutMin = 1 (0 + 1 from rounding). vm.expectCall( - LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS, + LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS, abi.encodeWithSelector( IRouteProcessor.processRoute.selector, address(iInputToken), @@ -74,7 +74,7 @@ contract RouteProcessorOrderBookV6ArbOrderTakerLossyRoundingTest is Test { // Approval revoked after call. assertEq( - iInputToken.allowance(address(iArb), LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS), + iInputToken.allowance(address(iArb), LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS), 0, "approval must be revoked" ); diff --git a/test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.nonStandardDecimals.t.sol b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.nonStandardDecimals.t.sol similarity index 80% rename from test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.nonStandardDecimals.t.sol rename to test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.nonStandardDecimals.t.sol index 01f6a104f6..320faa9ec7 100644 --- a/test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.nonStandardDecimals.t.sol +++ b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.nonStandardDecimals.t.sol @@ -6,8 +6,8 @@ import {Test} from "forge-std/Test.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import { - RouteProcessorOrderBookV6ArbOrderTaker -} from "../../../src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol"; + RouteProcessorRaindexV6ArbOrderTaker +} from "../../../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; import { IRaindexV6, TakeOrdersConfigV5, @@ -24,15 +24,15 @@ import {IInterpreterStoreV3} from "rain.interpreter.interface/interface/IInterpr import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; import {LibTOFUTokenDecimals} from "rain.tofu.erc20-decimals/lib/LibTOFUTokenDecimals.sol"; -import {LibOrderBookDeploy} from "../../../src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "../../../src/lib/deploy/LibRaindexDeploy.sol"; import {LibInterpreterDeploy} from "rain.interpreter/lib/deploy/LibInterpreterDeploy.sol"; import {MockToken} from "test/util/concrete/MockToken.sol"; import {MockRouteProcessor} from "test/util/concrete/MockRouteProcessor.sol"; -import {RealisticOrderTakerMockOrderBook} from "test/util/concrete/RealisticOrderTakerMockOrderBook.sol"; +import {RealisticOrderTakerMockRaindex} from "test/util/concrete/RealisticOrderTakerMockRaindex.sol"; /// arb5 with RouteProcessor MUST correctly convert Float amounts to /// fixed-point using the token's decimals, not hardcoded 18. -contract RouteProcessorOrderBookV6ArbOrderTakerNonStandardDecimalsTest is Test { +contract RouteProcessorRaindexV6ArbOrderTakerNonStandardDecimalsTest is Test { function testRouteProcessorArb5SixDecimalTokens() external { LibRainDeploy.etchZoltuFactory(vm); LibRainDeploy.deployZoltu(LibTOFUTokenDecimals.TOFU_DECIMALS_EXPECTED_CREATION_CODE); @@ -42,17 +42,17 @@ contract RouteProcessorOrderBookV6ArbOrderTakerNonStandardDecimalsTest is Test { MockToken outputToken = new MockToken("USDT", "USDT", 6); // OB will send 100 USDT (100e6) to the taker, then pull 100 USDC. - RealisticOrderTakerMockOrderBook orderBook = new RealisticOrderTakerMockOrderBook(100e6); + RealisticOrderTakerMockRaindex raindex = new RealisticOrderTakerMockRaindex(100e6); MockRouteProcessor mockRp = new MockRouteProcessor(); - vm.etch(LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS, address(mockRp).code); - address routeProcessor = LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS; + vm.etch(LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS, address(mockRp).code); + address routeProcessor = LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS; // OB has outputToken to send to taker. - outputToken.mint(address(orderBook), 100e6); + outputToken.mint(address(raindex), 100e6); // RouteProcessor has inputToken to give back after swap. inputToken.mint(routeProcessor, 100e6); - RouteProcessorOrderBookV6ArbOrderTaker arb = new RouteProcessorOrderBookV6ArbOrderTaker(); + RouteProcessorRaindexV6ArbOrderTaker arb = new RouteProcessorRaindexV6ArbOrderTaker(); IOV2[] memory validInputs = new IOV2[](1); validInputs[0] = IOV2(address(inputToken), bytes32(0)); @@ -77,7 +77,7 @@ contract RouteProcessorOrderBookV6ArbOrderTakerNonStandardDecimalsTest is Test { bytes memory takeOrdersData = abi.encode(hex""); arb.arb5( - IRaindexV6(address(orderBook)), + IRaindexV6(address(raindex)), TakeOrdersConfigV5({ minimumIO: LibDecimalFloat.packLossless(100, 0), maximumIO: LibDecimalFloat.packLossless(type(int224).max, 0), @@ -100,8 +100,8 @@ contract RouteProcessorOrderBookV6ArbOrderTakerNonStandardDecimalsTest is Test { assertEq(inputToken.balanceOf(address(arb)), 0, "arb inputToken"); assertEq(outputToken.balanceOf(address(arb)), 0, "arb outputToken"); // OB swapped outputToken for inputToken. - assertEq(inputToken.balanceOf(address(orderBook)), 100e6, "OB inputToken"); - assertEq(outputToken.balanceOf(address(orderBook)), 0, "OB outputToken"); + assertEq(inputToken.balanceOf(address(raindex)), 100e6, "OB inputToken"); + assertEq(outputToken.balanceOf(address(raindex)), 0, "OB outputToken"); // RouteProcessor sent all its inputToken. assertEq(inputToken.balanceOf(routeProcessor), 0, "RP inputToken"); assertEq(outputToken.balanceOf(routeProcessor), 0, "RP outputToken"); diff --git a/test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.onTakeOrders2.t.sol b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.onTakeOrders2.t.sol similarity index 78% rename from test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.onTakeOrders2.t.sol rename to test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.onTakeOrders2.t.sol index 4787c0b97e..4a34a5c00c 100644 --- a/test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.onTakeOrders2.t.sol +++ b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.onTakeOrders2.t.sol @@ -6,8 +6,8 @@ import {Test} from "forge-std/Test.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import { - RouteProcessorOrderBookV6ArbOrderTaker -} from "../../../src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol"; + RouteProcessorRaindexV6ArbOrderTaker +} from "../../../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; import { IRaindexV6, TakeOrdersConfigV5, @@ -24,12 +24,12 @@ import {IInterpreterStoreV3} from "rain.interpreter.interface/interface/IInterpr import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; import {LibTOFUTokenDecimals} from "rain.tofu.erc20-decimals/lib/LibTOFUTokenDecimals.sol"; -import {LibOrderBookDeploy} from "../../../src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "../../../src/lib/deploy/LibRaindexDeploy.sol"; import {MockToken} from "test/util/concrete/MockToken.sol"; import {MockRouteProcessor} from "test/util/concrete/MockRouteProcessor.sol"; -import {RealisticOrderTakerMockOrderBook} from "test/util/concrete/RealisticOrderTakerMockOrderBook.sol"; +import {RealisticOrderTakerMockRaindex} from "test/util/concrete/RealisticOrderTakerMockRaindex.sol"; -contract RouteProcessorOrderBookV6ArbOrderTakerOnTakeOrders2Test is Test { +contract RouteProcessorRaindexV6ArbOrderTakerOnTakeOrders2Test is Test { /// arb5 with RouteProcessor completes a full order-taker cycle: /// takeOrders, onTakeOrders2 callback via mock route processor, finalize. function testRouteProcessorArb5() external { @@ -39,17 +39,17 @@ contract RouteProcessorOrderBookV6ArbOrderTakerOnTakeOrders2Test is Test { MockToken inputToken = new MockToken("Input", "IN", 18); MockToken outputToken = new MockToken("Output", "OUT", 18); - RealisticOrderTakerMockOrderBook orderBook = new RealisticOrderTakerMockOrderBook(100e18); + RealisticOrderTakerMockRaindex raindex = new RealisticOrderTakerMockRaindex(100e18); MockRouteProcessor mockRp = new MockRouteProcessor(); - vm.etch(LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS, address(mockRp).code); - address routeProcessor = LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS; + vm.etch(LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS, address(mockRp).code); + address routeProcessor = LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS; // OB has outputToken to send to taker. - outputToken.mint(address(orderBook), 100e18); + outputToken.mint(address(raindex), 100e18); // RouteProcessor has inputToken to give back after swap. inputToken.mint(routeProcessor, 100e18); - RouteProcessorOrderBookV6ArbOrderTaker arb = new RouteProcessorOrderBookV6ArbOrderTaker(); + RouteProcessorRaindexV6ArbOrderTaker arb = new RouteProcessorRaindexV6ArbOrderTaker(); IOV2[] memory validInputs = new IOV2[](1); validInputs[0] = IOV2(address(inputToken), bytes32(0)); @@ -71,7 +71,7 @@ contract RouteProcessorOrderBookV6ArbOrderTakerOnTakeOrders2Test is Test { bytes memory takeOrdersData = abi.encode(hex""); arb.arb5( - IRaindexV6(address(orderBook)), + IRaindexV6(address(raindex)), TakeOrdersConfigV5({ minimumIO: LibDecimalFloat.packLossless(100, 0), maximumIO: LibDecimalFloat.packLossless(type(int224).max, 0), @@ -90,8 +90,8 @@ contract RouteProcessorOrderBookV6ArbOrderTakerOnTakeOrders2Test is Test { assertEq(inputToken.balanceOf(address(arb)), 0, "arb inputToken"); assertEq(outputToken.balanceOf(address(arb)), 0, "arb outputToken"); // OB started with outputToken, swapped for inputToken via arb. - assertEq(inputToken.balanceOf(address(orderBook)), 100e18, "OB inputToken"); - assertEq(outputToken.balanceOf(address(orderBook)), 0, "OB outputToken"); + assertEq(inputToken.balanceOf(address(raindex)), 100e18, "OB inputToken"); + assertEq(outputToken.balanceOf(address(raindex)), 0, "OB outputToken"); // RouteProcessor started with inputToken, received nothing (amountIn=0). assertEq(inputToken.balanceOf(routeProcessor), 0, "RP inputToken"); assertEq(outputToken.balanceOf(routeProcessor), 0, "RP outputToken"); diff --git a/test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.onTakeOrders2Direct.t.sol b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.onTakeOrders2Direct.t.sol similarity index 77% rename from test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.onTakeOrders2Direct.t.sol rename to test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.onTakeOrders2Direct.t.sol index beb6ce1b12..68ed882f28 100644 --- a/test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.onTakeOrders2Direct.t.sol +++ b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.onTakeOrders2Direct.t.sol @@ -5,16 +5,16 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import { - RouteProcessorOrderBookV6ArbOrderTaker -} from "../../../src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol"; + RouteProcessorRaindexV6ArbOrderTaker +} from "../../../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; import {Float} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; import {LibTOFUTokenDecimals} from "rain.tofu.erc20-decimals/lib/LibTOFUTokenDecimals.sol"; -import {LibOrderBookDeploy} from "../../../src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "../../../src/lib/deploy/LibRaindexDeploy.sol"; import {MockToken} from "test/util/concrete/MockToken.sol"; import {MockRouteProcessor} from "test/util/concrete/MockRouteProcessor.sol"; -contract RouteProcessorOrderBookV6ArbOrderTakerOnTakeOrders2DirectTest is Test { +contract RouteProcessorRaindexV6ArbOrderTakerOnTakeOrders2DirectTest is Test { /// Calling onTakeOrders2 directly from an arbitrary address MUST succeed. /// The function has no access control by design — the contract is stateless /// between operations so there is nothing to exploit. @@ -25,9 +25,9 @@ contract RouteProcessorOrderBookV6ArbOrderTakerOnTakeOrders2DirectTest is Test { MockToken tokenA = new MockToken("A", "A", 18); MockToken tokenB = new MockToken("B", "B", 18); MockRouteProcessor mockRp = new MockRouteProcessor(); - vm.etch(LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS, address(mockRp).code); + vm.etch(LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS, address(mockRp).code); - RouteProcessorOrderBookV6ArbOrderTaker arb = new RouteProcessorOrderBookV6ArbOrderTaker(); + RouteProcessorRaindexV6ArbOrderTaker arb = new RouteProcessorRaindexV6ArbOrderTaker(); // Attacker calls onTakeOrders2 directly with zero amounts. // processRoute is called with 0 amountIn so no tokens move. diff --git a/test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sender.t.sol b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sender.t.sol similarity index 79% rename from test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sender.t.sol rename to test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sender.t.sol index 6082bcbdf2..9ddfdbe9bb 100644 --- a/test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sender.t.sol +++ b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sender.t.sol @@ -3,8 +3,8 @@ pragma solidity =0.8.25; import { - RouteProcessorOrderBookV6ArbOrderTakerTest -} from "test/util/abstract/RouteProcessorOrderBookV6ArbOrderTakerTest.sol"; + RouteProcessorRaindexV6ArbOrderTakerTest +} from "test/util/abstract/RouteProcessorRaindexV6ArbOrderTakerTest.sol"; import { OrderV4, EvaluableV4, @@ -16,21 +16,21 @@ import { SignedContextV1 } from "rain.raindex.interface/interface/IRaindexV6.sol"; import { - RouteProcessorOrderBookV6ArbOrderTaker -} from "../../../src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol"; + RouteProcessorRaindexV6ArbOrderTaker +} from "../../../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; import {LibDecimalFloat, Float} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibInterpreterDeploy} from "rain.interpreter/lib/deploy/LibInterpreterDeploy.sol"; -contract RouteProcessorOrderBookV6ArbOrderTakerSenderTest is RouteProcessorOrderBookV6ArbOrderTakerTest { +contract RouteProcessorRaindexV6ArbOrderTakerSenderTest is RouteProcessorRaindexV6ArbOrderTakerTest { /// forge-config: default.fuzz.runs = 100 function testRouteProcessorTakeOrdersSender(OrderV4 memory order, uint256 inputIOIndex, uint256 outputIOIndex) public { TakeOrderConfigV4[] memory orders = buildTakeOrderConfig(order, inputIOIndex, outputIOIndex); - RouteProcessorOrderBookV6ArbOrderTaker(iArb) + RouteProcessorRaindexV6ArbOrderTaker(iArb) .arb5( - iOrderBook, + iRaindex, TakeOrdersConfigV5({ minimumIO: LibDecimalFloat.packLossless(0, 0), maximumIO: LibDecimalFloat.packLossless(type(int224).max, 0), diff --git a/test/concrete/ob/OrderBookV6.removeOrder.owner.t.sol b/test/concrete/ob/OrderBookV6.removeOrder.owner.t.sol deleted file mode 100644 index 15ddb7a787..0000000000 --- a/test/concrete/ob/OrderBookV6.removeOrder.owner.t.sol +++ /dev/null @@ -1,138 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity =0.8.25; - -import {OrderBookV6ExternalRealTest} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; -import {OrderConfigV4, OrderV4, EvaluableV4, TaskV2} from "rain.raindex.interface/interface/IRaindexV6.sol"; -import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; -import {LibOrder} from "../../../src/lib/LibOrder.sol"; -import {NotOrderOwner} from "../../../src/concrete/ob/OrderBookV6.sol"; - -contract OrderBookV6RemoveOrderOwnerTest is OrderBookV6ExternalRealTest { - using LibOrder for OrderV4; - - /// forge-config: default.fuzz.runs = 100 - function testRemoveOrderOwnerSameOrderNoop(address owner, OrderConfigV4 memory config) public { - LibTestAddOrder.conformConfig(config, iInterpreter, iStore); - - OrderV4 memory order = OrderV4(owner, config.evaluable, config.validInputs, config.validOutputs, config.nonce); - - vm.startPrank(owner); - - for (uint256 i = 0; i < 2; i++) { - bool stateChange = iOrderbook.addOrder4(config, new TaskV2[](0)); - assert(stateChange); - assert(iOrderbook.orderExists(order.hash())); - stateChange = iOrderbook.addOrder4(config, new TaskV2[](0)); - assert(!stateChange); - assert(iOrderbook.orderExists(order.hash())); - - stateChange = iOrderbook.removeOrder3(order, new TaskV2[](0)); - assert(stateChange); - assert(!iOrderbook.orderExists(order.hash())); - stateChange = iOrderbook.removeOrder3(order, new TaskV2[](0)); - assert(!stateChange); - assert(!iOrderbook.orderExists(order.hash())); - } - - vm.stopPrank(); - } - - /// forge-config: default.fuzz.runs = 100 - function testRemoveOrderOwnerDifferentOwnerStateChange(OrderConfigV4 memory config, address alice, address bob) - public - { - LibTestAddOrder.conformConfig(config, iInterpreter, iStore); - vm.assume(alice != bob); - - OrderV4 memory orderAlice = - OrderV4(alice, config.evaluable, config.validInputs, config.validOutputs, config.nonce); - OrderV4 memory orderBob = OrderV4(bob, config.evaluable, config.validInputs, config.validOutputs, config.nonce); - - { - vm.prank(alice); - bool stateChange = iOrderbook.addOrder4(config, new TaskV2[](0)); - - assert(stateChange); - assert(iOrderbook.orderExists(orderAlice.hash())); - assert(!iOrderbook.orderExists(orderBob.hash())); - - vm.prank(bob); - stateChange = iOrderbook.removeOrder3(orderBob, new TaskV2[](0)); - assert(!stateChange); - assert(iOrderbook.orderExists(orderAlice.hash())); - assert(!iOrderbook.orderExists(orderBob.hash())); - - vm.prank(alice); - stateChange = iOrderbook.removeOrder3(orderAlice, new TaskV2[](0)); - assert(stateChange); - assert(!iOrderbook.orderExists(orderAlice.hash())); - assert(!iOrderbook.orderExists(orderBob.hash())); - } - - { - vm.prank(bob); - bool stateChange = iOrderbook.addOrder4(config, new TaskV2[](0)); - assert(stateChange); - assert(iOrderbook.orderExists(orderBob.hash())); - assert(!iOrderbook.orderExists(orderAlice.hash())); - - vm.prank(alice); - stateChange = iOrderbook.removeOrder3(orderAlice, new TaskV2[](0)); - assert(!stateChange); - assert(iOrderbook.orderExists(orderBob.hash())); - assert(!iOrderbook.orderExists(orderAlice.hash())); - - vm.prank(bob); - stateChange = iOrderbook.removeOrder3(orderBob, new TaskV2[](0)); - assert(stateChange); - assert(!iOrderbook.orderExists(orderBob.hash())); - assert(!iOrderbook.orderExists(orderAlice.hash())); - } - - { - vm.prank(alice); - bool stateChange = iOrderbook.addOrder4(config, new TaskV2[](0)); - assert(stateChange); - assert(iOrderbook.orderExists(orderAlice.hash())); - assert(!iOrderbook.orderExists(orderBob.hash())); - - vm.prank(bob); - stateChange = iOrderbook.addOrder4(config, new TaskV2[](0)); - assert(stateChange); - assert(iOrderbook.orderExists(orderBob.hash())); - assert(iOrderbook.orderExists(orderAlice.hash())); - - vm.prank(alice); - stateChange = iOrderbook.removeOrder3(orderAlice, new TaskV2[](0)); - assert(stateChange); - assert(!iOrderbook.orderExists(orderAlice.hash())); - assert(iOrderbook.orderExists(orderBob.hash())); - - vm.prank(bob); - stateChange = iOrderbook.removeOrder3(orderBob, new TaskV2[](0)); - assert(stateChange); - assert(!iOrderbook.orderExists(orderBob.hash())); - assert(!iOrderbook.orderExists(orderAlice.hash())); - } - } - - /// forge-config: default.fuzz.runs = 100 - function testRemoveOrderWrongOwner(OrderConfigV4 memory config, address alice, address bob) public { - LibTestAddOrder.conformConfig(config, iInterpreter, iStore); - vm.assume(alice != bob); - - OrderV4 memory order = OrderV4(alice, config.evaluable, config.validInputs, config.validOutputs, config.nonce); - - vm.prank(alice); - bool stateChange = iOrderbook.addOrder4(config, new TaskV2[](0)); - assert(stateChange); - assert(iOrderbook.orderExists(order.hash())); - - vm.prank(bob); - vm.expectRevert(abi.encodeWithSelector(NotOrderOwner.selector, alice)); - stateChange = iOrderbook.removeOrder3(order, new TaskV2[](0)); - assert(!stateChange); - assert(iOrderbook.orderExists(order.hash())); - } -} diff --git a/test/concrete/ob/OrderBookV6.addOrder.entask.t.sol b/test/concrete/ob/RaindexV6.addOrder.entask.t.sol similarity index 94% rename from test/concrete/ob/OrderBookV6.addOrder.entask.t.sol rename to test/concrete/ob/RaindexV6.addOrder.entask.t.sol index 428c87dabf..29cccbb270 100644 --- a/test/concrete/ob/OrderBookV6.addOrder.entask.t.sol +++ b/test/concrete/ob/RaindexV6.addOrder.entask.t.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalRealTest} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import { OrderConfigV4, EvaluableV4, @@ -15,7 +15,7 @@ import {LibOrder} from "../../../src/lib/LibOrder.sol"; import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol"; -contract OrderBookV6AddOrderEnactTest is OrderBookV6ExternalRealTest { +contract RaindexV6AddOrderEnactTest is RaindexV6ExternalRealTest { using LibOrder for OrderV4; using Strings for address; using Strings for uint256; @@ -23,7 +23,7 @@ contract OrderBookV6AddOrderEnactTest is OrderBookV6ExternalRealTest { mapping(bytes32 => bool) nonces; function checkReentrancyRW(uint256 expectedReads, uint256 expectedWrites) internal view { - (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iOrderbook)); + (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iRaindex)); // ReentrancyGuard.REENTRANCY_GUARD_STORAGE bytes32 reentrancyGuardStorage = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00; // 3 reads for reentrancy guard. @@ -50,7 +50,7 @@ contract OrderBookV6AddOrderEnactTest is OrderBookV6ExternalRealTest { vm.startPrank(owner); TaskV2[] memory actions = evalsToActions(evalStrings); vm.record(); - bool stateChanged = iOrderbook.addOrder4(config, actions); + bool stateChanged = iRaindex.addOrder4(config, actions); assert(stateChanged != nonces[config.nonce]); checkReentrancyRW(nonces[config.nonce] ? 4 : 5, nonces[config.nonce] ? 2 : 3); (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iStore)); @@ -163,12 +163,12 @@ contract OrderBookV6AddOrderEnactTest is OrderBookV6ExternalRealTest { vm.startPrank(alice); TaskV2[] memory actions = evalsToActions(evals0); vm.expectRevert("always revert"); - bool stateChanged = iOrderbook.addOrder4(config, actions); + bool stateChanged = iRaindex.addOrder4(config, actions); assert(!stateChanged); OrderV4 memory order = OrderV4(alice, config.evaluable, config.validInputs, config.validOutputs, config.nonce); - assert(!iOrderbook.orderExists(order.hash())); + assert(!iRaindex.orderExists(order.hash())); } /// forge-config: default.fuzz.runs = 10 @@ -185,7 +185,7 @@ contract OrderBookV6AddOrderEnactTest is OrderBookV6ExternalRealTest { bytes[] memory evals = new bytes[](3); evals[0] = bytes( string.concat( - usingWordsFrom, ":ensure(equal-to(orderbook() ", address(iOrderbook).toHexString(), ") \"orderbook\");" + usingWordsFrom, ":ensure(equal-to(raindex() ", address(iRaindex).toHexString(), ") \"raindex\");" ) ); evals[1] = bytes( diff --git a/test/concrete/ob/OrderBookV6.addOrder.mock.t.sol b/test/concrete/ob/RaindexV6.addOrder.mock.t.sol similarity index 91% rename from test/concrete/ob/OrderBookV6.addOrder.mock.t.sol rename to test/concrete/ob/RaindexV6.addOrder.mock.t.sol index 5cc4662808..c7a3014d28 100644 --- a/test/concrete/ob/OrderBookV6.addOrder.mock.t.sol +++ b/test/concrete/ob/RaindexV6.addOrder.mock.t.sol @@ -2,16 +2,16 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalMockTest} from "test/util/abstract/OrderBookV6ExternalMockTest.sol"; +import {RaindexV6ExternalMockTest} from "test/util/abstract/RaindexV6ExternalMockTest.sol"; import {OrderConfigV4, OrderV4, IOV2, EvaluableV4, TaskV2} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; import {NotRainMetaV1, META_MAGIC_NUMBER_V1} from "rain.metadata/interface/unstable/IMetaV1_2.sol"; import {LibMeta} from "rain.metadata/lib/LibMeta.sol"; import {IExpressionDeployerV3} from "rain.interpreter.interface/interface/deprecated/v1/IExpressionDeployerV3.sol"; -/// @title OrderBookV6AddOrderMockTest -/// @notice Tests the addOrder function of the OrderBookV6 contract. -contract OrderBookV6AddOrderMockTest is OrderBookV6ExternalMockTest { +/// @title RaindexV6AddOrderMockTest +/// @notice Tests the addOrder function of the RaindexV6 contract. +contract RaindexV6AddOrderMockTest is RaindexV6ExternalMockTest { /// Adding an order without calculations does not revert. /// This is a runtime error. /// forge-config: default.fuzz.runs = 100 @@ -19,10 +19,10 @@ contract OrderBookV6AddOrderMockTest is OrderBookV6ExternalMockTest { vm.prank(owner); LibTestAddOrder.conformConfig(config, iInterpreter, iStore); config.evaluable.bytecode = ""; - iOrderbook.addOrder4(config, new TaskV2[](0)); + iRaindex.addOrder4(config, new TaskV2[](0)); (OrderV4 memory order, bytes32 orderHash) = LibTestAddOrder.expectedOrder(owner, config); (order); - assertTrue(iOrderbook.orderExists(orderHash)); + assertTrue(iRaindex.orderExists(orderHash)); } /// Adding an order without inputs reverts. @@ -32,10 +32,10 @@ contract OrderBookV6AddOrderMockTest is OrderBookV6ExternalMockTest { config.evaluable.bytecode = hex"02000000040000000000000000"; config.validInputs = new IOV2[](0); vm.expectRevert(abi.encodeWithSelector(OrderNoInputs.selector)); - iOrderbook.addOrder4(config, new TaskV2[](0)); + iRaindex.addOrder4(config, new TaskV2[](0)); (OrderV4 memory order, bytes32 orderHash) = LibTestAddOrder.expectedOrder(owner, config); (order); - assertTrue(!iOrderbook.orderExists(orderHash)); + assertTrue(!iRaindex.orderExists(orderHash)); } /// Adding an order without token outputs reverts. @@ -46,10 +46,10 @@ contract OrderBookV6AddOrderMockTest is OrderBookV6ExternalMockTest { vm.assume(config.validInputs.length > 0); config.validOutputs = new IOV2[](0); vm.expectRevert(abi.encodeWithSelector(OrderNoOutputs.selector)); - iOrderbook.addOrder4(config, new TaskV2[](0)); + iRaindex.addOrder4(config, new TaskV2[](0)); (OrderV4 memory order, bytes32 orderHash) = LibTestAddOrder.expectedOrder(owner, config); (order); - assertTrue(!iOrderbook.orderExists(orderHash)); + assertTrue(!iRaindex.orderExists(orderHash)); } /// Adding an order with calculations, inputs and outputs will succeed if @@ -82,11 +82,11 @@ contract OrderBookV6AddOrderMockTest is OrderBookV6ExternalMockTest { vm.assume(config.meta.length > 0); vm.expectRevert(abi.encodeWithSelector(NotRainMetaV1.selector, config.meta)); - iOrderbook.addOrder4(config, new TaskV2[](0)); + iRaindex.addOrder4(config, new TaskV2[](0)); (OrderV4 memory order, bytes32 orderHash) = LibTestAddOrder.expectedOrder(owner, config); (order); - assertTrue(!iOrderbook.orderExists(orderHash)); + assertTrue(!iRaindex.orderExists(orderHash)); } /// Adding a valid order with a non-empty meta MUST emit MetaV1 if the meta diff --git a/test/concrete/ob/OrderBookV6.addOrder.nonce.t.sol b/test/concrete/ob/RaindexV6.addOrder.nonce.t.sol similarity index 74% rename from test/concrete/ob/OrderBookV6.addOrder.nonce.t.sol rename to test/concrete/ob/RaindexV6.addOrder.nonce.t.sol index 4a55d62548..f559896db3 100644 --- a/test/concrete/ob/OrderBookV6.addOrder.nonce.t.sol +++ b/test/concrete/ob/RaindexV6.addOrder.nonce.t.sol @@ -2,12 +2,12 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalRealTest} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import {OrderConfigV4, OrderV4, EvaluableV4, TaskV2} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; import {LibOrder} from "../../../src/lib/LibOrder.sol"; -contract OrderBookV6AddOrderNonceTest is OrderBookV6ExternalRealTest { +contract RaindexV6AddOrderNonceTest is RaindexV6ExternalRealTest { using LibOrder for OrderV4; /// forge-config: default.fuzz.runs = 100 @@ -16,14 +16,14 @@ contract OrderBookV6AddOrderNonceTest is OrderBookV6ExternalRealTest { OrderV4 memory order = OrderV4(owner, config.evaluable, config.validInputs, config.validOutputs, config.nonce); vm.prank(owner); - bool stateChange = iOrderbook.addOrder4(config, new TaskV2[](0)); + bool stateChange = iRaindex.addOrder4(config, new TaskV2[](0)); assert(stateChange); - assert(iOrderbook.orderExists(order.hash())); + assert(iRaindex.orderExists(order.hash())); vm.prank(owner); - stateChange = iOrderbook.addOrder4(config, new TaskV2[](0)); + stateChange = iRaindex.addOrder4(config, new TaskV2[](0)); assert(!stateChange); - assert(iOrderbook.orderExists(order.hash())); + assert(iRaindex.orderExists(order.hash())); } /// forge-config: default.fuzz.runs = 100 @@ -33,20 +33,20 @@ contract OrderBookV6AddOrderNonceTest is OrderBookV6ExternalRealTest { LibTestAddOrder.conformConfig(config, iInterpreter, iStore); vm.assume(config.nonce != otherNonce); vm.prank(owner); - bool stateChange = iOrderbook.addOrder4(config, new TaskV2[](0)); + bool stateChange = iRaindex.addOrder4(config, new TaskV2[](0)); assert(stateChange); assert( - iOrderbook.orderExists( + iRaindex.orderExists( OrderV4(owner, config.evaluable, config.validInputs, config.validOutputs, config.nonce).hash() ) ); config.nonce = otherNonce; vm.prank(owner); - stateChange = iOrderbook.addOrder4(config, new TaskV2[](0)); + stateChange = iRaindex.addOrder4(config, new TaskV2[](0)); assert(stateChange); assert( - iOrderbook.orderExists( + iRaindex.orderExists( OrderV4(owner, config.evaluable, config.validInputs, config.validOutputs, otherNonce).hash() ) ); @@ -64,19 +64,19 @@ contract OrderBookV6AddOrderNonceTest is OrderBookV6ExternalRealTest { config1.nonce = config0.nonce; vm.assume(keccak256(abi.encode(config0)) != keccak256(abi.encode(config1))); vm.prank(owner); - bool stateChange = iOrderbook.addOrder4(config0, new TaskV2[](0)); + bool stateChange = iRaindex.addOrder4(config0, new TaskV2[](0)); assert(stateChange); assert( - iOrderbook.orderExists( + iRaindex.orderExists( OrderV4(owner, config0.evaluable, config0.validInputs, config0.validOutputs, config0.nonce).hash() ) ); vm.prank(owner); - stateChange = iOrderbook.addOrder4(config1, new TaskV2[](0)); + stateChange = iRaindex.addOrder4(config1, new TaskV2[](0)); assert(stateChange); assert( - iOrderbook.orderExists( + iRaindex.orderExists( OrderV4(owner, config1.evaluable, config1.validInputs, config1.validOutputs, config1.nonce).hash() ) ); diff --git a/test/concrete/ob/OrderBookV6.addOrder.owner.t.sol b/test/concrete/ob/RaindexV6.addOrder.owner.t.sol similarity index 69% rename from test/concrete/ob/OrderBookV6.addOrder.owner.t.sol rename to test/concrete/ob/RaindexV6.addOrder.owner.t.sol index c9cb5276c0..cbd12f1d90 100644 --- a/test/concrete/ob/OrderBookV6.addOrder.owner.t.sol +++ b/test/concrete/ob/RaindexV6.addOrder.owner.t.sol @@ -2,12 +2,12 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalRealTest} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import {OrderConfigV4, OrderV4, EvaluableV4, TaskV2} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; import {LibOrder} from "../../../src/lib/LibOrder.sol"; -contract OrderBookV6AddOrderOwnerTest is OrderBookV6ExternalRealTest { +contract RaindexV6AddOrderOwnerTest is RaindexV6ExternalRealTest { using LibOrder for OrderV4; /// forge-config: default.fuzz.runs = 100 @@ -17,14 +17,14 @@ contract OrderBookV6AddOrderOwnerTest is OrderBookV6ExternalRealTest { OrderV4 memory order = OrderV4(owner, config.evaluable, config.validInputs, config.validOutputs, config.nonce); vm.prank(owner); - bool stateChange = iOrderbook.addOrder4(config, new TaskV2[](0)); + bool stateChange = iRaindex.addOrder4(config, new TaskV2[](0)); assert(stateChange); - assert(iOrderbook.orderExists(order.hash())); + assert(iRaindex.orderExists(order.hash())); vm.prank(owner); - stateChange = iOrderbook.addOrder4(config, new TaskV2[](0)); + stateChange = iRaindex.addOrder4(config, new TaskV2[](0)); assert(!stateChange); - assert(iOrderbook.orderExists(order.hash())); + assert(iRaindex.orderExists(order.hash())); } /// forge-config: default.fuzz.runs = 100 @@ -39,13 +39,13 @@ contract OrderBookV6AddOrderOwnerTest is OrderBookV6ExternalRealTest { OrderV4 memory orderBob = OrderV4(bob, config.evaluable, config.validInputs, config.validOutputs, config.nonce); vm.prank(alice); - bool stateChange = iOrderbook.addOrder4(config, new TaskV2[](0)); + bool stateChange = iRaindex.addOrder4(config, new TaskV2[](0)); assert(stateChange); - assert(iOrderbook.orderExists(orderAlice.hash())); + assert(iRaindex.orderExists(orderAlice.hash())); vm.prank(bob); - stateChange = iOrderbook.addOrder4(config, new TaskV2[](0)); + stateChange = iRaindex.addOrder4(config, new TaskV2[](0)); assert(stateChange); - assert(iOrderbook.orderExists(orderBob.hash())); + assert(iRaindex.orderExists(orderBob.hash())); } } diff --git a/test/concrete/ob/OrderBookV6.addOrder.t.sol b/test/concrete/ob/RaindexV6.addOrder.t.sol similarity index 85% rename from test/concrete/ob/OrderBookV6.addOrder.t.sol rename to test/concrete/ob/RaindexV6.addOrder.t.sol index 0d95ad1687..b57166512c 100644 --- a/test/concrete/ob/OrderBookV6.addOrder.t.sol +++ b/test/concrete/ob/RaindexV6.addOrder.t.sol @@ -2,22 +2,22 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalRealTest} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; import {OrderConfigV4, EvaluableV4, TaskV2} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {IParserV2} from "rain.interpreter.interface/interface/IParserV2.sol"; -import {UnsupportedCalculateOutputs} from "../../../src/concrete/ob/OrderBookV6.sol"; +import {UnsupportedCalculateOutputs} from "../../../src/concrete/ob/RaindexV6.sol"; -/// @title OrderBookV6AddOrderTest -/// @notice A test harness for testing the OrderBookV6 addOrder function. -contract OrderBookV6AddOrderTest is OrderBookV6ExternalRealTest { +/// @title RaindexV6AddOrderTest +/// @notice A test harness for testing the RaindexV6 addOrder function. +contract RaindexV6AddOrderTest is RaindexV6ExternalRealTest { /// No sources deploys as we let this be a runtime check. /// forge-config: default.fuzz.runs = 100 function testAddOrderRealNoSourcesDeploys(address owner, OrderConfigV4 memory config) public { LibTestAddOrder.conformConfig(config, iInterpreter, iStore); config.evaluable.bytecode = hex""; vm.prank(owner); - iOrderbook.addOrder4(config, new TaskV2[](0)); + iRaindex.addOrder4(config, new TaskV2[](0)); } /// No handle IO reverts. @@ -28,7 +28,7 @@ contract OrderBookV6AddOrderTest is OrderBookV6ExternalRealTest { bytes memory bytecode = iParserV2.parse2(":;"); config.evaluable.bytecode = bytecode; vm.prank(owner); - iOrderbook.addOrder4(config, new TaskV2[](0)); + iRaindex.addOrder4(config, new TaskV2[](0)); } /// A stack of 0 for calculate order deploys. @@ -39,7 +39,7 @@ contract OrderBookV6AddOrderTest is OrderBookV6ExternalRealTest { bytes memory bytecode = iParserV2.parse2(":;:;"); config.evaluable.bytecode = bytecode; vm.prank(owner); - iOrderbook.addOrder4(config, new TaskV2[](0)); + iRaindex.addOrder4(config, new TaskV2[](0)); } /// A stack of 1 for calculate order reverts. @@ -50,7 +50,7 @@ contract OrderBookV6AddOrderTest is OrderBookV6ExternalRealTest { bytes memory bytecode = iParserV2.parse2("_:block-timestamp();:;"); config.evaluable.bytecode = bytecode; vm.prank(owner); - iOrderbook.addOrder4(config, new TaskV2[](0)); + iRaindex.addOrder4(config, new TaskV2[](0)); } /// A stack of 2 for calculate order deploys. @@ -60,7 +60,7 @@ contract OrderBookV6AddOrderTest is OrderBookV6ExternalRealTest { bytes memory bytecode = iParserV2.parse2("_ _:block-timestamp() chain-id();:;"); config.evaluable.bytecode = bytecode; vm.prank(owner); - iOrderbook.addOrder4(config, new TaskV2[](0)); + iRaindex.addOrder4(config, new TaskV2[](0)); } /// A stack of 3 for calculate order deploys. @@ -70,7 +70,7 @@ contract OrderBookV6AddOrderTest is OrderBookV6ExternalRealTest { bytes memory bytecode = iParserV2.parse2("_ _ _:block-timestamp() chain-id() block-number();:;"); config.evaluable.bytecode = bytecode; vm.prank(owner); - iOrderbook.addOrder4(config, new TaskV2[](0)); + iRaindex.addOrder4(config, new TaskV2[](0)); } /// Inputs for calculate order. Tests one input. @@ -81,7 +81,7 @@ contract OrderBookV6AddOrderTest is OrderBookV6ExternalRealTest { bytes memory bytecode = iParserV2.parse2("i:;:;"); config.evaluable.bytecode = bytecode; vm.prank(owner); - iOrderbook.addOrder4(config, new TaskV2[](0)); + iRaindex.addOrder4(config, new TaskV2[](0)); } /// Inputs for calculate order errors. Tests two inputs. @@ -92,7 +92,7 @@ contract OrderBookV6AddOrderTest is OrderBookV6ExternalRealTest { bytes memory bytecode = iParserV2.parse2("i0 i1:;:;"); config.evaluable.bytecode = bytecode; vm.prank(owner); - iOrderbook.addOrder4(config, new TaskV2[](0)); + iRaindex.addOrder4(config, new TaskV2[](0)); } /// Inputs for calculate order errors. This takes precedent over the same @@ -104,6 +104,6 @@ contract OrderBookV6AddOrderTest is OrderBookV6ExternalRealTest { bytes memory bytecode = iParserV2.parse2("i:;i:;"); config.evaluable.bytecode = bytecode; vm.prank(owner); - iOrderbook.addOrder4(config, new TaskV2[](0)); + iRaindex.addOrder4(config, new TaskV2[](0)); } } diff --git a/test/concrete/ob/OrderBookV6.clear.badStack.t.sol b/test/concrete/ob/RaindexV6.clear.badStack.t.sol similarity index 92% rename from test/concrete/ob/OrderBookV6.clear.badStack.t.sol rename to test/concrete/ob/RaindexV6.clear.badStack.t.sol index 64ecbb4cc2..445be19ca6 100644 --- a/test/concrete/ob/OrderBookV6.clear.badStack.t.sol +++ b/test/concrete/ob/RaindexV6.clear.badStack.t.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalRealTest} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; import { OrderConfigV4, @@ -12,10 +12,10 @@ import { SignedContextV1, TaskV2 } from "rain.raindex.interface/interface/IRaindexV6.sol"; -import {UnsupportedCalculateOutputs} from "../../../src/concrete/ob/OrderBookV6.sol"; +import {UnsupportedCalculateOutputs} from "../../../src/concrete/ob/RaindexV6.sol"; import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -contract OrderBookV6ClearOrderBadStackTest is OrderBookV6ExternalRealTest { +contract RaindexV6ClearOrderBadStackTest is RaindexV6ExternalRealTest { function checkBadStack( address alice, address bob, @@ -43,13 +43,13 @@ contract OrderBookV6ClearOrderBadStackTest is OrderBookV6ExternalRealTest { OrderV4(bob, configBob.evaluable, configBob.validInputs, configBob.validOutputs, configBob.nonce); vm.prank(alice); - iOrderbook.addOrder4(configAlice, new TaskV2[](0)); + iRaindex.addOrder4(configAlice, new TaskV2[](0)); vm.prank(bob); - iOrderbook.addOrder4(configBob, new TaskV2[](0)); + iRaindex.addOrder4(configBob, new TaskV2[](0)); vm.expectRevert(abi.encodeWithSelector(UnsupportedCalculateOutputs.selector, badStackHeight)); - iOrderbook.clear3( + iRaindex.clear3( orderAlice, orderBob, ClearConfigV2(0, 0, 0, 0, 0, 0), new SignedContextV1[](0), new SignedContextV1[](0) ); } diff --git a/test/concrete/ob/OrderBookV6.clear.context.t.sol b/test/concrete/ob/RaindexV6.clear.context.t.sol similarity index 94% rename from test/concrete/ob/OrderBookV6.clear.context.t.sol rename to test/concrete/ob/RaindexV6.clear.context.t.sol index d48692a787..ecd96c62ba 100644 --- a/test/concrete/ob/OrderBookV6.clear.context.t.sol +++ b/test/concrete/ob/RaindexV6.clear.context.t.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalRealTest} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; import { OrderConfigV4, @@ -27,7 +27,7 @@ struct ClearContextVaultIds { bytes32 bobOutputVaultId; } -contract OrderBookV6ClearOrderContextTest is OrderBookV6ExternalRealTest { +contract RaindexV6ClearOrderContextTest is RaindexV6ExternalRealTest { using Strings for address; using Strings for uint256; using LibDecimalFloat for Float; @@ -85,9 +85,9 @@ contract OrderBookV6ClearOrderContextTest is OrderBookV6ExternalRealTest { string.concat( ioPart, ":ensure(equal-to(output-vault-before() 100) \"output vault before\"),", - ":ensure(equal-to(orderbook() ", - address(iOrderbook).toHexString(), - ") \"OrderBook\"),", + ":ensure(equal-to(raindex() ", + address(iRaindex).toHexString(), + ") \"Raindex\"),", ":ensure(equal-to(order-clearer() ", address(this).toHexString(), ") \"clearer\"),", @@ -127,11 +127,11 @@ contract OrderBookV6ClearOrderContextTest is OrderBookV6ExternalRealTest { } else { vm.mockCall( token, - abi.encodeWithSelector(IERC20.transferFrom.selector, owner, address(iOrderbook)), + abi.encodeWithSelector(IERC20.transferFrom.selector, owner, address(iRaindex)), abi.encode(true) ); vm.prank(owner); - iOrderbook.deposit4(token, vaultId, LibDecimalFloat.packLossless(amount, exponent), new TaskV2[](0)); + iRaindex.deposit4(token, vaultId, LibDecimalFloat.packLossless(amount, exponent), new TaskV2[](0)); } } @@ -230,10 +230,10 @@ contract OrderBookV6ClearOrderContextTest is OrderBookV6ExternalRealTest { OrderV4(bob, configBob.evaluable, configBob.validInputs, configBob.validOutputs, configBob.nonce); vm.prank(alice); - iOrderbook.addOrder4(configAlice, new TaskV2[](0)); + iRaindex.addOrder4(configAlice, new TaskV2[](0)); vm.prank(bob); - iOrderbook.addOrder4(configBob, new TaskV2[](0)); + iRaindex.addOrder4(configBob, new TaskV2[](0)); setupOutputVault(address(iToken1), alice, vaultIds.aliceOutputVaultId, 100e6, -6, 6); setupOutputVault(address(iToken0), bob, vaultIds.bobOutputVaultId, 100e12, -12, 12); @@ -245,7 +245,7 @@ contract OrderBookV6ClearOrderContextTest is OrderBookV6ExternalRealTest { mockVault0Input(address(iToken0), alice, 3e12); } - iOrderbook.clear3( + iRaindex.clear3( orderAlice, orderBob, ClearConfigV2(0, 0, 0, 0, 0, 0), new SignedContextV1[](0), new SignedContextV1[](0) ); } diff --git a/test/concrete/ob/OrderBookV6.clear.handleIO.revert.t.sol b/test/concrete/ob/RaindexV6.clear.handleIO.revert.t.sol similarity index 91% rename from test/concrete/ob/OrderBookV6.clear.handleIO.revert.t.sol rename to test/concrete/ob/RaindexV6.clear.handleIO.revert.t.sol index f9aea68953..33b9853844 100644 --- a/test/concrete/ob/OrderBookV6.clear.handleIO.revert.t.sol +++ b/test/concrete/ob/RaindexV6.clear.handleIO.revert.t.sol @@ -3,7 +3,7 @@ pragma solidity =0.8.25; import {Vm} from "forge-std/Vm.sol"; -import {OrderBookV6ExternalRealTest} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import { ClearConfigV2, OrderV4, @@ -18,10 +18,10 @@ import {SourceIndexOutOfBounds} from "rain.interpreter.interface/error/ErrByteco import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibTestTakeOrder} from "test/util/lib/LibTestTakeOrder.sol"; -/// @title OrderBookV6ClearHandleIORevertTest -/// @notice A test harness for testing the OrderBook clear function will run +/// @title RaindexV6ClearHandleIORevertTest +/// @notice A test harness for testing the Raindex clear function will run /// handle IO and revert if it fails. -contract OrderBookV6ClearHandleIORevertTest is OrderBookV6ExternalRealTest { +contract RaindexV6ClearHandleIORevertTest is RaindexV6ExternalRealTest { using LibDecimalFloat for Float; function userDeposit(bytes memory rainString, address owner, address inputToken, address outputToken) @@ -52,7 +52,7 @@ contract OrderBookV6ClearHandleIORevertTest is OrderBookV6ExternalRealTest { // Etch with invalid. vm.etch(inputToken, hex"fe"); vm.etch(outputToken, hex"fe"); - // Mock every call to output as a success, so the orderbook thinks it + // Mock every call to output as a success, so the raindex thinks it // is transferring tokens. vm.mockCall(inputToken, bytes(""), abi.encode(true)); vm.mockCall(outputToken, bytes(""), abi.encode(true)); @@ -62,10 +62,10 @@ contract OrderBookV6ClearHandleIORevertTest is OrderBookV6ExternalRealTest { mockVault0Output(outputToken, owner, uint256(int256(type(int224).max))); } else { vm.prank(owner); - iOrderbook.deposit4( + iRaindex.deposit4( outputToken, vaultId, LibDecimalFloat.packLossless(type(int224).max, 0), new TaskV2[](0) ); - Float balance = iOrderbook.vaultBalance2(owner, outputToken, vaultId); + Float balance = iRaindex.vaultBalance2(owner, outputToken, vaultId); assertTrue(balance.eq(LibDecimalFloat.packLossless(type(int224).max, 0))); } if (inputVaultId == bytes32(0)) { @@ -78,7 +78,7 @@ contract OrderBookV6ClearHandleIORevertTest is OrderBookV6ExternalRealTest { vm.prank(owner); vm.recordLogs(); - iOrderbook.addOrder4(config, new TaskV2[](0)); + iRaindex.addOrder4(config, new TaskV2[](0)); Vm.Log[] memory entries = vm.getRecordedLogs(); assertEq(entries.length, 1); @@ -117,12 +117,12 @@ contract OrderBookV6ClearHandleIORevertTest is OrderBookV6ExternalRealTest { if (aliceErr.length > 0) { vm.expectRevert(aliceErr); } - iOrderbook.clear3(aliceOrder, bobOrder, clearConfig, new SignedContextV1[](0), new SignedContextV1[](0)); + iRaindex.clear3(aliceOrder, bobOrder, clearConfig, new SignedContextV1[](0), new SignedContextV1[](0)); if (bobErr.length > 0) { vm.expectRevert(bobErr); } - iOrderbook.clear3(bobOrder, aliceOrder, clearConfig, new SignedContextV1[](0), new SignedContextV1[](0)); + iRaindex.clear3(bobOrder, aliceOrder, clearConfig, new SignedContextV1[](0), new SignedContextV1[](0)); } function testClearOrderHandleIO0() external { diff --git a/test/concrete/ob/OrderBookV6.clear.mock.t.sol b/test/concrete/ob/RaindexV6.clear.mock.t.sol similarity index 96% rename from test/concrete/ob/OrderBookV6.clear.mock.t.sol rename to test/concrete/ob/RaindexV6.clear.mock.t.sol index 034664d05c..b5ad3e952e 100644 --- a/test/concrete/ob/OrderBookV6.clear.mock.t.sol +++ b/test/concrete/ob/RaindexV6.clear.mock.t.sol @@ -5,7 +5,7 @@ pragma solidity =0.8.25; import {Test, stdError} from "forge-std/Test.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import {OrderBookV6ExternalMockTest} from "test/util/abstract/OrderBookV6ExternalMockTest.sol"; +import {RaindexV6ExternalMockTest} from "test/util/abstract/RaindexV6ExternalMockTest.sol"; import { OrderConfigV4, OrderV4, @@ -18,7 +18,7 @@ import { Float } from "rain.raindex.interface/interface/IRaindexV6.sol"; import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; -import {NotOrderOwner, StackItem, NegativeBounty, ClearZeroAmount} from "../../../src/concrete/ob/OrderBookV6.sol"; +import {NotOrderOwner, StackItem, NegativeBounty, ClearZeroAmount} from "../../../src/concrete/ob/RaindexV6.sol"; import {LibNamespace} from "rain.interpreter.interface/lib/ns/LibNamespace.sol"; import {StateNamespace, EvalV4, SourceIndexV2} from "rain.interpreter.interface/interface/IInterpreterV4.sol"; import { @@ -42,9 +42,9 @@ contract MockInterpreter { } } -/// @title OrderBookV6ClearTest +/// @title RaindexV6ClearTest /// Tests clearing an order. -contract OrderBookV6ClearTest is OrderBookV6ExternalMockTest { +contract RaindexV6ClearTest is RaindexV6ExternalMockTest { using LibFixedPointDecimalArithmeticOpenZeppelin for uint256; using Math for uint256; using LibDecimalFloat for Float; @@ -58,12 +58,12 @@ contract OrderBookV6ClearTest is OrderBookV6ExternalMockTest { // zero case the clear will internally do a transfer from. vm.mockCall( token, - abi.encodeWithSelector(IERC20.transferFrom.selector, depositor, address(iOrderbook), amount18), + abi.encodeWithSelector(IERC20.transferFrom.selector, depositor, address(iRaindex), amount18), abi.encode(true) ); vm.prank(depositor); - iOrderbook.deposit4(address(token), vaultId, amount, new TaskV2[](0)); - Float balance = iOrderbook.vaultBalance2(depositor, token, vaultId); + iRaindex.deposit4(address(token), vaultId, amount, new TaskV2[](0)); + Float balance = iRaindex.vaultBalance2(depositor, token, vaultId); assertTrue(balance.eq(amount)); } } @@ -148,40 +148,40 @@ contract OrderBookV6ClearTest is OrderBookV6ExternalMockTest { ); if (clear.aliceConfig.validInputs[0].vaultId != bytes32(0)) { - Float aliceInputBalance = iOrderbook.vaultBalance2( + Float aliceInputBalance = iRaindex.vaultBalance2( clear.alice, clear.aliceConfig.validInputs[0].token, clear.aliceConfig.validInputs[0].vaultId ); assertTrue(aliceInputBalance.isZero()); } if (clear.aliceConfig.validOutputs[0].vaultId != bytes32(0)) { - Float aliceOutputBalance = iOrderbook.vaultBalance2( + Float aliceOutputBalance = iRaindex.vaultBalance2( clear.alice, clear.aliceConfig.validOutputs[0].token, clear.aliceConfig.validOutputs[0].vaultId ); assertTrue(aliceOutputBalance.eq(clear.aliceAmount)); } if (clear.bobConfig.validInputs[0].vaultId != bytes32(0)) { - Float bobInputBalance = iOrderbook.vaultBalance2( + Float bobInputBalance = iRaindex.vaultBalance2( clear.bob, clear.bobConfig.validInputs[0].token, clear.bobConfig.validInputs[0].vaultId ); assertTrue(bobInputBalance.isZero()); } if (clear.bobConfig.validOutputs[0].vaultId != bytes32(0)) { - Float bobOutputBalance = iOrderbook.vaultBalance2( + Float bobOutputBalance = iRaindex.vaultBalance2( clear.bob, clear.bobConfig.validOutputs[0].token, clear.bobConfig.validOutputs[0].vaultId ); assertTrue(bobOutputBalance.eq(clear.bobAmount), "Bob output balance should be equal to bob amount"); } { - Float aliceBountyBalance = iOrderbook.vaultBalance2( + Float aliceBountyBalance = iRaindex.vaultBalance2( clear.bountyBot, clear.aliceConfig.validOutputs[0].token, clear.aliceBountyVaultId ); assertTrue(aliceBountyBalance.isZero()); } { - Float bobBountyBalance = iOrderbook.vaultBalance2( + Float bobBountyBalance = iRaindex.vaultBalance2( clear.bountyBot, clear.bobConfig.validOutputs[0].token, clear.bobBountyVaultId ); assertTrue(bobBountyBalance.isZero()); @@ -270,7 +270,7 @@ contract OrderBookV6ClearTest is OrderBookV6ExternalMockTest { ); vm.mockCall( clear.aliceConfig.validOutputs[0].token, - abi.encodeWithSelector(IERC20.transferFrom.selector, clear.alice, address(iOrderbook), amount18), + abi.encodeWithSelector(IERC20.transferFrom.selector, clear.alice, address(iRaindex), amount18), abi.encode(true) ); @@ -289,7 +289,7 @@ contract OrderBookV6ClearTest is OrderBookV6ExternalMockTest { vm.expectCall( clear.aliceConfig.validOutputs[0].token, abi.encodeWithSelector( - IERC20.transferFrom.selector, clear.alice, address(iOrderbook), amount18 + IERC20.transferFrom.selector, clear.alice, address(iRaindex), amount18 ), 1 ); @@ -358,7 +358,7 @@ contract OrderBookV6ClearTest is OrderBookV6ExternalMockTest { ); vm.mockCall( clear.bobConfig.validOutputs[0].token, - abi.encodeWithSelector(IERC20.transferFrom.selector, clear.bob, address(iOrderbook), bobAmount18), + abi.encodeWithSelector(IERC20.transferFrom.selector, clear.bob, address(iRaindex), bobAmount18), abi.encode(true) ); @@ -377,7 +377,7 @@ contract OrderBookV6ClearTest is OrderBookV6ExternalMockTest { vm.expectCall( clear.bobConfig.validOutputs[0].token, abi.encodeWithSelector( - IERC20.transferFrom.selector, clear.bob, address(iOrderbook), bobAmount18 + IERC20.transferFrom.selector, clear.bob, address(iRaindex), bobAmount18 ), 1 ); @@ -389,13 +389,13 @@ contract OrderBookV6ClearTest is OrderBookV6ExternalMockTest { if (clear.expectedError.length > 0) { vm.expectRevert(clear.expectedError); } - iOrderbook.clear3(aliceOrder, bobOrder, configClear, new SignedContextV1[](0), new SignedContextV1[](0)); + iRaindex.clear3(aliceOrder, bobOrder, configClear, new SignedContextV1[](0), new SignedContextV1[](0)); } if (clear.expectedError.length == 0) { if (clear.aliceConfig.validOutputs[0].vaultId != bytes32(0)) { assertTrue( - iOrderbook.vaultBalance2( + iRaindex.vaultBalance2( clear.alice, clear.aliceConfig.validOutputs[0].token, clear.aliceConfig.validOutputs[0].vaultId @@ -406,7 +406,7 @@ contract OrderBookV6ClearTest is OrderBookV6ExternalMockTest { if (clear.aliceConfig.validInputs[0].vaultId != bytes32(0)) { assertTrue( - iOrderbook.vaultBalance2( + iRaindex.vaultBalance2( clear.alice, clear.aliceConfig.validInputs[0].token, clear.aliceConfig.validInputs[0].vaultId @@ -417,7 +417,7 @@ contract OrderBookV6ClearTest is OrderBookV6ExternalMockTest { if (clear.bobConfig.validOutputs[0].vaultId != bytes32(0)) { assertTrue( - iOrderbook.vaultBalance2( + iRaindex.vaultBalance2( clear.bob, clear.bobConfig.validOutputs[0].token, clear.bobConfig.validOutputs[0].vaultId ).eq(clear.bobAmount.sub(clear.expectedBobOutput)), "Bob output vault" @@ -426,7 +426,7 @@ contract OrderBookV6ClearTest is OrderBookV6ExternalMockTest { if (clear.bobConfig.validInputs[0].vaultId != bytes32(0)) { assertTrue( - iOrderbook.vaultBalance2( + iRaindex.vaultBalance2( clear.bob, clear.bobConfig.validInputs[0].token, clear.bobConfig.validInputs[0].vaultId ).eq(clear.expectedBobInput), "Bob input vault" @@ -434,24 +434,24 @@ contract OrderBookV6ClearTest is OrderBookV6ExternalMockTest { } assertTrue( - iOrderbook.vaultBalance2( + iRaindex.vaultBalance2( clear.bountyBot, clear.aliceConfig.validOutputs[0].token, clear.aliceBountyVaultId ).eq(clear.expectedAliceOutput.sub(clear.expectedBobInput)), "Alice bounty" ); assertTrue( - iOrderbook.vaultBalance2( + iRaindex.vaultBalance2( clear.bountyBot, clear.aliceConfig.validInputs[0].token, clear.aliceBountyVaultId ).isZero(), "Alice bounty input" ); assertTrue( - iOrderbook.vaultBalance2(clear.bountyBot, clear.bobConfig.validOutputs[0].token, clear.bobBountyVaultId) + iRaindex.vaultBalance2(clear.bountyBot, clear.bobConfig.validOutputs[0].token, clear.bobBountyVaultId) .eq(clear.expectedBobOutput.sub(clear.expectedAliceInput)), "Bob bounty" ); assertTrue( - iOrderbook.vaultBalance2(clear.bountyBot, clear.bobConfig.validInputs[0].token, clear.bobBountyVaultId) + iRaindex.vaultBalance2(clear.bountyBot, clear.bobConfig.validInputs[0].token, clear.bobBountyVaultId) .eq(LibDecimalFloat.packLossless(0, 0)), "Bob bounty input" ); diff --git a/test/concrete/ob/OrderBookV6.clear.sameOwner.t.sol b/test/concrete/ob/RaindexV6.clear.sameOwner.t.sol similarity index 81% rename from test/concrete/ob/OrderBookV6.clear.sameOwner.t.sol rename to test/concrete/ob/RaindexV6.clear.sameOwner.t.sol index 24e83f65a7..e7b6eb6e76 100644 --- a/test/concrete/ob/OrderBookV6.clear.sameOwner.t.sol +++ b/test/concrete/ob/RaindexV6.clear.sameOwner.t.sol @@ -2,15 +2,15 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalRealTest} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; import {LibTestTakeOrder} from "test/util/lib/LibTestTakeOrder.sol"; import {OrderConfigV4, OrderV4, ClearConfigV2, TaskV2} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {SignedContextV1} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; -import {SameOwner} from "../../../src/concrete/ob/OrderBookV6.sol"; +import {SameOwner} from "../../../src/concrete/ob/RaindexV6.sol"; /// Clearing two orders with the same owner must revert with SameOwner. -contract OrderBookV6ClearSameOwnerTest is OrderBookV6ExternalRealTest { +contract RaindexV6ClearSameOwnerTest is RaindexV6ExternalRealTest { /// forge-config: default.fuzz.runs = 10 function testClearSameOwner(address alice, OrderConfigV4 memory configAlice, OrderConfigV4 memory configBob) external @@ -27,16 +27,16 @@ contract OrderBookV6ClearSameOwnerTest is OrderBookV6ExternalRealTest { // Add both orders as the same owner. vm.prank(alice); vm.recordLogs(); - iOrderbook.addOrder4(configAlice, new TaskV2[](0)); + iRaindex.addOrder4(configAlice, new TaskV2[](0)); OrderV4 memory orderAlice = LibTestTakeOrder.extractOrderFromLogs(vm.getRecordedLogs()); vm.prank(alice); vm.recordLogs(); - iOrderbook.addOrder4(configBob, new TaskV2[](0)); + iRaindex.addOrder4(configBob, new TaskV2[](0)); OrderV4 memory orderBob = LibTestTakeOrder.extractOrderFromLogs(vm.getRecordedLogs()); vm.expectRevert(abi.encodeWithSelector(SameOwner.selector)); - iOrderbook.clear3( + iRaindex.clear3( orderAlice, orderBob, ClearConfigV2(0, 0, 0, 0, 0, 0), new SignedContextV1[](0), new SignedContextV1[](0) ); } diff --git a/test/concrete/ob/OrderBookV6.clear.sameToken.t.sol b/test/concrete/ob/RaindexV6.clear.sameToken.t.sol similarity index 80% rename from test/concrete/ob/OrderBookV6.clear.sameToken.t.sol rename to test/concrete/ob/RaindexV6.clear.sameToken.t.sol index 06389d2df7..3b1cb84cc7 100644 --- a/test/concrete/ob/OrderBookV6.clear.sameToken.t.sol +++ b/test/concrete/ob/RaindexV6.clear.sameToken.t.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalRealTest} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import { OrderConfigV4, OrderV4, @@ -12,9 +12,9 @@ import { TaskV2 } from "rain.raindex.interface/interface/IRaindexV6.sol"; import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; -import {TokenSelfTrade} from "../../../src/concrete/ob/OrderBookV6.sol"; +import {TokenSelfTrade} from "../../../src/concrete/ob/RaindexV6.sol"; -contract OrderBookV6ClearSameTokenTest is OrderBookV6ExternalRealTest { +contract RaindexV6ClearSameTokenTest is RaindexV6ExternalRealTest { /// forge-config: default.fuzz.runs = 10 function testClearSameToken( address alice, @@ -37,13 +37,13 @@ contract OrderBookV6ClearSameTokenTest is OrderBookV6ExternalRealTest { OrderV4(bob, configBob.evaluable, configBob.validInputs, configBob.validOutputs, configBob.nonce); vm.prank(alice); - iOrderbook.addOrder4(configAlice, new TaskV2[](0)); + iRaindex.addOrder4(configAlice, new TaskV2[](0)); vm.prank(bob); - iOrderbook.addOrder4(configBob, new TaskV2[](0)); + iRaindex.addOrder4(configBob, new TaskV2[](0)); vm.expectRevert(abi.encodeWithSelector(TokenSelfTrade.selector)); - iOrderbook.clear3( + iRaindex.clear3( orderAlice, orderBob, ClearConfigV2(0, 0, 0, 0, 0, 0), new SignedContextV1[](0), new SignedContextV1[](0) ); } diff --git a/test/concrete/ob/OrderBookV6.clear.zeroAmount.t.sol b/test/concrete/ob/RaindexV6.clear.zeroAmount.t.sol similarity index 82% rename from test/concrete/ob/OrderBookV6.clear.zeroAmount.t.sol rename to test/concrete/ob/RaindexV6.clear.zeroAmount.t.sol index b1b61c457a..eec1aed4b8 100644 --- a/test/concrete/ob/OrderBookV6.clear.zeroAmount.t.sol +++ b/test/concrete/ob/RaindexV6.clear.zeroAmount.t.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalRealTest} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import { OrderConfigV4, OrderV4, @@ -11,9 +11,9 @@ import { ClearConfigV2 } from "rain.raindex.interface/interface/IRaindexV6.sol"; import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; -import {ClearZeroAmount} from "../../../src/concrete/ob/OrderBookV6.sol"; +import {ClearZeroAmount} from "../../../src/concrete/ob/RaindexV6.sol"; -contract OrderBookV6ClearZeroAmountTest is OrderBookV6ExternalRealTest { +contract RaindexV6ClearZeroAmountTest is RaindexV6ExternalRealTest { /// forge-config: default.fuzz.runs = 10 function testClearZeroAmount( address alice, @@ -41,12 +41,12 @@ contract OrderBookV6ClearZeroAmountTest is OrderBookV6ExternalRealTest { OrderV4(bob, configBob.evaluable, configBob.validInputs, configBob.validOutputs, configBob.nonce); vm.prank(alice); - iOrderbook.addOrder4(configAlice, new TaskV2[](0)); + iRaindex.addOrder4(configAlice, new TaskV2[](0)); vm.prank(bob); - iOrderbook.addOrder4(configBob, new TaskV2[](0)); + iRaindex.addOrder4(configBob, new TaskV2[](0)); vm.expectRevert(ClearZeroAmount.selector); - iOrderbook.clear3( + iRaindex.clear3( orderAlice, orderBob, ClearConfigV2(0, 0, 0, 0, 0, 0), new SignedContextV1[](0), new SignedContextV1[](0) ); } diff --git a/test/concrete/ob/OrderBookV6.deposit.entask.t.sol b/test/concrete/ob/RaindexV6.deposit.entask.t.sol similarity index 88% rename from test/concrete/ob/OrderBookV6.deposit.entask.t.sol rename to test/concrete/ob/RaindexV6.deposit.entask.t.sol index 0c43f9e546..ae7efa56ba 100644 --- a/test/concrete/ob/OrderBookV6.deposit.entask.t.sol +++ b/test/concrete/ob/RaindexV6.deposit.entask.t.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalRealTest, LibDecimalFloat, Float} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest, LibDecimalFloat, Float} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import {OrderConfigV4, EvaluableV4, TaskV2, SignedContextV1} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; @@ -10,14 +10,14 @@ import {LibFormatDecimalFloat} from "rain.math.float/lib/format/LibFormatDecimal import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol"; -contract OrderBookV6DepositEnactTest is OrderBookV6ExternalRealTest { +contract RaindexV6DepositEnactTest is RaindexV6ExternalRealTest { using Strings for address; using Strings for uint256; using LibDecimalFloat for Float; using LibFormatDecimalFloat for Float; function checkReentrancyRW() internal view { - (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iOrderbook)); + (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iRaindex)); // ReentrancyGuard.REENTRANCY_GUARD_STORAGE bytes32 reentrancyGuardStorage = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00; @@ -45,7 +45,7 @@ contract OrderBookV6DepositEnactTest is OrderBookV6ExternalRealTest { vm.startPrank(owner); vm.mockCall( address(iToken0), - abi.encodeWithSelector(IERC20.transferFrom.selector, owner, address(iOrderbook), amount18), + abi.encodeWithSelector(IERC20.transferFrom.selector, owner, address(iRaindex), amount18), abi.encode(true) ); @@ -55,7 +55,7 @@ contract OrderBookV6DepositEnactTest is OrderBookV6ExternalRealTest { TaskV2(EvaluableV4(iInterpreter, iStore, iParserV2.parse2(evalStrings[i])), new SignedContextV1[](0)); } vm.record(); - iOrderbook.deposit4(address(iToken0), vaultId, amount, actions); + iRaindex.deposit4(address(iToken0), vaultId, amount, actions); checkReentrancyRW(); (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iStore)); assert(reads.length == expectedReads); @@ -64,7 +64,7 @@ contract OrderBookV6DepositEnactTest is OrderBookV6ExternalRealTest { } /// forge-config: default.fuzz.runs = 10 - function testOrderBookDepositEnactEmptyNoop(address alice, bytes32 vaultId, uint256 amount18) external { + function testRaindexDepositEnactEmptyNoop(address alice, bytes32 vaultId, uint256 amount18) external { amount18 = bound(amount18, 1, uint256(int256(type(int224).max))); Float amount = LibDecimalFloat.fromFixedDecimalLosslessPacked(amount18, 18); vm.assume(amount.gt(LibDecimalFloat.packLossless(0, 0))); @@ -73,7 +73,7 @@ contract OrderBookV6DepositEnactTest is OrderBookV6ExternalRealTest { } /// forge-config: default.fuzz.runs = 10 - function testOrderBookDepositEnactOneStateless(address alice, bytes32 vaultId, uint256 amount18) external { + function testRaindexDepositEnactOneStateless(address alice, bytes32 vaultId, uint256 amount18) external { amount18 = bound(amount18, 1, uint256(int256(type(int224).max))); Float amount = LibDecimalFloat.fromFixedDecimalLosslessPacked(amount18, 18); vm.assume(amount.gt(LibDecimalFloat.packLossless(0, 0))); @@ -83,7 +83,7 @@ contract OrderBookV6DepositEnactTest is OrderBookV6ExternalRealTest { } /// forge-config: default.fuzz.runs = 10 - function testOrderBookDepositEnactOneReadState(address alice, bytes32 vaultId, uint256 amount18) external { + function testRaindexDepositEnactOneReadState(address alice, bytes32 vaultId, uint256 amount18) external { amount18 = bound(amount18, 1, uint256(int256(type(int224).max))); Float amount = LibDecimalFloat.fromFixedDecimalLosslessPacked(amount18, 18); vm.assume(amount.gt(LibDecimalFloat.packLossless(0, 0))); @@ -95,7 +95,7 @@ contract OrderBookV6DepositEnactTest is OrderBookV6ExternalRealTest { } /// forge-config: default.fuzz.runs = 10 - function testOrderBookDepositEvalWriteStateSingle(address alice, bytes32 vaultId, uint256 amount18) external { + function testRaindexDepositEvalWriteStateSingle(address alice, bytes32 vaultId, uint256 amount18) external { amount18 = bound(amount18, 1, uint256(int256(type(int224).max))); // amount18 is bound above so safe to typecast. // forge-lint: disable-next-line(unsafe-typecast) @@ -111,7 +111,7 @@ contract OrderBookV6DepositEnactTest is OrderBookV6ExternalRealTest { } /// forge-config: default.fuzz.runs = 10 - function testOrderBookDepositEvalWriteStateSequential(address alice, bytes32 vaultId, uint256 amount18) external { + function testRaindexDepositEvalWriteStateSequential(address alice, bytes32 vaultId, uint256 amount18) external { amount18 = bound(amount18, 1, uint256(int256(type(int224).max))); // amount18 is bound above so safe to typecast. // forge-lint: disable-next-line(unsafe-typecast) @@ -133,7 +133,7 @@ contract OrderBookV6DepositEnactTest is OrderBookV6ExternalRealTest { } /// forge-config: default.fuzz.runs = 10 - function testOrderBookDepositEvalWriteStateDifferentOwnersNamespaced( + function testRaindexDepositEvalWriteStateDifferentOwnersNamespaced( address alice, address bob, bytes32 vaultId, @@ -198,9 +198,9 @@ contract OrderBookV6DepositEnactTest is OrderBookV6ExternalRealTest { evals[0] = bytes( string.concat( usingWordsFrom, - ":ensure(equal-to(orderbook() ", - address(iOrderbook).toHexString(), - ") \"orderbook is iOrderbook\");" + ":ensure(equal-to(raindex() ", + address(iRaindex).toHexString(), + ") \"raindex is iRaindex\");" ) ); evals[1] = bytes( @@ -252,7 +252,7 @@ contract OrderBookV6DepositEnactTest is OrderBookV6ExternalRealTest { vm.startPrank(alice); vm.mockCall( address(iToken0), - abi.encodeWithSelector(IERC20.transferFrom.selector, alice, address(iOrderbook), amount18), + abi.encodeWithSelector(IERC20.transferFrom.selector, alice, address(iRaindex), amount18), abi.encode(true) ); @@ -263,11 +263,11 @@ contract OrderBookV6DepositEnactTest is OrderBookV6ExternalRealTest { TaskV2[] memory actions = evalsToActions(evals); - assertTrue(iOrderbook.vaultBalance2(alice, address(iToken0), vaultId).isZero()); + assertTrue(iRaindex.vaultBalance2(alice, address(iToken0), vaultId).isZero()); vm.expectRevert("revert in action"); - iOrderbook.deposit4(address(iToken0), vaultId, amount, actions); + iRaindex.deposit4(address(iToken0), vaultId, amount, actions); - assertTrue(iOrderbook.vaultBalance2(alice, address(iToken0), vaultId).isZero()); + assertTrue(iRaindex.vaultBalance2(alice, address(iToken0), vaultId).isZero()); } } diff --git a/test/concrete/ob/OrderBookV6.deposit.t.sol b/test/concrete/ob/RaindexV6.deposit.t.sol similarity index 85% rename from test/concrete/ob/OrderBookV6.deposit.t.sol rename to test/concrete/ob/RaindexV6.deposit.t.sol index f71048daf1..f80cf22989 100644 --- a/test/concrete/ob/OrderBookV6.deposit.t.sol +++ b/test/concrete/ob/RaindexV6.deposit.t.sol @@ -4,7 +4,7 @@ pragma solidity =0.8.25; import {stdError} from "forge-std/Test.sol"; import {REVERTING_MOCK_BYTECODE, CONSOLE_ADDRESS} from "test/util/lib/LibTestConstants.sol"; -import {OrderBookV6ExternalMockTest} from "test/util/abstract/OrderBookV6ExternalMockTest.sol"; +import {RaindexV6ExternalMockTest} from "test/util/abstract/RaindexV6ExternalMockTest.sol"; import {TaskV2, EvaluableV4, IRaindexV6} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {Reenteroor} from "test/util/concrete/Reenteroor.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; @@ -13,9 +13,9 @@ import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/exten import {ReentrancyGuard} from "openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol"; import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; -/// @title OrderBookV6DepositTest +/// @title RaindexV6DepositTest /// Tests depositing to an order book. -contract OrderBookV6DepositTest is OrderBookV6ExternalMockTest { +contract RaindexV6DepositTest is RaindexV6ExternalMockTest { using LibDecimalFloat for Float; /// Tests that we can deposit some amount and view the new vault balance. @@ -26,14 +26,14 @@ contract OrderBookV6DepositTest is OrderBookV6ExternalMockTest { vm.prank(depositor); vm.mockCall( address(iToken0), - abi.encodeWithSelector(IERC20.transferFrom.selector, depositor, address(iOrderbook), amount18), + abi.encodeWithSelector(IERC20.transferFrom.selector, depositor, address(iRaindex), amount18), abi.encode(true) ); Float amount = LibDecimalFloat.fromFixedDecimalLosslessPacked(amount18, 18); - iOrderbook.deposit4(address(iToken0), vaultId, amount, new TaskV2[](0)); - assertTrue(iOrderbook.vaultBalance2(depositor, address(iToken0), vaultId).eq(amount)); + iRaindex.deposit4(address(iToken0), vaultId, amount, new TaskV2[](0)); + assertTrue(iRaindex.vaultBalance2(depositor, address(iToken0), vaultId).eq(amount)); } /// Depositing zero should revert. @@ -44,7 +44,7 @@ contract OrderBookV6DepositTest is OrderBookV6ExternalMockTest { vm.expectRevert( abi.encodeWithSelector(IRaindexV6.ZeroDepositAmount.selector, address(depositor), address(iToken0), vaultId) ); - iOrderbook.deposit4(address(iToken0), vaultId, LibDecimalFloat.packLossless(0, 0), new TaskV2[](0)); + iRaindex.deposit4(address(iToken0), vaultId, LibDecimalFloat.packLossless(0, 0), new TaskV2[](0)); } /// Depositing vaultID of zero should revert. @@ -52,7 +52,7 @@ contract OrderBookV6DepositTest is OrderBookV6ExternalMockTest { vm.assume(amount.gt(Float.wrap(0))); vm.prank(depositor); vm.expectRevert(abi.encodeWithSelector(IRaindexV6.ZeroVaultId.selector, address(depositor), address(token))); - iOrderbook.deposit4(token, bytes32(0), amount, new TaskV2[](0)); + iRaindex.deposit4(token, bytes32(0), amount, new TaskV2[](0)); } /// Test a warm deposit, which is the best case scenario for gas. In this @@ -63,19 +63,19 @@ contract OrderBookV6DepositTest is OrderBookV6ExternalMockTest { // warm up storage vm.mockCall( address(iToken0), - abi.encodeWithSelector(IERC20.transferFrom.selector, address(this), address(iOrderbook), 1), + abi.encodeWithSelector(IERC20.transferFrom.selector, address(this), address(iRaindex), 1), abi.encode(true) ); - iOrderbook.deposit4( + iRaindex.deposit4( address(iToken0), bytes32(uint256(0x01)), LibDecimalFloat.packLossless(1, -18), new TaskV2[](0) ); vm.mockCall( address(iToken0), - abi.encodeWithSelector(IERC20.transferFrom.selector, address(this), address(iOrderbook), 1), + abi.encodeWithSelector(IERC20.transferFrom.selector, address(this), address(iRaindex), 1), abi.encode(true) ); vm.resumeGasMetering(); - iOrderbook.deposit4( + iRaindex.deposit4( address(iToken0), bytes32(uint256(0x01)), LibDecimalFloat.packLossless(1, -18), new TaskV2[](0) ); } @@ -88,11 +88,11 @@ contract OrderBookV6DepositTest is OrderBookV6ExternalMockTest { vm.pauseGasMetering(); vm.mockCall( address(iToken0), - abi.encodeWithSelector(IERC20.transferFrom.selector, address(this), address(iOrderbook), 1), + abi.encodeWithSelector(IERC20.transferFrom.selector, address(this), address(iRaindex), 1), abi.encode(true) ); vm.resumeGasMetering(); - iOrderbook.deposit4( + iRaindex.deposit4( address(iToken0), bytes32(uint256(0x01)), LibDecimalFloat.packLossless(1, -18), new TaskV2[](0) ); } @@ -107,18 +107,18 @@ contract OrderBookV6DepositTest is OrderBookV6ExternalMockTest { // The token contract always reverts when not mocked. vm.prank(depositor); vm.expectRevert(); - iOrderbook.deposit4(address(iToken0), vaultId, amount, new TaskV2[](0)); + iRaindex.deposit4(address(iToken0), vaultId, amount, new TaskV2[](0)); // Mocking the token to return false should also revert. vm.prank(depositor); vm.mockCall( address(iToken0), - abi.encodeWithSelector(IERC20.transferFrom.selector, depositor, address(iOrderbook), amount18), + abi.encodeWithSelector(IERC20.transferFrom.selector, depositor, address(iRaindex), amount18), abi.encode(false) ); // This error string appears when the call completes but returns false. vm.expectRevert(abi.encodeWithSelector(SafeERC20.SafeERC20FailedOperation.selector, address(iToken0))); - iOrderbook.deposit4(address(iToken0), vaultId, amount, new TaskV2[](0)); + iRaindex.deposit4(address(iToken0), vaultId, amount, new TaskV2[](0)); } /// Defines a deposit to be used in testDepositMany. @@ -155,14 +155,14 @@ contract OrderBookV6DepositTest is OrderBookV6ExternalMockTest { for (uint256 i = 0; i < actions.length; i++) { vm.etch(actions[i].token, REVERTING_MOCK_BYTECODE); Float vaultBalanceBefore = - iOrderbook.vaultBalance2(actions[i].depositor, actions[i].token, actions[i].vaultId); + iRaindex.vaultBalance2(actions[i].depositor, actions[i].token, actions[i].vaultId); vm.prank(actions[i].depositor); vm.mockCall( actions[i].token, abi.encodeWithSelector( IERC20.transferFrom.selector, actions[i].depositor, - address(iOrderbook), + address(iRaindex), LibDecimalFloat.toFixedDecimalLossless(actions[i].amount, 18) ), abi.encode(true) @@ -174,8 +174,8 @@ contract OrderBookV6DepositTest is OrderBookV6ExternalMockTest { emit DepositV2(actions[i].depositor, actions[i].token, actions[i].vaultId, actions[i].amount18); vm.record(); vm.recordLogs(); - iOrderbook.deposit4(actions[i].token, actions[i].vaultId, actions[i].amount, new TaskV2[](0)); - (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iOrderbook)); + iRaindex.deposit4(actions[i].token, actions[i].vaultId, actions[i].amount, new TaskV2[](0)); + (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iRaindex)); assertEq(vm.getRecordedLogs().length, 1, "logs"); // - reentrancy guard x3 // - vault balance floats x2 @@ -185,7 +185,7 @@ contract OrderBookV6DepositTest is OrderBookV6ExternalMockTest { // // - vault balance x1 assertTrue(writes.length == 4 || writes.length == 3, "writes"); assertTrue( - iOrderbook.vaultBalance2(actions[i].depositor, actions[i].token, actions[i].vaultId) + iRaindex.vaultBalance2(actions[i].depositor, actions[i].token, actions[i].vaultId) .eq(actions[i].amount.add(vaultBalanceBefore)), "vault balance" ); @@ -200,13 +200,13 @@ contract OrderBookV6DepositTest is OrderBookV6ExternalMockTest { vm.prank(depositor); vm.mockCall( address(iToken0), - abi.encodeWithSelector(IERC20.transferFrom.selector, depositor, address(iOrderbook), amount18), + abi.encodeWithSelector(IERC20.transferFrom.selector, depositor, address(iRaindex), amount18), abi.encode(true) ); vm.expectEmit(false, false, false, true); emit DepositV2(depositor, address(iToken0), vaultId, amount18); Float amount = LibDecimalFloat.fromFixedDecimalLosslessPacked(amount18, 18); - iOrderbook.deposit4(address(iToken0), vaultId, amount, new TaskV2[](0)); + iRaindex.deposit4(address(iToken0), vaultId, amount, new TaskV2[](0)); } /// Depositing should NOT allow reentrancy. @@ -234,6 +234,6 @@ contract OrderBookV6DepositTest is OrderBookV6ExternalMockTest { abi.encodeWithSelector(IRaindexV6.deposit4.selector, reToken, reVaultId, reAmount, new TaskV2[](0)) ); vm.expectRevert(abi.encodeWithSelector(ReentrancyGuard.ReentrancyGuardReentrantCall.selector)); - iOrderbook.deposit4(address(reenteroor), vaultId, amount, new TaskV2[](0)); + iRaindex.deposit4(address(reenteroor), vaultId, amount, new TaskV2[](0)); } } diff --git a/test/concrete/ob/OrderBookV6.entask.t.sol b/test/concrete/ob/RaindexV6.entask.t.sol similarity index 86% rename from test/concrete/ob/OrderBookV6.entask.t.sol rename to test/concrete/ob/RaindexV6.entask.t.sol index cde5ee554f..e8ef5bbff2 100644 --- a/test/concrete/ob/OrderBookV6.entask.t.sol +++ b/test/concrete/ob/RaindexV6.entask.t.sol @@ -2,12 +2,12 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalRealTest} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import {OrderConfigV4, EvaluableV4, TaskV2, SignedContextV1} from "rain.raindex.interface/interface/IRaindexV6.sol"; -contract OrderBookV6EnactTest is OrderBookV6ExternalRealTest { +contract RaindexV6EnactTest is RaindexV6ExternalRealTest { function checkReentrancyRW() internal view { - (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iOrderbook)); + (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iRaindex)); // reads/writes for reentrancy guard. // ReentrancyGuard.REENTRANCY_GUARD_STORAGE bytes32 reentrancyGuardStorage = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00; @@ -30,7 +30,7 @@ contract OrderBookV6EnactTest is OrderBookV6ExternalRealTest { TaskV2(EvaluableV4(iInterpreter, iStore, iParserV2.parse2(evalStrings[i])), new SignedContextV1[](0)); } vm.record(); - iOrderbook.entask2(actions); + iRaindex.entask2(actions); checkReentrancyRW(); (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iStore)); assert(reads.length == expectedReads); @@ -39,26 +39,26 @@ contract OrderBookV6EnactTest is OrderBookV6ExternalRealTest { } /// forge-config: default.fuzz.runs = 100 - function testOrderBookEvalEmptyNoop(address alice) external { + function testRaindexEvalEmptyNoop(address alice) external { checkEntask(alice, new bytes[](0), 0, 0); } /// forge-config: default.fuzz.runs = 100 - function testOrderBookEvalOneStateless(address alice) external { + function testRaindexEvalOneStateless(address alice) external { bytes[] memory evals = new bytes[](1); evals[0] = bytes("_:1;"); checkEntask(alice, evals, 0, 0); } /// forge-config: default.fuzz.runs = 100 - function testOrderBookEvalOneReadState(address alice) external { + function testRaindexEvalOneReadState(address alice) external { bytes[] memory evals = new bytes[](1); evals[0] = bytes("_:get(0);"); checkEntask(alice, evals, 2, 1); } /// forge-config: default.fuzz.runs = 100 - function testOrderBookEvalWriteStateSingle(address alice) external { + function testRaindexEvalWriteStateSingle(address alice) external { bytes[] memory evals0 = new bytes[](1); evals0[0] = bytes(":set(1 2);"); checkEntask(alice, evals0, 1, 1); @@ -69,7 +69,7 @@ contract OrderBookV6EnactTest is OrderBookV6ExternalRealTest { } /// forge-config: default.fuzz.runs = 100 - function testOrderBookEvalWriteStateSequential() external { + function testRaindexEvalWriteStateSequential() external { bytes[] memory evals0 = new bytes[](4); evals0[0] = bytes(":set(1 2);"); evals0[1] = bytes(":ensure(equal-to(get(1) 2) \"0th set not equal\");"); @@ -86,7 +86,7 @@ contract OrderBookV6EnactTest is OrderBookV6ExternalRealTest { } /// forge-config: default.fuzz.runs = 100 - function testOrderBookEvalWriteStateDifferentOwnersNamespaced(address alice, address bob) external { + function testRaindexEvalWriteStateDifferentOwnersNamespaced(address alice, address bob) external { vm.assume(alice != bob); bytes[] memory evals0 = new bytes[](4); evals0[0] = bytes(":set(1 2);"); diff --git a/test/concrete/ob/OrderBookV6.quote.sameToken.t.sol b/test/concrete/ob/RaindexV6.quote.sameToken.t.sol similarity index 76% rename from test/concrete/ob/OrderBookV6.quote.sameToken.t.sol rename to test/concrete/ob/RaindexV6.quote.sameToken.t.sol index 058d08181b..ad8fc45aa1 100644 --- a/test/concrete/ob/OrderBookV6.quote.sameToken.t.sol +++ b/test/concrete/ob/RaindexV6.quote.sameToken.t.sol @@ -2,13 +2,13 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalRealTest} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import {QuoteV2, OrderConfigV4, TaskV2} from "rain.raindex.interface/interface/IRaindexV6.sol"; -import {TokenSelfTrade} from "../../../src/concrete/ob/OrderBookV6.sol"; +import {TokenSelfTrade} from "../../../src/concrete/ob/RaindexV6.sol"; import {Float} from "rain.math.float/lib/LibDecimalFloat.sol"; -/// @title OrderBookV6QuoteSameTokenTest -contract OrderBookV6QuoteSameTokenTest is OrderBookV6ExternalRealTest { +/// @title RaindexV6QuoteSameTokenTest +contract RaindexV6QuoteSameTokenTest is RaindexV6ExternalRealTest { /// Same token for input and output is error. /// forge-config: default.fuzz.runs = 10 function testQuoteSameToken(QuoteV2 memory quoteConfig) external { @@ -18,7 +18,7 @@ contract OrderBookV6QuoteSameTokenTest is OrderBookV6ExternalRealTest { quoteConfig.inputIOIndex = 0; quoteConfig.outputIOIndex = 0; vm.prank(quoteConfig.order.owner); - iOrderbook.addOrder4( + iRaindex.addOrder4( OrderConfigV4({ evaluable: quoteConfig.order.evaluable, validInputs: quoteConfig.order.validInputs, @@ -30,7 +30,7 @@ contract OrderBookV6QuoteSameTokenTest is OrderBookV6ExternalRealTest { new TaskV2[](0) ); vm.expectRevert(abi.encodeWithSelector(TokenSelfTrade.selector)); - (bool success, Float maxOutput, Float ioRatio) = iOrderbook.quote2(quoteConfig); + (bool success, Float maxOutput, Float ioRatio) = iRaindex.quote2(quoteConfig); (success, maxOutput, ioRatio); } } diff --git a/test/concrete/ob/OrderBookV6.quote.t.sol b/test/concrete/ob/RaindexV6.quote.t.sol similarity index 94% rename from test/concrete/ob/OrderBookV6.quote.t.sol rename to test/concrete/ob/RaindexV6.quote.t.sol index 5d7e37f767..d7793fc54e 100644 --- a/test/concrete/ob/OrderBookV6.quote.t.sol +++ b/test/concrete/ob/RaindexV6.quote.t.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalRealTest, console2} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest, console2} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import { IRaindexV6, QuoteV2, @@ -15,14 +15,14 @@ import { import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {TokenSelfTrade} from "../../../src/concrete/ob/OrderBookV6.sol"; +import {TokenSelfTrade} from "../../../src/concrete/ob/RaindexV6.sol"; import {Float, LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol"; import {LibFormatDecimalFloat} from "rain.math.float/lib/format/LibFormatDecimalFloat.sol"; -/// @title OrderBookV6QuoteTest -contract OrderBookV6QuoteTest is OrderBookV6ExternalRealTest { +/// @title RaindexV6QuoteTest +contract RaindexV6QuoteTest is RaindexV6ExternalRealTest { using Strings for address; using Strings for uint256; @@ -31,7 +31,7 @@ contract OrderBookV6QuoteTest is OrderBookV6ExternalRealTest { /// Dead orders always eval to false. /// forge-config: default.fuzz.runs = 100 function testQuoteDeadOrder(QuoteV2 memory quoteConfig) external view { - (bool success, Float maxOutput, Float ioRatio) = iOrderbook.quote2(quoteConfig); + (bool success, Float maxOutput, Float ioRatio) = iRaindex.quote2(quoteConfig); assert(!success); assertTrue(maxOutput.isZero(), "max output"); assertTrue(ioRatio.isZero(), "io ratio"); @@ -86,11 +86,11 @@ contract OrderBookV6QuoteTest is OrderBookV6ExternalRealTest { } else { vm.mockCall( address(iToken0), - abi.encodeWithSelector(IERC20.transferFrom.selector, owner, address(iOrderbook), depositAmount18), + abi.encodeWithSelector(IERC20.transferFrom.selector, owner, address(iRaindex), depositAmount18), abi.encode(true) ); vm.prank(owner); - iOrderbook.deposit4( + iRaindex.deposit4( config.validOutputs[0].token, config.validOutputs[0].vaultId, depositAmount, new TaskV2[](0) ); } @@ -102,7 +102,7 @@ contract OrderBookV6QuoteTest is OrderBookV6ExternalRealTest { for (uint256 i = 0; i < rainlang.length; i++) { config.evaluable.bytecode = iParserV2.parse2(rainlang[i]); vm.prank(owner); - iOrderbook.addOrder4(config, new TaskV2[](0)); + iRaindex.addOrder4(config, new TaskV2[](0)); OrderV4 memory order = OrderV4({ owner: owner, @@ -114,7 +114,7 @@ contract OrderBookV6QuoteTest is OrderBookV6ExternalRealTest { QuoteV2 memory quoteConfig = QuoteV2({order: order, inputIOIndex: 0, outputIOIndex: 0, signedContext: new SignedContextV1[](0)}); - (bool success, Float maxOutput, Float ioRatio) = iOrderbook.quote2(quoteConfig); + (bool success, Float maxOutput, Float ioRatio) = iRaindex.quote2(quoteConfig); assert(success); assertTrue(maxOutput.eq(expectedMaxOutput[i]), "max output"); @@ -178,7 +178,7 @@ contract OrderBookV6QuoteTest is OrderBookV6ExternalRealTest { bytes[] memory rainlang = new bytes[](10); // quote msg.sender rainlang[0] = "_ _:1 context<0 0>();:;"; - // orderbook + // raindex rainlang[1] = "_ _:1 context<0 1>();:;"; // // We can't easily check order hash with this setup // rainlang[2] = "_ _:1 context<1 0>();:;"; @@ -252,7 +252,7 @@ contract OrderBookV6QuoteTest is OrderBookV6ExternalRealTest { Float[] memory expectedIoRatio = new Float[](10); expectedIoRatio[0] = Float.wrap(bytes32(uint256(uint160(address(this))))); - expectedIoRatio[1] = Float.wrap(bytes32(uint256(uint160(address(iOrderbook))))); + expectedIoRatio[1] = Float.wrap(bytes32(uint256(uint160(address(iRaindex))))); expectedIoRatio[2] = Float.wrap(bytes32(uint256(uint160(owner)))); expectedIoRatio[3] = Float.wrap(bytes32(uint256(uint160(address(this))))); expectedIoRatio[4] = Float.wrap(bytes32(uint256(uint160(address(iToken1))))); diff --git a/test/concrete/ob/OrderBookV6.removeOrder.entask.t.sol b/test/concrete/ob/RaindexV6.removeOrder.entask.t.sol similarity index 92% rename from test/concrete/ob/OrderBookV6.removeOrder.entask.t.sol rename to test/concrete/ob/RaindexV6.removeOrder.entask.t.sol index 2cbbe74255..48840b31a5 100644 --- a/test/concrete/ob/OrderBookV6.removeOrder.entask.t.sol +++ b/test/concrete/ob/RaindexV6.removeOrder.entask.t.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalRealTest} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import { OrderConfigV4, EvaluableV4, @@ -15,13 +15,13 @@ import {LibOrder} from "../../../src/lib/LibOrder.sol"; import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol"; -contract OrderBookV6RemoveOrderEnactTest is OrderBookV6ExternalRealTest { +contract RaindexV6RemoveOrderEnactTest is RaindexV6ExternalRealTest { using LibOrder for OrderV4; using Strings for address; using Strings for uint256; function checkReentrancyRW(uint256 expectedReads, uint256 expectedWrites) internal view { - (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iOrderbook)); + (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iRaindex)); // 3 reads for reentrancy guard. // 1 reads for remove order. assert(reads.length == expectedReads); @@ -55,11 +55,11 @@ contract OrderBookV6RemoveOrderEnactTest is OrderBookV6ExternalRealTest { // Hacky way to give a unique nonce to each order passed in. config.nonce = keccak256(abi.encode(evalStrings)); if (addOrder) { - iOrderbook.addOrder4(config, new TaskV2[](0)); + iRaindex.addOrder4(config, new TaskV2[](0)); } OrderV4 memory order = OrderV4(owner, config.evaluable, config.validInputs, config.validOutputs, config.nonce); vm.record(); - bool stateChanged = iOrderbook.removeOrder3(order, actions); + bool stateChanged = iRaindex.removeOrder3(order, actions); assertEq(stateChanged, addOrder); checkReentrancyRW(addOrder ? 5 : 4, addOrder ? 3 : 2); (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iStore)); @@ -157,12 +157,12 @@ contract OrderBookV6RemoveOrderEnactTest is OrderBookV6ExternalRealTest { bytes[] memory evals0 = new bytes[](1); evals0[0] = bytes(":;"); TaskV2[] memory actions = evalsToActions(evals0); - bool stateChanged = iOrderbook.addOrder4(config, actions); + bool stateChanged = iRaindex.addOrder4(config, actions); assert(stateChanged); OrderV4 memory order = OrderV4(alice, config.evaluable, config.validInputs, config.validOutputs, config.nonce); - assert(iOrderbook.orderExists(order.hash())); + assert(iRaindex.orderExists(order.hash())); bytes[] memory evals1 = new bytes[](1); evals1[0] = bytes(":ensure(0 \"always revert\");"); @@ -170,11 +170,11 @@ contract OrderBookV6RemoveOrderEnactTest is OrderBookV6ExternalRealTest { TaskV2[] memory actions1 = evalsToActions(evals1); vm.expectRevert("always revert"); - bool stateChanged2 = iOrderbook.removeOrder3(order, actions1); + bool stateChanged2 = iRaindex.removeOrder3(order, actions1); assert(!stateChanged2); - assert(iOrderbook.orderExists(order.hash())); + assert(iRaindex.orderExists(order.hash())); } /// forge-config: default.fuzz.runs = 100 @@ -191,7 +191,7 @@ contract OrderBookV6RemoveOrderEnactTest is OrderBookV6ExternalRealTest { bytes[] memory evals = new bytes[](3); evals[0] = bytes( string.concat( - usingWordsFrom, ":ensure(equal-to(orderbook() ", address(iOrderbook).toHexString(), ") \"orderbook\");" + usingWordsFrom, ":ensure(equal-to(raindex() ", address(iRaindex).toHexString(), ") \"raindex\");" ) ); evals[1] = bytes( diff --git a/test/concrete/ob/OrderBookV6.removeOrder.mock.t.sol b/test/concrete/ob/RaindexV6.removeOrder.mock.t.sol similarity index 88% rename from test/concrete/ob/OrderBookV6.removeOrder.mock.t.sol rename to test/concrete/ob/RaindexV6.removeOrder.mock.t.sol index 3af21eb0f2..18256a83d4 100644 --- a/test/concrete/ob/OrderBookV6.removeOrder.mock.t.sol +++ b/test/concrete/ob/RaindexV6.removeOrder.mock.t.sol @@ -2,14 +2,14 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalMockTest} from "test/util/abstract/OrderBookV6ExternalMockTest.sol"; +import {RaindexV6ExternalMockTest} from "test/util/abstract/RaindexV6ExternalMockTest.sol"; import {OrderConfigV4, OrderV4, EvaluableV4, TaskV2} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; -import {NotOrderOwner} from "../../../src/concrete/ob/OrderBookV6.sol"; +import {NotOrderOwner} from "../../../src/concrete/ob/RaindexV6.sol"; -/// @title OrderBookV6RemoveOrderMockTest -/// @notice A contract to test the OrderBook removeOrder function. -contract OrderBookV6RemoveOrderMockTest is OrderBookV6ExternalMockTest { +/// @title RaindexV6RemoveOrderMockTest +/// @notice A contract to test the Raindex removeOrder function. +contract RaindexV6RemoveOrderMockTest is RaindexV6ExternalMockTest { /// An order MUST ONLY be removable by its owner. /// forge-config: default.fuzz.runs = 100 function testRemoveOrderOnlyOwner(address alice, address bob, OrderConfigV4 memory config, bytes memory expression) @@ -23,7 +23,7 @@ contract OrderBookV6RemoveOrderMockTest is OrderBookV6ExternalMockTest { // It will revert even if the order has not been added yet. vm.expectRevert(abi.encodeWithSelector(NotOrderOwner.selector, alice)); vm.prank(bob); - iOrderbook.removeOrder3(expectedOrder, new TaskV2[](0)); + iRaindex.removeOrder3(expectedOrder, new TaskV2[](0)); // And will revert after the order is added. (OrderV4 memory order, bytes32 orderHash) = addOrderWithChecks(alice, config, expression); @@ -31,7 +31,7 @@ contract OrderBookV6RemoveOrderMockTest is OrderBookV6ExternalMockTest { vm.expectRevert(abi.encodeWithSelector(NotOrderOwner.selector, alice)); vm.prank(bob); - iOrderbook.removeOrder3(order, new TaskV2[](0)); + iRaindex.removeOrder3(order, new TaskV2[](0)); // Alice can remove the order. removeOrderWithChecks(alice, order); @@ -39,7 +39,7 @@ contract OrderBookV6RemoveOrderMockTest is OrderBookV6ExternalMockTest { // It will revert even after the order has been removed. vm.expectRevert(abi.encodeWithSelector(NotOrderOwner.selector, alice)); vm.prank(bob); - iOrderbook.removeOrder3(order, new TaskV2[](0)); + iRaindex.removeOrder3(order, new TaskV2[](0)); } /// The same order can be added and removed multiple times. @@ -68,13 +68,13 @@ contract OrderBookV6RemoveOrderMockTest is OrderBookV6ExternalMockTest { function testRemoveOrderDoesNotExist(address alice, OrderConfigV4 memory config, bytes memory) external { LibTestAddOrder.conformConfig(config, iInterpreter, iStore); (OrderV4 memory order, bytes32 orderHash) = LibTestAddOrder.expectedOrder(alice, config); - assertFalse(iOrderbook.orderExists(orderHash)); + assertFalse(iRaindex.orderExists(orderHash)); vm.record(); vm.recordLogs(); vm.prank(alice); - assertFalse(iOrderbook.removeOrder3(order, new TaskV2[](0))); + assertFalse(iRaindex.removeOrder3(order, new TaskV2[](0))); assertEq(vm.getRecordedLogs().length, 0); - (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iOrderbook)); + (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iRaindex)); // 3x for reentrancy guard, 1x for dead order check. assertEq(reads.length, 4); // 2x for reentrancy guard. @@ -126,11 +126,11 @@ contract OrderBookV6RemoveOrderMockTest is OrderBookV6ExternalMockTest { // Owners can't interfere with each other. vm.expectRevert(abi.encodeWithSelector(NotOrderOwner.selector, bob)); vm.prank(alice); - iOrderbook.removeOrder3(orderBob, new TaskV2[](0)); + iRaindex.removeOrder3(orderBob, new TaskV2[](0)); vm.expectRevert(abi.encodeWithSelector(NotOrderOwner.selector, alice)); vm.prank(bob); - iOrderbook.removeOrder3(orderAlice, new TaskV2[](0)); + iRaindex.removeOrder3(orderAlice, new TaskV2[](0)); removeOrderWithChecks(alice, orderAlice); removeOrderWithChecks(bob, orderBob); @@ -186,17 +186,17 @@ contract OrderBookV6RemoveOrderMockTest is OrderBookV6ExternalMockTest { // Owners can't interfere with each other. vm.expectRevert(abi.encodeWithSelector(NotOrderOwner.selector, bob)); vm.prank(alice); - iOrderbook.removeOrder3(orderBobOne, new TaskV2[](0)); + iRaindex.removeOrder3(orderBobOne, new TaskV2[](0)); vm.expectRevert(abi.encodeWithSelector(NotOrderOwner.selector, bob)); vm.prank(alice); - iOrderbook.removeOrder3(orderBobTwo, new TaskV2[](0)); + iRaindex.removeOrder3(orderBobTwo, new TaskV2[](0)); vm.expectRevert(abi.encodeWithSelector(NotOrderOwner.selector, alice)); vm.prank(bob); - iOrderbook.removeOrder3(orderAliceOne, new TaskV2[](0)); + iRaindex.removeOrder3(orderAliceOne, new TaskV2[](0)); vm.expectRevert(abi.encodeWithSelector(NotOrderOwner.selector, alice)); vm.prank(bob); - iOrderbook.removeOrder3(orderAliceTwo, new TaskV2[](0)); + iRaindex.removeOrder3(orderAliceTwo, new TaskV2[](0)); removeOrderWithChecks(alice, orderAliceOne); removeOrderWithChecks(bob, orderBobOne); diff --git a/test/concrete/ob/RaindexV6.removeOrder.owner.t.sol b/test/concrete/ob/RaindexV6.removeOrder.owner.t.sol new file mode 100644 index 0000000000..82ded43520 --- /dev/null +++ b/test/concrete/ob/RaindexV6.removeOrder.owner.t.sol @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity =0.8.25; + +import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; +import {OrderConfigV4, OrderV4, EvaluableV4, TaskV2} from "rain.raindex.interface/interface/IRaindexV6.sol"; +import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; +import {LibOrder} from "../../../src/lib/LibOrder.sol"; +import {NotOrderOwner} from "../../../src/concrete/ob/RaindexV6.sol"; + +contract RaindexV6RemoveOrderOwnerTest is RaindexV6ExternalRealTest { + using LibOrder for OrderV4; + + /// forge-config: default.fuzz.runs = 100 + function testRemoveOrderOwnerSameOrderNoop(address owner, OrderConfigV4 memory config) public { + LibTestAddOrder.conformConfig(config, iInterpreter, iStore); + + OrderV4 memory order = OrderV4(owner, config.evaluable, config.validInputs, config.validOutputs, config.nonce); + + vm.startPrank(owner); + + for (uint256 i = 0; i < 2; i++) { + bool stateChange = iRaindex.addOrder4(config, new TaskV2[](0)); + assert(stateChange); + assert(iRaindex.orderExists(order.hash())); + stateChange = iRaindex.addOrder4(config, new TaskV2[](0)); + assert(!stateChange); + assert(iRaindex.orderExists(order.hash())); + + stateChange = iRaindex.removeOrder3(order, new TaskV2[](0)); + assert(stateChange); + assert(!iRaindex.orderExists(order.hash())); + stateChange = iRaindex.removeOrder3(order, new TaskV2[](0)); + assert(!stateChange); + assert(!iRaindex.orderExists(order.hash())); + } + + vm.stopPrank(); + } + + /// forge-config: default.fuzz.runs = 100 + function testRemoveOrderOwnerDifferentOwnerStateChange(OrderConfigV4 memory config, address alice, address bob) + public + { + LibTestAddOrder.conformConfig(config, iInterpreter, iStore); + vm.assume(alice != bob); + + OrderV4 memory orderAlice = + OrderV4(alice, config.evaluable, config.validInputs, config.validOutputs, config.nonce); + OrderV4 memory orderBob = OrderV4(bob, config.evaluable, config.validInputs, config.validOutputs, config.nonce); + + { + vm.prank(alice); + bool stateChange = iRaindex.addOrder4(config, new TaskV2[](0)); + + assert(stateChange); + assert(iRaindex.orderExists(orderAlice.hash())); + assert(!iRaindex.orderExists(orderBob.hash())); + + vm.prank(bob); + stateChange = iRaindex.removeOrder3(orderBob, new TaskV2[](0)); + assert(!stateChange); + assert(iRaindex.orderExists(orderAlice.hash())); + assert(!iRaindex.orderExists(orderBob.hash())); + + vm.prank(alice); + stateChange = iRaindex.removeOrder3(orderAlice, new TaskV2[](0)); + assert(stateChange); + assert(!iRaindex.orderExists(orderAlice.hash())); + assert(!iRaindex.orderExists(orderBob.hash())); + } + + { + vm.prank(bob); + bool stateChange = iRaindex.addOrder4(config, new TaskV2[](0)); + assert(stateChange); + assert(iRaindex.orderExists(orderBob.hash())); + assert(!iRaindex.orderExists(orderAlice.hash())); + + vm.prank(alice); + stateChange = iRaindex.removeOrder3(orderAlice, new TaskV2[](0)); + assert(!stateChange); + assert(iRaindex.orderExists(orderBob.hash())); + assert(!iRaindex.orderExists(orderAlice.hash())); + + vm.prank(bob); + stateChange = iRaindex.removeOrder3(orderBob, new TaskV2[](0)); + assert(stateChange); + assert(!iRaindex.orderExists(orderBob.hash())); + assert(!iRaindex.orderExists(orderAlice.hash())); + } + + { + vm.prank(alice); + bool stateChange = iRaindex.addOrder4(config, new TaskV2[](0)); + assert(stateChange); + assert(iRaindex.orderExists(orderAlice.hash())); + assert(!iRaindex.orderExists(orderBob.hash())); + + vm.prank(bob); + stateChange = iRaindex.addOrder4(config, new TaskV2[](0)); + assert(stateChange); + assert(iRaindex.orderExists(orderBob.hash())); + assert(iRaindex.orderExists(orderAlice.hash())); + + vm.prank(alice); + stateChange = iRaindex.removeOrder3(orderAlice, new TaskV2[](0)); + assert(stateChange); + assert(!iRaindex.orderExists(orderAlice.hash())); + assert(iRaindex.orderExists(orderBob.hash())); + + vm.prank(bob); + stateChange = iRaindex.removeOrder3(orderBob, new TaskV2[](0)); + assert(stateChange); + assert(!iRaindex.orderExists(orderBob.hash())); + assert(!iRaindex.orderExists(orderAlice.hash())); + } + } + + /// forge-config: default.fuzz.runs = 100 + function testRemoveOrderWrongOwner(OrderConfigV4 memory config, address alice, address bob) public { + LibTestAddOrder.conformConfig(config, iInterpreter, iStore); + vm.assume(alice != bob); + + OrderV4 memory order = OrderV4(alice, config.evaluable, config.validInputs, config.validOutputs, config.nonce); + + vm.prank(alice); + bool stateChange = iRaindex.addOrder4(config, new TaskV2[](0)); + assert(stateChange); + assert(iRaindex.orderExists(order.hash())); + + vm.prank(bob); + vm.expectRevert(abi.encodeWithSelector(NotOrderOwner.selector, alice)); + stateChange = iRaindex.removeOrder3(order, new TaskV2[](0)); + assert(!stateChange); + assert(iRaindex.orderExists(order.hash())); + } +} diff --git a/test/concrete/ob/OrderBookV6.takeOrder.badStack.t.sol b/test/concrete/ob/RaindexV6.takeOrder.badStack.t.sol similarity index 85% rename from test/concrete/ob/OrderBookV6.takeOrder.badStack.t.sol rename to test/concrete/ob/RaindexV6.takeOrder.badStack.t.sol index d48a5ca0b8..6b6657e828 100644 --- a/test/concrete/ob/OrderBookV6.takeOrder.badStack.t.sol +++ b/test/concrete/ob/RaindexV6.takeOrder.badStack.t.sol @@ -2,13 +2,13 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalRealTest} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; import {LibTestTakeOrder} from "test/util/lib/LibTestTakeOrder.sol"; import {OrderConfigV4, OrderV4, TaskV2, TakeOrdersConfigV5} from "rain.raindex.interface/interface/IRaindexV6.sol"; -import {UnsupportedCalculateOutputs} from "../../../src/concrete/ob/OrderBookV6.sol"; +import {UnsupportedCalculateOutputs} from "../../../src/concrete/ob/RaindexV6.sol"; -contract OrderBookV6TakeOrderBadStackTest is OrderBookV6ExternalRealTest { +contract RaindexV6TakeOrderBadStackTest is RaindexV6ExternalRealTest { function checkBadStack( address alice, address bob, @@ -28,11 +28,11 @@ contract OrderBookV6TakeOrderBadStackTest is OrderBookV6ExternalRealTest { config.validOutputs[0].token = address(iToken1); vm.prank(alice); - iOrderbook.addOrder4(config, new TaskV2[](0)); + iRaindex.addOrder4(config, new TaskV2[](0)); vm.prank(bob); vm.expectRevert(abi.encodeWithSelector(UnsupportedCalculateOutputs.selector, badStackHeight)); - iOrderbook.takeOrders4(takeOrdersConfig); + iRaindex.takeOrders4(takeOrdersConfig); } /// forge-config: default.fuzz.runs = 100 diff --git a/test/concrete/ob/OrderBookV6.takeOrder.exceedsMaxRatio.t.sol b/test/concrete/ob/RaindexV6.takeOrder.exceedsMaxRatio.t.sol similarity index 86% rename from test/concrete/ob/OrderBookV6.takeOrder.exceedsMaxRatio.t.sol rename to test/concrete/ob/RaindexV6.takeOrder.exceedsMaxRatio.t.sol index 174575e600..2e3c6a9572 100644 --- a/test/concrete/ob/OrderBookV6.takeOrder.exceedsMaxRatio.t.sol +++ b/test/concrete/ob/RaindexV6.takeOrder.exceedsMaxRatio.t.sol @@ -3,7 +3,7 @@ pragma solidity =0.8.25; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import {OrderBookV6ExternalRealTest} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import {LibTestTakeOrder} from "test/util/lib/LibTestTakeOrder.sol"; import {OrderV4, TakeOrdersConfigV5, TaskV2, IRaindexV6} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {Float, LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; @@ -11,7 +11,7 @@ import {LibOrder} from "../../../src/lib/LibOrder.sol"; /// When an order's IORatio exceeds the taker's maximumIORatio, the order /// is skipped and OrderExceedsMaxRatio is emitted. -contract OrderBookV6TakeOrderExceedsMaxRatioTest is OrderBookV6ExternalRealTest { +contract RaindexV6TakeOrderExceedsMaxRatioTest is RaindexV6ExternalRealTest { using LibDecimalFloat for Float; function testTakeOrderExceedsMaxRatio() external { @@ -21,11 +21,11 @@ contract OrderBookV6TakeOrderExceedsMaxRatioTest is OrderBookV6ExternalRealTest // Deposit so the order can fill. vm.mockCall( address(iToken1), - abi.encodeWithSelector(IERC20.transferFrom.selector, alice, address(iOrderbook)), + abi.encodeWithSelector(IERC20.transferFrom.selector, alice, address(iRaindex)), abi.encode(true) ); vm.prank(alice); - iOrderbook.deposit4( + iRaindex.deposit4( address(iToken1), bytes32(uint256(0x01)), LibDecimalFloat.packLossless(10, 0), new TaskV2[](0) ); @@ -47,7 +47,7 @@ contract OrderBookV6TakeOrderExceedsMaxRatioTest is OrderBookV6ExternalRealTest vm.prank(bob); vm.expectEmit(true, true, true, true); emit IRaindexV6.OrderExceedsMaxRatio(bob, alice, LibOrder.hash(order)); - (Float totalTakerInput, Float totalTakerOutput) = iOrderbook.takeOrders4(takeConfig); + (Float totalTakerInput, Float totalTakerOutput) = iRaindex.takeOrders4(takeConfig); assertTrue(totalTakerInput.isZero(), "totalTakerInput must be zero"); assertTrue(totalTakerOutput.isZero(), "totalTakerOutput must be zero"); diff --git a/test/concrete/ob/OrderBookV6.takeOrder.handleIO.revert.t.sol b/test/concrete/ob/RaindexV6.takeOrder.handleIO.revert.t.sol similarity index 93% rename from test/concrete/ob/OrderBookV6.takeOrder.handleIO.revert.t.sol rename to test/concrete/ob/RaindexV6.takeOrder.handleIO.revert.t.sol index c026ddd8e0..aef659267f 100644 --- a/test/concrete/ob/OrderBookV6.takeOrder.handleIO.revert.t.sol +++ b/test/concrete/ob/RaindexV6.takeOrder.handleIO.revert.t.sol @@ -3,7 +3,7 @@ pragma solidity =0.8.25; import {Vm} from "forge-std/Vm.sol"; -import {OrderBookV6ExternalRealTest, IERC20} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest, IERC20} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import { OrderV4, TakeOrderConfigV4, @@ -18,10 +18,10 @@ import {Float, LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {LibTestTakeOrder} from "test/util/lib/LibTestTakeOrder.sol"; -/// @title OrderBookV6TakeOrderHandleIORevertTest -/// @notice A test harness for testing the OrderBook takeOrder function will run +/// @title RaindexV6TakeOrderHandleIORevertTest +/// @notice A test harness for testing the Raindex takeOrder function will run /// handle IO and revert if it fails. -contract OrderBookV6TakeOrderHandleIORevertTest is OrderBookV6ExternalRealTest { +contract RaindexV6TakeOrderHandleIORevertTest is RaindexV6ExternalRealTest { using LibDecimalFloat for Float; function checkTakeOrderHandleIO(bytes[] memory configs, bytes memory err, Float maxInput) internal { @@ -50,12 +50,12 @@ contract OrderBookV6TakeOrderHandleIORevertTest is OrderBookV6ExternalRealTest { // Etch with invalid. vm.etch(outputToken, hex"fe"); vm.etch(inputToken, hex"fe"); - // Mock every call to output as a success, so the orderbook thinks it + // Mock every call to output as a success, so the raindex thinks it // is transferring tokens. vm.mockCall(outputToken, abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(uint8(18))); vm.mockCall( outputToken, - abi.encodeWithSelector(IERC20.transferFrom.selector, address(this), address(iOrderbook)), + abi.encodeWithSelector(IERC20.transferFrom.selector, address(this), address(iRaindex)), abi.encode(true) ); vm.mockCall(outputToken, abi.encodeWithSelector(IERC20.transfer.selector, address(this)), abi.encode(true)); @@ -64,11 +64,11 @@ contract OrderBookV6TakeOrderHandleIORevertTest is OrderBookV6ExternalRealTest { if (outputVaultId == bytes32(0)) { mockVault0Output(outputToken, address(this), uint256(int256(type(int224).max))); } else { - iOrderbook.deposit4( + iRaindex.deposit4( outputToken, vaultId, LibDecimalFloat.packLossless(type(int224).max, -18), new TaskV2[](0) ); assertTrue( - iOrderbook.vaultBalance2(address(this), outputToken, vaultId) + iRaindex.vaultBalance2(address(this), outputToken, vaultId) .eq(LibDecimalFloat.packLossless(type(int224).max, -18)) ); } @@ -84,7 +84,7 @@ contract OrderBookV6TakeOrderHandleIORevertTest is OrderBookV6ExternalRealTest { config = OrderConfigV4(evaluable, validInputs, validOutputs, bytes32(i), bytes32(0), ""); vm.recordLogs(); - iOrderbook.addOrder4(config, new TaskV2[](0)); + iRaindex.addOrder4(config, new TaskV2[](0)); Vm.Log[] memory entries = vm.getRecordedLogs(); assertEq(entries.length, 1); OrderV4 memory order = LibTestTakeOrder.extractOrderFromLogs(entries); @@ -97,7 +97,7 @@ contract OrderBookV6TakeOrderHandleIORevertTest is OrderBookV6ExternalRealTest { if (err.length > 0) { vm.expectRevert(err); } - (Float totalTakerInput, Float totalTakerOutput) = iOrderbook.takeOrders4(takeOrdersConfig); + (Float totalTakerInput, Float totalTakerOutput) = iRaindex.takeOrders4(takeOrdersConfig); // We don't really care about the outputs as the tests are basically just // trying to show that the IO handler is running or not running by simple // reverts. diff --git a/test/concrete/ob/OrderBookV6.takeOrder.maximumInput.t.sol b/test/concrete/ob/RaindexV6.takeOrder.maximumInput.t.sol similarity index 95% rename from test/concrete/ob/OrderBookV6.takeOrder.maximumInput.t.sol rename to test/concrete/ob/RaindexV6.takeOrder.maximumInput.t.sol index 95fb1615b4..62a3031de5 100644 --- a/test/concrete/ob/OrderBookV6.takeOrder.maximumInput.t.sol +++ b/test/concrete/ob/RaindexV6.takeOrder.maximumInput.t.sol @@ -3,7 +3,7 @@ pragma solidity =0.8.25; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import {OrderBookV6ExternalRealTest, Vm} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest, Vm} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import { OrderV4, TakeOrderConfigV4, @@ -20,7 +20,7 @@ import {LibTestTakeOrder} from "test/util/lib/LibTestTakeOrder.sol"; import {Float, LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibFormatDecimalFloat} from "rain.math.float/lib/format/LibFormatDecimalFloat.sol"; -contract OrderBookV6TakeOrderMaximumInputTest is OrderBookV6ExternalRealTest { +contract RaindexV6TakeOrderMaximumInputTest is RaindexV6ExternalRealTest { using LibDecimalFloat for Float; using LibFormatDecimalFloat for Float; @@ -44,7 +44,7 @@ contract OrderBookV6TakeOrderMaximumInputTest is OrderBookV6ExternalRealTest { data: "" }); vm.expectRevert(IRaindexV6.ZeroMaximumIO.selector); - (Float totalTakerInput, Float totalTakerOutput) = iOrderbook.takeOrders4(config); + (Float totalTakerInput, Float totalTakerOutput) = iRaindex.takeOrders4(config); (totalTakerInput, totalTakerOutput); } @@ -89,7 +89,7 @@ contract OrderBookV6TakeOrderMaximumInputTest is OrderBookV6ExternalRealTest { vm.prank(testOrders[i].owner); vm.recordLogs(); - iOrderbook.addOrder4(orderConfig, new TaskV2[](0)); + iRaindex.addOrder4(orderConfig, new TaskV2[](0)); Vm.Log[] memory entries = vm.getRecordedLogs(); assertEq(entries.length, 1); orders[i] = LibTestTakeOrder.extractOrderFromLogs(entries); @@ -113,26 +113,26 @@ contract OrderBookV6TakeOrderMaximumInputTest is OrderBookV6ExternalRealTest { vm.mockCall( address(iToken1), abi.encodeWithSelector( - IERC20.transferFrom.selector, testVaults[i].owner, address(iOrderbook), depositAmount18 + IERC20.transferFrom.selector, testVaults[i].owner, address(iRaindex), depositAmount18 ), abi.encode(true) ); vm.expectCall( address(iToken1), abi.encodeWithSelector( - IERC20.transferFrom.selector, testVaults[i].owner, address(iOrderbook), depositAmount18 + IERC20.transferFrom.selector, testVaults[i].owner, address(iRaindex), depositAmount18 ), 1 ); Float balanceBefore = - iOrderbook.vaultBalance2(testVaults[i].owner, testVaults[i].token, testVaults[i].vaultId); + iRaindex.vaultBalance2(testVaults[i].owner, testVaults[i].token, testVaults[i].vaultId); vm.prank(testVaults[i].owner); - iOrderbook.deposit4( + iRaindex.deposit4( testVaults[i].token, testVaults[i].vaultId, testVaults[i].deposit, new TaskV2[](0) ); Float balanceAfter = - iOrderbook.vaultBalance2(testVaults[i].owner, testVaults[i].token, testVaults[i].vaultId); + iRaindex.vaultBalance2(testVaults[i].owner, testVaults[i].token, testVaults[i].vaultId); Float expectedBalance = testVaults[i].deposit.add(balanceBefore); assertTrue(balanceAfter.eq(expectedBalance), "vaultBalance after"); @@ -167,18 +167,18 @@ contract OrderBookV6TakeOrderMaximumInputTest is OrderBookV6ExternalRealTest { ); vm.mockCall( address(iToken0), - abi.encodeWithSelector(IERC20.transferFrom.selector, bob, address(iOrderbook), expectedTakerOutput18), + abi.encodeWithSelector(IERC20.transferFrom.selector, bob, address(iRaindex), expectedTakerOutput18), abi.encode(true) ); vm.expectCall( address(iToken0), - abi.encodeWithSelector(IERC20.transferFrom.selector, bob, address(iOrderbook), expectedTakerOutput18), + abi.encodeWithSelector(IERC20.transferFrom.selector, bob, address(iRaindex), expectedTakerOutput18), expectedTakerOutput18 > 0 ? 1 : 0 ); } { vm.prank(bob); - (Float totalTakerInput, Float totalTakerOutput) = iOrderbook.takeOrders4(config); + (Float totalTakerInput, Float totalTakerOutput) = iRaindex.takeOrders4(config); assertTrue(totalTakerInput.eq(expectedTakerInput), "totalTakerInput"); assertTrue(totalTakerOutput.eq(expectedTakerOutput), "totalTakerOutput"); } @@ -186,7 +186,7 @@ contract OrderBookV6TakeOrderMaximumInputTest is OrderBookV6ExternalRealTest { for (uint256 i = 0; i < testVaults.length; i++) { if (testVaults[i].vaultId != bytes32(0)) { Float vaultBalance = - iOrderbook.vaultBalance2(testVaults[i].owner, testVaults[i].token, testVaults[i].vaultId); + iRaindex.vaultBalance2(testVaults[i].owner, testVaults[i].token, testVaults[i].vaultId); assertTrue(vaultBalance.eq(testVaults[i].expect), "vaultBalance"); } } diff --git a/test/concrete/ob/OrderBookV6.takeOrder.maximumOutput.t.sol b/test/concrete/ob/RaindexV6.takeOrder.maximumOutput.t.sol similarity index 97% rename from test/concrete/ob/OrderBookV6.takeOrder.maximumOutput.t.sol rename to test/concrete/ob/RaindexV6.takeOrder.maximumOutput.t.sol index 2a513c61b4..849679c663 100644 --- a/test/concrete/ob/OrderBookV6.takeOrder.maximumOutput.t.sol +++ b/test/concrete/ob/RaindexV6.takeOrder.maximumOutput.t.sol @@ -3,7 +3,7 @@ pragma solidity =0.8.25; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import {OrderBookV6ExternalRealTest, Vm} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest, Vm} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import { OrderV4, TakeOrderConfigV4, @@ -18,7 +18,7 @@ import { import {LibTestTakeOrder} from "test/util/lib/LibTestTakeOrder.sol"; import {LibDecimalFloat, Float} from "rain.math.float/lib/LibDecimalFloat.sol"; -contract OrderBookV6TakeOrderMaximumOutputTest is OrderBookV6ExternalRealTest { +contract RaindexV6TakeOrderMaximumOutputTest is RaindexV6ExternalRealTest { using LibDecimalFloat for Float; /// It should be possible to take an order with zero maximum output. @@ -40,7 +40,7 @@ contract OrderBookV6TakeOrderMaximumOutputTest is OrderBookV6ExternalRealTest { data: "" }); vm.expectRevert(IRaindexV6.ZeroMaximumIO.selector); - (Float totalTakerInput, Float totalTakerOutput) = iOrderbook.takeOrders4(config); + (Float totalTakerInput, Float totalTakerOutput) = iRaindex.takeOrders4(config); (totalTakerInput, totalTakerOutput); } @@ -93,7 +93,7 @@ contract OrderBookV6TakeOrderMaximumOutputTest is OrderBookV6ExternalRealTest { vm.prank(testOrders[i].owner); vm.recordLogs(); - iOrderbook.addOrder4(orderConfig, new TaskV2[](0)); + iRaindex.addOrder4(orderConfig, new TaskV2[](0)); Vm.Log[] memory logs = vm.getRecordedLogs(); assertEq(logs.length, 1); orders[i] = LibTestTakeOrder.extractOrderFromLogs(logs); @@ -118,26 +118,26 @@ contract OrderBookV6TakeOrderMaximumOutputTest is OrderBookV6ExternalRealTest { vm.mockCall( address(iToken1), abi.encodeWithSelector( - iToken1.transferFrom.selector, testVaults[i].owner, address(iOrderbook), depositAmount18 + iToken1.transferFrom.selector, testVaults[i].owner, address(iRaindex), depositAmount18 ), abi.encode(true) ); vm.expectCall( address(iToken1), abi.encodeWithSelector( - iToken1.transferFrom.selector, testVaults[i].owner, address(iOrderbook), depositAmount18 + iToken1.transferFrom.selector, testVaults[i].owner, address(iRaindex), depositAmount18 ), 1 ); Float balanceBefore = - iOrderbook.vaultBalance2(testVaults[i].owner, testVaults[i].token, testVaults[i].vaultId); + iRaindex.vaultBalance2(testVaults[i].owner, testVaults[i].token, testVaults[i].vaultId); vm.prank(testVaults[i].owner); - iOrderbook.deposit4( + iRaindex.deposit4( testVaults[i].token, testVaults[i].vaultId, testVaults[i].deposit, new TaskV2[](0) ); Float balanceAfter = - iOrderbook.vaultBalance2(testVaults[i].owner, testVaults[i].token, testVaults[i].vaultId); + iRaindex.vaultBalance2(testVaults[i].owner, testVaults[i].token, testVaults[i].vaultId); Float expectedBalance = testVaults[i].deposit.add(balanceBefore); assertTrue(balanceAfter.eq(expectedBalance), "deposit"); @@ -166,12 +166,12 @@ contract OrderBookV6TakeOrderMaximumOutputTest is OrderBookV6ExternalRealTest { // Mock and expect the token transfers. vm.mockCall( address(iToken0), - abi.encodeWithSelector(iToken0.transferFrom.selector, bob, address(iOrderbook), expectedTakerOutput18), + abi.encodeWithSelector(iToken0.transferFrom.selector, bob, address(iRaindex), expectedTakerOutput18), abi.encode(true) ); vm.expectCall( address(iToken0), - abi.encodeWithSelector(iToken0.transferFrom.selector, bob, address(iOrderbook), expectedTakerOutput18), + abi.encodeWithSelector(iToken0.transferFrom.selector, bob, address(iRaindex), expectedTakerOutput18), expectedTakerOutput18 > 0 ? 1 : 0 ); vm.mockCall( @@ -187,7 +187,7 @@ contract OrderBookV6TakeOrderMaximumOutputTest is OrderBookV6ExternalRealTest { } { vm.prank(bob); - (Float totalTakerInput, Float totalTakerOutput) = iOrderbook.takeOrders4(config); + (Float totalTakerInput, Float totalTakerOutput) = iRaindex.takeOrders4(config); assertTrue(totalTakerInput.eq(expectedTakerInput), "taker input"); assertTrue(totalTakerOutput.eq(expectedTakerOutput), "taker output"); @@ -200,7 +200,7 @@ contract OrderBookV6TakeOrderMaximumOutputTest is OrderBookV6ExternalRealTest { // assertions above. if (testVaults[i].vaultId != bytes32(0)) { Float finalBalance = - iOrderbook.vaultBalance2(testVaults[i].owner, testVaults[i].token, testVaults[i].vaultId); + iRaindex.vaultBalance2(testVaults[i].owner, testVaults[i].token, testVaults[i].vaultId); Float expectedFinalBalance = testVaults[i].expect; assertTrue(finalBalance.eq(expectedFinalBalance), "final balance"); } diff --git a/test/concrete/ob/OrderBookV6.takeOrder.minimumIO.t.sol b/test/concrete/ob/RaindexV6.takeOrder.minimumIO.t.sol similarity index 85% rename from test/concrete/ob/OrderBookV6.takeOrder.minimumIO.t.sol rename to test/concrete/ob/RaindexV6.takeOrder.minimumIO.t.sol index 83fb3be402..fc204da238 100644 --- a/test/concrete/ob/OrderBookV6.takeOrder.minimumIO.t.sol +++ b/test/concrete/ob/RaindexV6.takeOrder.minimumIO.t.sol @@ -3,15 +3,15 @@ pragma solidity =0.8.25; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import {OrderBookV6ExternalRealTest} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import {LibTestTakeOrder} from "test/util/lib/LibTestTakeOrder.sol"; import {OrderV4, TakeOrdersConfigV5, TaskV2} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {Float, LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; -import {MinimumIO} from "../../../src/concrete/ob/OrderBookV6.sol"; +import {MinimumIO} from "../../../src/concrete/ob/RaindexV6.sol"; /// When the total taker IO is less than the configured minimumIO, /// takeOrders4 must revert with MinimumIO(minimumIO, actualIO). -contract OrderBookV6TakeOrderMinimumIOTest is OrderBookV6ExternalRealTest { +contract RaindexV6TakeOrderMinimumIOTest is RaindexV6ExternalRealTest { function testTakeOrderMinimumIORevert() external { address alice = address(uint160(uint256(keccak256("alice.rain.test")))); address bob = address(uint160(uint256(keccak256("bob.rain.test")))); @@ -19,11 +19,11 @@ contract OrderBookV6TakeOrderMinimumIOTest is OrderBookV6ExternalRealTest { // Deposit 1 token into alice's output vault so the order can fill. vm.mockCall( address(iToken1), - abi.encodeWithSelector(IERC20.transferFrom.selector, alice, address(iOrderbook)), + abi.encodeWithSelector(IERC20.transferFrom.selector, alice, address(iRaindex)), abi.encode(true) ); vm.prank(alice); - iOrderbook.deposit4( + iRaindex.deposit4( address(iToken1), bytes32(uint256(0x01)), LibDecimalFloat.packLossless(1, 0), new TaskV2[](0) ); @@ -48,6 +48,6 @@ contract OrderBookV6TakeOrderMinimumIOTest is OrderBookV6ExternalRealTest { MinimumIO.selector, LibDecimalFloat.packLossless(1, 0), LibDecimalFloat.packLossless(1, -18) ) ); - iOrderbook.takeOrders4(takeConfig); + iRaindex.takeOrders4(takeConfig); } } diff --git a/test/concrete/ob/OrderBookV6.takeOrder.noop.t.sol b/test/concrete/ob/RaindexV6.takeOrder.noop.t.sol similarity index 91% rename from test/concrete/ob/OrderBookV6.takeOrder.noop.t.sol rename to test/concrete/ob/RaindexV6.takeOrder.noop.t.sol index c67137406c..2d3a375364 100644 --- a/test/concrete/ob/OrderBookV6.takeOrder.noop.t.sol +++ b/test/concrete/ob/RaindexV6.takeOrder.noop.t.sol @@ -6,7 +6,7 @@ import {Vm} from "forge-std/Test.sol"; import {LibOrder} from "../../../src/lib/LibOrder.sol"; import {LibTestTakeOrder} from "test/util/lib/LibTestTakeOrder.sol"; -import {OrderBookV6ExternalRealTest} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import { OrderV4, TakeOrdersConfigV5, @@ -16,10 +16,10 @@ import { import {Float, LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -/// @title OrderBookV6TakeOrderNoopTest -/// @notice A test harness for testing the OrderBook takeOrder function. Focuses +/// @title RaindexV6TakeOrderNoopTest +/// @notice A test harness for testing the Raindex takeOrder function. Focuses /// on the no-op case. -contract OrderBookV6TakeOrderNoopTest is OrderBookV6ExternalRealTest { +contract RaindexV6TakeOrderNoopTest is RaindexV6ExternalRealTest { using LibOrder for OrderV4; using LibDecimalFloat for Float; @@ -28,7 +28,7 @@ contract OrderBookV6TakeOrderNoopTest is OrderBookV6ExternalRealTest { function testTakeOrderNoopZeroOrders() external { TakeOrdersConfigV5 memory config = LibTestTakeOrder.defaultTakeConfig(new TakeOrderConfigV4[](0)); vm.expectRevert(NoOrders.selector); - (Float totalTakerInput, Float totalTakerOutput) = iOrderbook.takeOrders4(config); + (Float totalTakerInput, Float totalTakerOutput) = iRaindex.takeOrders4(config); (totalTakerInput, totalTakerOutput); } @@ -60,10 +60,10 @@ contract OrderBookV6TakeOrderNoopTest is OrderBookV6ExternalRealTest { TakeOrderConfigV4[] memory orders = new TakeOrderConfigV4[](1); orders[0] = orderConfig; TakeOrdersConfigV5 memory config = LibTestTakeOrder.defaultTakeConfig(orders); - vm.expectEmit(address(iOrderbook)); + vm.expectEmit(address(iRaindex)); emit OrderNotFound(address(this), order.owner, order.hash()); vm.recordLogs(); - (Float totalTakerInput, Float totalTakerOutput) = iOrderbook.takeOrders4(config); + (Float totalTakerInput, Float totalTakerOutput) = iRaindex.takeOrders4(config); assertTrue(totalTakerInput.isZero()); assertTrue(totalTakerOutput.isZero()); Vm.Log[] memory logs = vm.getRecordedLogs(); @@ -126,7 +126,7 @@ contract OrderBookV6TakeOrderNoopTest is OrderBookV6ExternalRealTest { vm.recordLogs(); { - (Float totalTakerInput, Float totalTakerOutput) = iOrderbook.takeOrders4(config); + (Float totalTakerInput, Float totalTakerOutput) = iRaindex.takeOrders4(config); assertTrue(totalTakerInput.isZero()); assertTrue(totalTakerOutput.isZero()); } diff --git a/test/concrete/ob/OrderBookV6.takeOrder.precision.t.sol b/test/concrete/ob/RaindexV6.takeOrder.precision.t.sol similarity index 91% rename from test/concrete/ob/OrderBookV6.takeOrder.precision.t.sol rename to test/concrete/ob/RaindexV6.takeOrder.precision.t.sol index ce901ef6d1..a615f90147 100644 --- a/test/concrete/ob/OrderBookV6.takeOrder.precision.t.sol +++ b/test/concrete/ob/RaindexV6.takeOrder.precision.t.sol @@ -3,7 +3,7 @@ pragma solidity =0.8.25; import {Vm} from "forge-std/Test.sol"; -import {OrderBookV6ExternalRealTest, IERC20} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest, IERC20} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import { OrderV4, TakeOrdersConfigV5, @@ -17,9 +17,9 @@ import {Float, LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {LibTestTakeOrder} from "test/util/lib/LibTestTakeOrder.sol"; -/// @title OrderBookV6TakeOrderPrecisionTest -/// @notice A test harness for testing the OrderBook takeOrder function. -contract OrderBookV6TakeOrderPrecisionTest is OrderBookV6ExternalRealTest { +/// @title RaindexV6TakeOrderPrecisionTest +/// @notice A test harness for testing the Raindex takeOrder function. +contract RaindexV6TakeOrderPrecisionTest is RaindexV6ExternalRealTest { using LibDecimalFloat for Float; function checkPrecision( @@ -75,7 +75,7 @@ contract OrderBookV6TakeOrderPrecisionTest is OrderBookV6ExternalRealTest { vm.mockCall( outputToken, abi.encodeWithSelector( - IERC20.transferFrom.selector, address(this), address(iOrderbook), absoluteDepositAmount + IERC20.transferFrom.selector, address(this), address(iRaindex), absoluteDepositAmount ), abi.encode(true) ); @@ -102,7 +102,7 @@ contract OrderBookV6TakeOrderPrecisionTest is OrderBookV6ExternalRealTest { vm.mockCall( inputToken, abi.encodeWithSelector( - IERC20.transferFrom.selector, address(this), address(iOrderbook), absoluteTakerOutputAmount + IERC20.transferFrom.selector, address(this), address(iRaindex), absoluteTakerOutputAmount ), abi.encode(true) ); @@ -126,28 +126,28 @@ contract OrderBookV6TakeOrderPrecisionTest is OrderBookV6ExternalRealTest { { if (outputVaultId != bytes32(0) && expectedTakerTotalInput.gt(LibDecimalFloat.packLossless(0, 0))) { - iOrderbook.deposit4(outputToken, outputVaultId, expectedTakerTotalInput, new TaskV2[](0)); + iRaindex.deposit4(outputToken, outputVaultId, expectedTakerTotalInput, new TaskV2[](0)); } if (outputVaultId != bytes32(0)) { assertTrue( - iOrderbook.vaultBalance2(address(this), outputToken, outputVaultId).eq(expectedTakerTotalInput) + iRaindex.vaultBalance2(address(this), outputToken, outputVaultId).eq(expectedTakerTotalInput) ); } vm.recordLogs(); - iOrderbook.addOrder4(config, new TaskV2[](0)); + iRaindex.addOrder4(config, new TaskV2[](0)); Vm.Log[] memory entries = vm.getRecordedLogs(); assertEq(entries.length, 1); OrderV4 memory order = LibTestTakeOrder.extractOrderFromLogs(entries); TakeOrdersConfigV5 memory takeOrdersConfig = LibTestTakeOrder.defaultTakeConfig(LibTestTakeOrder.wrapSingle(order)); - (Float totalTakerInput, Float totalTakerOutput) = iOrderbook.takeOrders4(takeOrdersConfig); + (Float totalTakerInput, Float totalTakerOutput) = iRaindex.takeOrders4(takeOrdersConfig); assertTrue(totalTakerInput.eq(expectedTakerTotalInput), "input"); assertTrue(totalTakerOutput.eq(expectedTakerTotalOutput), "output"); } if (outputVaultId != bytes32(0)) { - assertTrue(iOrderbook.vaultBalance2(address(this), outputToken, outputVaultId).isZero(), "vault balance"); + assertTrue(iRaindex.vaultBalance2(address(this), outputToken, outputVaultId).isZero(), "vault balance"); } } diff --git a/test/concrete/ob/OrderBookV6.takeOrder.sameToken.t.sol b/test/concrete/ob/RaindexV6.takeOrder.sameToken.t.sol similarity index 82% rename from test/concrete/ob/OrderBookV6.takeOrder.sameToken.t.sol rename to test/concrete/ob/RaindexV6.takeOrder.sameToken.t.sol index 43d28d9b4f..ced38fce53 100644 --- a/test/concrete/ob/OrderBookV6.takeOrder.sameToken.t.sol +++ b/test/concrete/ob/RaindexV6.takeOrder.sameToken.t.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalRealTest} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import { OrderConfigV4, OrderV4, @@ -12,10 +12,10 @@ import { TakeOrdersConfigV5 } from "rain.raindex.interface/interface/IRaindexV6.sol"; import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; -import {TokenSelfTrade} from "../../../src/concrete/ob/OrderBookV6.sol"; +import {TokenSelfTrade} from "../../../src/concrete/ob/RaindexV6.sol"; import {Float, LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; -contract OrderBookV6TakeOrderSameTokenTest is OrderBookV6ExternalRealTest { +contract RaindexV6TakeOrderSameTokenTest is RaindexV6ExternalRealTest { /// forge-config: default.fuzz.runs = 10 function testTakeOrderSameToken(address alice, OrderConfigV4 memory configAlice) external { LibTestAddOrder.conformConfig(configAlice, iInterpreter, iStore); @@ -26,7 +26,7 @@ contract OrderBookV6TakeOrderSameTokenTest is OrderBookV6ExternalRealTest { OrderV4(alice, configAlice.evaluable, configAlice.validInputs, configAlice.validOutputs, configAlice.nonce); vm.prank(alice); - iOrderbook.addOrder4(configAlice, new TaskV2[](0)); + iRaindex.addOrder4(configAlice, new TaskV2[](0)); TakeOrderConfigV4[] memory takeOrders = new TakeOrderConfigV4[](1); takeOrders[0] = TakeOrderConfigV4({ @@ -43,6 +43,6 @@ contract OrderBookV6TakeOrderSameTokenTest is OrderBookV6ExternalRealTest { }); vm.expectRevert(abi.encodeWithSelector(TokenSelfTrade.selector)); - iOrderbook.takeOrders4(takeOrdersConfig); + iRaindex.takeOrders4(takeOrdersConfig); } } diff --git a/test/concrete/ob/OrderBookV6.takeOrder.tokenMismatch.t.sol b/test/concrete/ob/RaindexV6.takeOrder.tokenMismatch.t.sol similarity index 90% rename from test/concrete/ob/OrderBookV6.takeOrder.tokenMismatch.t.sol rename to test/concrete/ob/RaindexV6.takeOrder.tokenMismatch.t.sol index 4d90ca2cfa..2c533c86b2 100644 --- a/test/concrete/ob/OrderBookV6.takeOrder.tokenMismatch.t.sol +++ b/test/concrete/ob/RaindexV6.takeOrder.tokenMismatch.t.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalRealTest} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import { OrderV4, IOV2, @@ -11,13 +11,13 @@ import { EvaluableV4, SignedContextV1 } from "rain.raindex.interface/interface/IRaindexV6.sol"; -import {TokenMismatch} from "../../../src/concrete/ob/OrderBookV6.sol"; +import {TokenMismatch} from "../../../src/concrete/ob/RaindexV6.sol"; import {Float, LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; -/// @title OrderBookV6TakeOrderTokenMismatchTest -/// @notice A test harness for testing the OrderBookV6 takeOrder function. +/// @title RaindexV6TakeOrderTokenMismatchTest +/// @notice A test harness for testing the RaindexV6 takeOrder function. /// Focuses on the token mismatch case. -contract OrderBookV6TakeOrderTokenMismatchTest is OrderBookV6ExternalRealTest { +contract RaindexV6TakeOrderTokenMismatchTest is RaindexV6ExternalRealTest { /// It is only possible to get a token mismatch when there are at least two /// orders. This is because `takeOrders` is interactive so we assume that /// the caller's desired input and output tokens match the first order they @@ -64,7 +64,7 @@ contract OrderBookV6TakeOrderTokenMismatchTest is OrderBookV6ExternalRealTest { data: "" }); vm.expectRevert(abi.encodeWithSelector(TokenMismatch.selector)); - (Float totalTakerInput, Float totalTakerOutput) = iOrderbook.takeOrders4(config); + (Float totalTakerInput, Float totalTakerOutput) = iRaindex.takeOrders4(config); (totalTakerInput, totalTakerOutput); } @@ -110,7 +110,7 @@ contract OrderBookV6TakeOrderTokenMismatchTest is OrderBookV6ExternalRealTest { data: "" }); vm.expectRevert(abi.encodeWithSelector(TokenMismatch.selector)); - (Float totalTakerInput, Float totalTakerOutput) = iOrderbook.takeOrders4(config); + (Float totalTakerInput, Float totalTakerOutput) = iRaindex.takeOrders4(config); (totalTakerInput, totalTakerOutput); } } diff --git a/test/concrete/ob/OrderBookV6.vaultBalance.t.sol b/test/concrete/ob/RaindexV6.vaultBalance.t.sol similarity index 69% rename from test/concrete/ob/OrderBookV6.vaultBalance.t.sol rename to test/concrete/ob/RaindexV6.vaultBalance.t.sol index 0f1f8496db..fed27c63c1 100644 --- a/test/concrete/ob/OrderBookV6.vaultBalance.t.sol +++ b/test/concrete/ob/RaindexV6.vaultBalance.t.sol @@ -2,18 +2,18 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalMockTest} from "test/util/abstract/OrderBookV6ExternalMockTest.sol"; +import {RaindexV6ExternalMockTest} from "test/util/abstract/RaindexV6ExternalMockTest.sol"; import {LibDecimalFloat, Float} from "rain.math.float/lib/LibDecimalFloat.sol"; import {IRaindexV6} from "rain.raindex.interface/interface/IRaindexV6.sol"; -/// @title OrderBookV6VaultBalanceTest +/// @title RaindexV6VaultBalanceTest /// Tests the basic functionality of reading from the vault balance. -contract OrderBookV6VaultBalanceTest is OrderBookV6ExternalMockTest { +contract RaindexV6VaultBalanceTest is RaindexV6ExternalMockTest { using LibDecimalFloat for Float; /// Test that reading the vault balance without deposits is always zero. function testVaultBalanceNoDeposits(address owner, address token, bytes32 vaultId) external view { vm.assume(vaultId != bytes32(0)); - assertTrue(iOrderbook.vaultBalance2(owner, token, vaultId).isZero()); + assertTrue(iRaindex.vaultBalance2(owner, token, vaultId).isZero()); } } diff --git a/test/concrete/ob/OrderBookV6.withdraw.entask.t.sol b/test/concrete/ob/RaindexV6.withdraw.entask.t.sol similarity index 91% rename from test/concrete/ob/OrderBookV6.withdraw.entask.t.sol rename to test/concrete/ob/RaindexV6.withdraw.entask.t.sol index ac2f1ebd8e..e9ca0c4499 100644 --- a/test/concrete/ob/OrderBookV6.withdraw.entask.t.sol +++ b/test/concrete/ob/RaindexV6.withdraw.entask.t.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ExternalRealTest} from "test/util/abstract/OrderBookV6ExternalRealTest.sol"; +import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import {OrderConfigV4, EvaluableV4, TaskV2, SignedContextV1} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; @@ -14,14 +14,14 @@ import {ReentrancyGuard} from "openzeppelin-contracts/contracts/utils/Reentrancy import {console2} from "forge-std/Test.sol"; -contract OrderBookV6WithdrawEvalTest is OrderBookV6ExternalRealTest { +contract RaindexV6WithdrawEvalTest is RaindexV6ExternalRealTest { using Strings for address; using Strings for uint256; using LibDecimalFloat for Float; using LibFormatDecimalFloat for Float; function checkReentrancyRW(uint256 expectedReads, uint256 expectedWrites) internal view { - (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iOrderbook)); + (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iRaindex)); // 3 reads for reentrancy guard. // 2 reads for deposit. assertEq(reads.length, expectedReads, "reads length"); @@ -68,7 +68,7 @@ contract OrderBookV6WithdrawEvalTest is OrderBookV6ExternalRealTest { vm.mockCall( address(iToken0), abi.encodeWithSelector( - IERC20.transferFrom.selector, owner, address(iOrderbook), depositAmountAbsolute + IERC20.transferFrom.selector, owner, address(iRaindex), depositAmountAbsolute ), abi.encode(true) ); @@ -76,7 +76,7 @@ contract OrderBookV6WithdrawEvalTest is OrderBookV6ExternalRealTest { vm.startPrank(owner); if (depositAmountAbsolute > 0) { - iOrderbook.deposit4(address(iToken0), vaultId, depositAmount, new TaskV2[](0)); + iRaindex.deposit4(address(iToken0), vaultId, depositAmount, new TaskV2[](0)); } } @@ -110,7 +110,7 @@ contract OrderBookV6WithdrawEvalTest is OrderBookV6ExternalRealTest { withdrawAmount18 ); } - iOrderbook.withdraw4(address(iToken0), vaultId, targetAmount, actions); + iRaindex.withdraw4(address(iToken0), vaultId, targetAmount, actions); if (err.length == 0) { checkReentrancyRW(6, 3); (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iStore)); @@ -122,7 +122,7 @@ contract OrderBookV6WithdrawEvalTest is OrderBookV6ExternalRealTest { } /// forge-config: default.fuzz.runs = 100 - function testOrderBookWithdrawEvalEmptyNoop( + function testRaindexWithdrawEvalEmptyNoop( address alice, bytes32 vaultId, uint256 depositAmount18, @@ -137,7 +137,7 @@ contract OrderBookV6WithdrawEvalTest is OrderBookV6ExternalRealTest { } /// forge-config: default.fuzz.runs = 100 - function testOrderBookWithdrawEvalOneStateless( + function testRaindexWithdrawEvalOneStateless( address alice, bytes32 vaultId, uint256 depositAmount18, @@ -156,7 +156,7 @@ contract OrderBookV6WithdrawEvalTest is OrderBookV6ExternalRealTest { } /// forge-config: default.fuzz.runs = 100 - function testOrderBookWithdrawEvalOneReadState( + function testRaindexWithdrawEvalOneReadState( address alice, bytes32 vaultId, uint256 depositAmount18, @@ -176,7 +176,7 @@ contract OrderBookV6WithdrawEvalTest is OrderBookV6ExternalRealTest { } /// forge-config: default.fuzz.runs = 100 - function testOrderBookWithdrawEvalWriteStateSingle( + function testRaindexWithdrawEvalWriteStateSingle( address alice, bytes32 vaultId, uint256 depositAmount18, @@ -201,7 +201,7 @@ contract OrderBookV6WithdrawEvalTest is OrderBookV6ExternalRealTest { } /// forge-config: default.fuzz.runs = 100 - function testOrderBookWithdrawEvalWriteStateSequential( + function testRaindexWithdrawEvalWriteStateSequential( address alice, bytes32 vaultId, uint256 depositAmount18, @@ -234,7 +234,7 @@ contract OrderBookV6WithdrawEvalTest is OrderBookV6ExternalRealTest { } /// forge-config: default.fuzz.runs = 100 - function testOrderBookWithdrawEvalWriteStateDifferentOwnersNamespaced( + function testRaindexWithdrawEvalWriteStateDifferentOwnersNamespaced( address alice, address bob, bytes32 vaultId, @@ -282,7 +282,7 @@ contract OrderBookV6WithdrawEvalTest is OrderBookV6ExternalRealTest { /// Evals DO run if withdrawal amount ends up as 0. /// No withdraw => eval. /// forge-config: default.fuzz.runs = 100 - function testOrderBookWithdrawalEvalZeroAmountEvalNoop(address alice, bytes32 vaultId, uint256 withdrawAmount18) + function testRaindexWithdrawalEvalZeroAmountEvalNoop(address alice, bytes32 vaultId, uint256 withdrawAmount18) external { vm.assume(vaultId != bytes32(0)); @@ -295,7 +295,7 @@ contract OrderBookV6WithdrawEvalTest is OrderBookV6ExternalRealTest { /// A revert in the action prevents withdraw from being enacted. /// forge-config: default.fuzz.runs = 100 - function testOrderBookWithdrawalEvalRevertInAction( + function testRaindexWithdrawalEvalRevertInAction( address alice, bytes32 vaultId, uint256 depositAmount18, @@ -311,10 +311,10 @@ contract OrderBookV6WithdrawEvalTest is OrderBookV6ExternalRealTest { vm.startPrank(alice); vm.mockCall( address(iToken0), - abi.encodeWithSelector(IERC20.transferFrom.selector, alice, address(iOrderbook), depositAmount18), + abi.encodeWithSelector(IERC20.transferFrom.selector, alice, address(iRaindex), depositAmount18), abi.encode(true) ); - iOrderbook.deposit4(address(iToken0), vaultId, depositAmount, new TaskV2[](0)); + iRaindex.deposit4(address(iToken0), vaultId, depositAmount, new TaskV2[](0)); vm.mockCall( address(iToken0), @@ -326,12 +326,12 @@ contract OrderBookV6WithdrawEvalTest is OrderBookV6ExternalRealTest { evals[0] = bytes(":ensure(0 \"revert in action\");"); TaskV2[] memory actions = evalsToActions(evals); - assertTrue(depositAmount.eq(iOrderbook.vaultBalance2(alice, address(iToken0), vaultId))); + assertTrue(depositAmount.eq(iRaindex.vaultBalance2(alice, address(iToken0), vaultId))); vm.expectRevert("revert in action"); - iOrderbook.withdraw4(address(iToken0), vaultId, withdrawAmount, actions); + iRaindex.withdraw4(address(iToken0), vaultId, withdrawAmount, actions); - assertTrue(depositAmount.eq(iOrderbook.vaultBalance2(alice, address(iToken0), vaultId))); + assertTrue(depositAmount.eq(iRaindex.vaultBalance2(alice, address(iToken0), vaultId))); } /// forge-config: default.fuzz.runs = 100 @@ -353,9 +353,9 @@ contract OrderBookV6WithdrawEvalTest is OrderBookV6ExternalRealTest { evals[0] = bytes( string.concat( usingWordsFrom, - ":ensure(equal-to(orderbook() ", - address(iOrderbook).toHexString(), - ") \"orderbook is iOrderbook\");" + ":ensure(equal-to(raindex() ", + address(iRaindex).toHexString(), + ") \"raindex is iRaindex\");" ) ); evals[1] = bytes( diff --git a/test/concrete/ob/OrderBookV6.withdraw.t.sol b/test/concrete/ob/RaindexV6.withdraw.t.sol similarity index 82% rename from test/concrete/ob/OrderBookV6.withdraw.t.sol rename to test/concrete/ob/RaindexV6.withdraw.t.sol index e9a7d1f7c0..96af2852bb 100644 --- a/test/concrete/ob/OrderBookV6.withdraw.t.sol +++ b/test/concrete/ob/RaindexV6.withdraw.t.sol @@ -6,7 +6,7 @@ import {Test} from "forge-std/Test.sol"; import {Math} from "openzeppelin-contracts/contracts/utils/math/Math.sol"; -import {OrderBookV6ExternalMockTest, REVERTING_MOCK_BYTECODE} from "test/util/abstract/OrderBookV6ExternalMockTest.sol"; +import {RaindexV6ExternalMockTest, REVERTING_MOCK_BYTECODE} from "test/util/abstract/RaindexV6ExternalMockTest.sol"; import {Reenteroor, IERC20} from "test/util/concrete/Reenteroor.sol"; import {TaskV2, IRaindexV6} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; @@ -15,9 +15,9 @@ import {Float, LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibDecimalFloatImplementation} from "rain.math.float/lib/implementation/LibDecimalFloatImplementation.sol"; import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; -/// @title OrderBookV6WithdrawTest +/// @title RaindexV6WithdrawTest /// Tests withdrawing from the order book. -contract OrderBookV6WithdrawTest is OrderBookV6ExternalMockTest { +contract RaindexV6WithdrawTest is RaindexV6ExternalMockTest { using Math for uint256; using LibDecimalFloat for Float; @@ -30,7 +30,7 @@ contract OrderBookV6WithdrawTest is OrderBookV6ExternalMockTest { function testWithdrawZeroVaultId(address alice, address token) external { vm.prank(alice); vm.expectRevert(abi.encodeWithSelector(IRaindexV6.ZeroVaultId.selector, alice, token)); - iOrderbook.withdraw4(token, bytes32(0), Float.wrap(0), new TaskV2[](0)); + iRaindex.withdraw4(token, bytes32(0), Float.wrap(0), new TaskV2[](0)); } /// Withdrawing a zero target amount should revert. @@ -39,7 +39,7 @@ contract OrderBookV6WithdrawTest is OrderBookV6ExternalMockTest { vm.assume(vaultId != bytes32(0)); vm.prank(alice); vm.expectRevert(abi.encodeWithSelector(ZeroWithdrawTargetAmount.selector, alice, token, vaultId)); - iOrderbook.withdraw4(token, vaultId, Float.wrap(0), new TaskV2[](0)); + iRaindex.withdraw4(token, vaultId, Float.wrap(0), new TaskV2[](0)); } /// Withdrawing a non-zero amount from an empty vault should be a noop. @@ -52,8 +52,8 @@ contract OrderBookV6WithdrawTest is OrderBookV6ExternalMockTest { vm.expectEmit(false, false, false, true); emit WithdrawV2(alice, address(iToken0), vaultId, amount, Float.wrap(0), 0); vm.record(); - iOrderbook.withdraw4(address(iToken0), vaultId, amount, new TaskV2[](0)); - (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iOrderbook)); + iRaindex.withdraw4(address(iToken0), vaultId, amount, new TaskV2[](0)); + (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iRaindex)); assertEq(reads.length, 6, "reads"); assertEq(writes.length, 3, "writes"); } @@ -69,15 +69,15 @@ contract OrderBookV6WithdrawTest is OrderBookV6ExternalMockTest { vm.prank(alice); vm.mockCall( address(iToken0), - abi.encodeWithSelector(IERC20.transferFrom.selector, alice, address(iOrderbook), depositAmount18), + abi.encodeWithSelector(IERC20.transferFrom.selector, alice, address(iRaindex), depositAmount18), abi.encode(true) ); Float depositAmount = LibDecimalFloat.fromFixedDecimalLosslessPacked(depositAmount18, 18); Float withdrawAmount = LibDecimalFloat.fromFixedDecimalLosslessPacked(withdrawAmount18, 18); - iOrderbook.deposit4(address(iToken0), vaultId, depositAmount, new TaskV2[](0)); - assertTrue(iOrderbook.vaultBalance2(address(alice), address(iToken0), vaultId).eq(depositAmount)); + iRaindex.deposit4(address(iToken0), vaultId, depositAmount, new TaskV2[](0)); + assertTrue(iRaindex.vaultBalance2(address(alice), address(iToken0), vaultId).eq(depositAmount)); vm.prank(alice); vm.mockCall( @@ -85,8 +85,8 @@ contract OrderBookV6WithdrawTest is OrderBookV6ExternalMockTest { ); vm.expectEmit(false, false, false, true); emit WithdrawV2(alice, address(iToken0), vaultId, withdrawAmount, depositAmount, depositAmount18); - iOrderbook.withdraw4(address(iToken0), vaultId, withdrawAmount, new TaskV2[](0)); - assertTrue(iOrderbook.vaultBalance2(address(alice), address(iToken0), vaultId).isZero(), "vault balance"); + iRaindex.withdraw4(address(iToken0), vaultId, withdrawAmount, new TaskV2[](0)); + assertTrue(iRaindex.vaultBalance2(address(alice), address(iToken0), vaultId).isZero(), "vault balance"); } /// Withdrawing a partial amount from a vault should reduce the vault balance. @@ -100,15 +100,15 @@ contract OrderBookV6WithdrawTest is OrderBookV6ExternalMockTest { vm.prank(alice); vm.mockCall( address(iToken0), - abi.encodeWithSelector(IERC20.transferFrom.selector, alice, address(iOrderbook), depositAmount18), + abi.encodeWithSelector(IERC20.transferFrom.selector, alice, address(iRaindex), depositAmount18), abi.encode(true) ); Float depositAmount = LibDecimalFloat.fromFixedDecimalLosslessPacked(depositAmount18, 18); Float withdrawAmount = LibDecimalFloat.fromFixedDecimalLosslessPacked(withdrawAmount18, 18); - iOrderbook.deposit4(address(iToken0), vaultId, depositAmount, new TaskV2[](0)); - assertTrue(iOrderbook.vaultBalance2(address(alice), address(iToken0), vaultId).eq(depositAmount)); + iRaindex.deposit4(address(iToken0), vaultId, depositAmount, new TaskV2[](0)); + assertTrue(iRaindex.vaultBalance2(address(alice), address(iToken0), vaultId).eq(depositAmount)); vm.prank(alice); vm.mockCall( @@ -119,10 +119,10 @@ contract OrderBookV6WithdrawTest is OrderBookV6ExternalMockTest { vm.expectEmit(false, false, false, true); // The full withdraw amount is possible as it's only a partial withdraw. emit WithdrawV2(alice, address(iToken0), vaultId, withdrawAmount, withdrawAmount, withdrawAmount18); - iOrderbook.withdraw4(address(iToken0), vaultId, withdrawAmount, new TaskV2[](0)); + iRaindex.withdraw4(address(iToken0), vaultId, withdrawAmount, new TaskV2[](0)); // The vault balance is reduced by the withdraw amount. assertTrue( - iOrderbook.vaultBalance2(address(alice), address(iToken0), vaultId).eq(depositAmount.sub(withdrawAmount)) + iRaindex.vaultBalance2(address(alice), address(iToken0), vaultId).eq(depositAmount.sub(withdrawAmount)) ); } @@ -137,18 +137,18 @@ contract OrderBookV6WithdrawTest is OrderBookV6ExternalMockTest { vm.prank(alice); vm.mockCall( address(iToken0), - abi.encodeWithSelector(IERC20.transferFrom.selector, alice, address(iOrderbook), depositAmount18), + abi.encodeWithSelector(IERC20.transferFrom.selector, alice, address(iRaindex), depositAmount18), abi.encode(true) ); Float depositAmount = LibDecimalFloat.fromFixedDecimalLosslessPacked(depositAmount18, 18); Float withdrawAmount = LibDecimalFloat.fromFixedDecimalLosslessPacked(withdrawAmount18, 18); - iOrderbook.deposit4(address(iToken0), vaultId, depositAmount, new TaskV2[](0)); - assertTrue(iOrderbook.vaultBalance2(address(alice), address(iToken0), vaultId).eq(depositAmount)); + iRaindex.deposit4(address(iToken0), vaultId, depositAmount, new TaskV2[](0)); + assertTrue(iRaindex.vaultBalance2(address(alice), address(iToken0), vaultId).eq(depositAmount)); // The token contract always reverts when not mocked. vm.prank(alice); vm.expectRevert(); - iOrderbook.withdraw4(address(iToken0), vaultId, withdrawAmount, new TaskV2[](0)); + iRaindex.withdraw4(address(iToken0), vaultId, withdrawAmount, new TaskV2[](0)); vm.prank(alice); vm.mockCall( @@ -157,7 +157,7 @@ contract OrderBookV6WithdrawTest is OrderBookV6ExternalMockTest { abi.encode(false) ); vm.expectRevert(abi.encodeWithSelector(SafeERC20.SafeERC20FailedOperation.selector, address(iToken0))); - iOrderbook.withdraw4(address(iToken0), vaultId, withdrawAmount, new TaskV2[](0)); + iRaindex.withdraw4(address(iToken0), vaultId, withdrawAmount, new TaskV2[](0)); } /// Defines an action that can be taken in withdrawal tests. @@ -209,7 +209,7 @@ contract OrderBookV6WithdrawTest is OrderBookV6ExternalMockTest { action.vaultId = bytes32(uint256(0x01)); } vm.etch(action.token, REVERTING_MOCK_BYTECODE); - Float balance = iOrderbook.vaultBalance2(action.alice, action.token, action.vaultId); + Float balance = iRaindex.vaultBalance2(action.alice, action.token, action.vaultId); vm.prank(action.alice); if (action.actionKind || !sHasDeposit[sRunID][action.token]) { @@ -217,7 +217,7 @@ contract OrderBookV6WithdrawTest is OrderBookV6ExternalMockTest { vm.mockCall( action.token, abi.encodeWithSelector( - IERC20.transferFrom.selector, action.alice, address(iOrderbook), uint256(action.amount) + IERC20.transferFrom.selector, action.alice, address(iRaindex), uint256(action.amount) ), abi.encode(true) ); @@ -227,9 +227,9 @@ contract OrderBookV6WithdrawTest is OrderBookV6ExternalMockTest { vm.expectEmit(false, false, false, true); emit DepositV2(action.alice, action.token, action.vaultId, action.amount); - iOrderbook.deposit4(action.token, action.vaultId, action.amountFloat, new TaskV2[](0)); + iRaindex.deposit4(action.token, action.vaultId, action.amountFloat, new TaskV2[](0)); assertTrue( - iOrderbook.vaultBalance2(action.alice, action.token, action.vaultId) + iRaindex.vaultBalance2(action.alice, action.token, action.vaultId) .eq(balance.add(action.amountFloat)), "vault balance on deposit" ); @@ -256,9 +256,9 @@ contract OrderBookV6WithdrawTest is OrderBookV6ExternalMockTest { expectedActualAmount18 ); } - iOrderbook.withdraw4(action.token, action.vaultId, action.amountFloat, new TaskV2[](0)); + iRaindex.withdraw4(action.token, action.vaultId, action.amountFloat, new TaskV2[](0)); assertTrue( - iOrderbook.vaultBalance2(action.alice, action.token, action.vaultId) + iRaindex.vaultBalance2(action.alice, action.token, action.vaultId) .eq(balance.sub(expectedActualAmount)), "vault balance on withdraw" ); diff --git a/test/concrete/parser/OrderBookV6SubParser.describedByMeta.t.sol b/test/concrete/parser/OrderBookV6SubParser.describedByMeta.t.sol deleted file mode 100644 index 3dd34ff471..0000000000 --- a/test/concrete/parser/OrderBookV6SubParser.describedByMeta.t.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity =0.8.25; - -import {Test} from "forge-std/Test.sol"; -import {OrderBookV6SubParser} from "../../../src/concrete/parser/OrderBookV6SubParser.sol"; -import {LibOrderBookDeploy} from "../../../src/lib/deploy/LibOrderBookDeploy.sol"; -import {LibEtchOrderBook} from "test/util/lib/LibEtchOrderBook.sol"; - -contract OrderBookV6SubParserDescribedByMetaV1Test is Test { - function setUp() public { - LibEtchOrderBook.etchOrderBook(vm); - } - - function testOrderBookV6SubParserDescribedByMetaV1Happy() external view { - bytes memory describedByMeta = vm.readFileBinary("meta/OrderBookV6SubParser.rain.meta"); - OrderBookV6SubParser subParser = OrderBookV6SubParser(LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS); - - assertEq(keccak256(describedByMeta), subParser.describedByMetaV1()); - } -} diff --git a/test/concrete/parser/OrderBookV6SubParser.contextCalculatedIORatio.t.sol b/test/concrete/parser/RaindexV6SubParser.contextCalculatedIORatio.t.sol similarity index 57% rename from test/concrete/parser/OrderBookV6SubParser.contextCalculatedIORatio.t.sol rename to test/concrete/parser/RaindexV6SubParser.contextCalculatedIORatio.t.sol index ac9a80ffcc..cde9758b40 100644 --- a/test/concrete/parser/OrderBookV6SubParser.contextCalculatedIORatio.t.sol +++ b/test/concrete/parser/RaindexV6SubParser.contextCalculatedIORatio.t.sol @@ -2,9 +2,9 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6SubParserContextTest} from "test/util/abstract/OrderBookV6SubParserContextTest.sol"; +import {RaindexV6SubParserContextTest} from "test/util/abstract/RaindexV6SubParserContextTest.sol"; -contract OrderBookV6SubParserContextCalculatedIORatioTest is OrderBookV6SubParserContextTest { +contract RaindexV6SubParserContextCalculatedIORatioTest is RaindexV6SubParserContextTest { function word() internal pure override returns (string memory) { return "calculated-io-ratio"; } diff --git a/test/concrete/parser/OrderBookV6SubParser.contextCalculatedMaxOutput.t.sol b/test/concrete/parser/RaindexV6SubParser.contextCalculatedMaxOutput.t.sol similarity index 57% rename from test/concrete/parser/OrderBookV6SubParser.contextCalculatedMaxOutput.t.sol rename to test/concrete/parser/RaindexV6SubParser.contextCalculatedMaxOutput.t.sol index b0a2816734..fb96a13a26 100644 --- a/test/concrete/parser/OrderBookV6SubParser.contextCalculatedMaxOutput.t.sol +++ b/test/concrete/parser/RaindexV6SubParser.contextCalculatedMaxOutput.t.sol @@ -2,9 +2,9 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6SubParserContextTest} from "test/util/abstract/OrderBookV6SubParserContextTest.sol"; +import {RaindexV6SubParserContextTest} from "test/util/abstract/RaindexV6SubParserContextTest.sol"; -contract OrderBookV6SubParserContextCalculatedMaxOutputTest is OrderBookV6SubParserContextTest { +contract RaindexV6SubParserContextCalculatedMaxOutputTest is RaindexV6SubParserContextTest { function word() internal pure override returns (string memory) { return "calculated-max-output"; } diff --git a/test/concrete/parser/OrderBookV6SubParser.contextInputToken.t.sol b/test/concrete/parser/RaindexV6SubParser.contextInputToken.t.sol similarity index 57% rename from test/concrete/parser/OrderBookV6SubParser.contextInputToken.t.sol rename to test/concrete/parser/RaindexV6SubParser.contextInputToken.t.sol index 61fb0af35f..2b5e8e39d0 100644 --- a/test/concrete/parser/OrderBookV6SubParser.contextInputToken.t.sol +++ b/test/concrete/parser/RaindexV6SubParser.contextInputToken.t.sol @@ -2,9 +2,9 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6SubParserContextTest} from "test/util/abstract/OrderBookV6SubParserContextTest.sol"; +import {RaindexV6SubParserContextTest} from "test/util/abstract/RaindexV6SubParserContextTest.sol"; -contract OrderBookV6SubParserContextInputTokenTest is OrderBookV6SubParserContextTest { +contract RaindexV6SubParserContextInputTokenTest is RaindexV6SubParserContextTest { function word() internal pure override returns (string memory) { return "input-token"; } diff --git a/test/concrete/parser/OrderBookV6SubParser.contextInputTokenDecimals.t.sol b/test/concrete/parser/RaindexV6SubParser.contextInputTokenDecimals.t.sol similarity index 57% rename from test/concrete/parser/OrderBookV6SubParser.contextInputTokenDecimals.t.sol rename to test/concrete/parser/RaindexV6SubParser.contextInputTokenDecimals.t.sol index ebb396827d..c837bd178d 100644 --- a/test/concrete/parser/OrderBookV6SubParser.contextInputTokenDecimals.t.sol +++ b/test/concrete/parser/RaindexV6SubParser.contextInputTokenDecimals.t.sol @@ -2,9 +2,9 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6SubParserContextTest} from "test/util/abstract/OrderBookV6SubParserContextTest.sol"; +import {RaindexV6SubParserContextTest} from "test/util/abstract/RaindexV6SubParserContextTest.sol"; -contract OrderBookV6SubParserContextInputTokenDecimalsTest is OrderBookV6SubParserContextTest { +contract RaindexV6SubParserContextInputTokenDecimalsTest is RaindexV6SubParserContextTest { function word() internal pure override returns (string memory) { return "input-token-decimals"; } diff --git a/test/concrete/parser/OrderBookV6SubParser.contextInputVaultBalanceBefore.t.sol b/test/concrete/parser/RaindexV6SubParser.contextInputVaultBalanceBefore.t.sol similarity index 56% rename from test/concrete/parser/OrderBookV6SubParser.contextInputVaultBalanceBefore.t.sol rename to test/concrete/parser/RaindexV6SubParser.contextInputVaultBalanceBefore.t.sol index 8302fc2c56..ae0d7eb595 100644 --- a/test/concrete/parser/OrderBookV6SubParser.contextInputVaultBalanceBefore.t.sol +++ b/test/concrete/parser/RaindexV6SubParser.contextInputVaultBalanceBefore.t.sol @@ -2,9 +2,9 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6SubParserContextTest} from "test/util/abstract/OrderBookV6SubParserContextTest.sol"; +import {RaindexV6SubParserContextTest} from "test/util/abstract/RaindexV6SubParserContextTest.sol"; -contract OrderBookV6SubParserContextInputVaultBalanceBeforeTest is OrderBookV6SubParserContextTest { +contract RaindexV6SubParserContextInputVaultBalanceBeforeTest is RaindexV6SubParserContextTest { function word() internal pure override returns (string memory) { return "input-vault-before"; } diff --git a/test/concrete/parser/OrderBookV6SubParser.contextInputVaultBalanceIncrease.t.sol b/test/concrete/parser/RaindexV6SubParser.contextInputVaultBalanceIncrease.t.sol similarity index 56% rename from test/concrete/parser/OrderBookV6SubParser.contextInputVaultBalanceIncrease.t.sol rename to test/concrete/parser/RaindexV6SubParser.contextInputVaultBalanceIncrease.t.sol index 996c58ff70..5f43c3476e 100644 --- a/test/concrete/parser/OrderBookV6SubParser.contextInputVaultBalanceIncrease.t.sol +++ b/test/concrete/parser/RaindexV6SubParser.contextInputVaultBalanceIncrease.t.sol @@ -2,9 +2,9 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6SubParserContextTest} from "test/util/abstract/OrderBookV6SubParserContextTest.sol"; +import {RaindexV6SubParserContextTest} from "test/util/abstract/RaindexV6SubParserContextTest.sol"; -contract OrderBookV6SubParserContextInputVaultBalanceIncreaseTest is OrderBookV6SubParserContextTest { +contract RaindexV6SubParserContextInputVaultBalanceIncreaseTest is RaindexV6SubParserContextTest { function word() internal pure override returns (string memory) { return "input-vault-increase"; } diff --git a/test/concrete/parser/OrderBookV6SubParser.contextInputVaultId.t.sol b/test/concrete/parser/RaindexV6SubParser.contextInputVaultId.t.sol similarity index 57% rename from test/concrete/parser/OrderBookV6SubParser.contextInputVaultId.t.sol rename to test/concrete/parser/RaindexV6SubParser.contextInputVaultId.t.sol index fc80c44981..200c71ef4e 100644 --- a/test/concrete/parser/OrderBookV6SubParser.contextInputVaultId.t.sol +++ b/test/concrete/parser/RaindexV6SubParser.contextInputVaultId.t.sol @@ -2,9 +2,9 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6SubParserContextTest} from "test/util/abstract/OrderBookV6SubParserContextTest.sol"; +import {RaindexV6SubParserContextTest} from "test/util/abstract/RaindexV6SubParserContextTest.sol"; -contract OrderBookV6SubParserContextInputVaultIdTest is OrderBookV6SubParserContextTest { +contract RaindexV6SubParserContextInputVaultIdTest is RaindexV6SubParserContextTest { function word() internal pure override returns (string memory) { return "input-vault-id"; } diff --git a/test/concrete/parser/OrderBookV6SubParser.contextOrderClearer.t.sol b/test/concrete/parser/RaindexV6SubParser.contextOrderClearer.t.sol similarity index 57% rename from test/concrete/parser/OrderBookV6SubParser.contextOrderClearer.t.sol rename to test/concrete/parser/RaindexV6SubParser.contextOrderClearer.t.sol index b01cd5ebdf..e8a05fd062 100644 --- a/test/concrete/parser/OrderBookV6SubParser.contextOrderClearer.t.sol +++ b/test/concrete/parser/RaindexV6SubParser.contextOrderClearer.t.sol @@ -2,9 +2,9 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6SubParserContextTest} from "test/util/abstract/OrderBookV6SubParserContextTest.sol"; +import {RaindexV6SubParserContextTest} from "test/util/abstract/RaindexV6SubParserContextTest.sol"; -contract OrderBookV6SubParserContextOrderClearerTest is OrderBookV6SubParserContextTest { +contract RaindexV6SubParserContextOrderClearerTest is RaindexV6SubParserContextTest { function word() internal pure override returns (string memory) { return "order-clearer"; } diff --git a/test/concrete/parser/OrderBookV6SubParser.contextOrderCounterparty.t.sol b/test/concrete/parser/RaindexV6SubParser.contextOrderCounterparty.t.sol similarity index 57% rename from test/concrete/parser/OrderBookV6SubParser.contextOrderCounterparty.t.sol rename to test/concrete/parser/RaindexV6SubParser.contextOrderCounterparty.t.sol index 543c1093ca..703094c53b 100644 --- a/test/concrete/parser/OrderBookV6SubParser.contextOrderCounterparty.t.sol +++ b/test/concrete/parser/RaindexV6SubParser.contextOrderCounterparty.t.sol @@ -2,9 +2,9 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6SubParserContextTest} from "test/util/abstract/OrderBookV6SubParserContextTest.sol"; +import {RaindexV6SubParserContextTest} from "test/util/abstract/RaindexV6SubParserContextTest.sol"; -contract OrderBookV6SubParserContextOrderCounterpartyTest is OrderBookV6SubParserContextTest { +contract RaindexV6SubParserContextOrderCounterpartyTest is RaindexV6SubParserContextTest { function word() internal pure override returns (string memory) { return "order-counterparty"; } diff --git a/test/concrete/parser/OrderBookV6SubParser.contextOrderHash.t.sol b/test/concrete/parser/RaindexV6SubParser.contextOrderHash.t.sol similarity index 57% rename from test/concrete/parser/OrderBookV6SubParser.contextOrderHash.t.sol rename to test/concrete/parser/RaindexV6SubParser.contextOrderHash.t.sol index f6132173e5..935fddda0e 100644 --- a/test/concrete/parser/OrderBookV6SubParser.contextOrderHash.t.sol +++ b/test/concrete/parser/RaindexV6SubParser.contextOrderHash.t.sol @@ -2,9 +2,9 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6SubParserContextTest} from "test/util/abstract/OrderBookV6SubParserContextTest.sol"; +import {RaindexV6SubParserContextTest} from "test/util/abstract/RaindexV6SubParserContextTest.sol"; -contract OrderBookV6SubParserContextOrderHashTest is OrderBookV6SubParserContextTest { +contract RaindexV6SubParserContextOrderHashTest is RaindexV6SubParserContextTest { function word() internal pure override returns (string memory) { return "order-hash"; } diff --git a/test/concrete/parser/OrderBookV6SubParser.contextOrderOwner.t.sol b/test/concrete/parser/RaindexV6SubParser.contextOrderOwner.t.sol similarity index 57% rename from test/concrete/parser/OrderBookV6SubParser.contextOrderOwner.t.sol rename to test/concrete/parser/RaindexV6SubParser.contextOrderOwner.t.sol index ce5ad54dc0..079e910eca 100644 --- a/test/concrete/parser/OrderBookV6SubParser.contextOrderOwner.t.sol +++ b/test/concrete/parser/RaindexV6SubParser.contextOrderOwner.t.sol @@ -2,9 +2,9 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6SubParserContextTest} from "test/util/abstract/OrderBookV6SubParserContextTest.sol"; +import {RaindexV6SubParserContextTest} from "test/util/abstract/RaindexV6SubParserContextTest.sol"; -contract OrderBookV6SubParserContextOrderOwnerTest is OrderBookV6SubParserContextTest { +contract RaindexV6SubParserContextOrderOwnerTest is RaindexV6SubParserContextTest { function word() internal pure override returns (string memory) { return "order-owner"; } diff --git a/test/concrete/parser/OrderBookV6SubParser.contextOutputToken.t.sol b/test/concrete/parser/RaindexV6SubParser.contextOutputToken.t.sol similarity index 57% rename from test/concrete/parser/OrderBookV6SubParser.contextOutputToken.t.sol rename to test/concrete/parser/RaindexV6SubParser.contextOutputToken.t.sol index 5d8e3c1a12..d4401622c6 100644 --- a/test/concrete/parser/OrderBookV6SubParser.contextOutputToken.t.sol +++ b/test/concrete/parser/RaindexV6SubParser.contextOutputToken.t.sol @@ -2,9 +2,9 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6SubParserContextTest} from "test/util/abstract/OrderBookV6SubParserContextTest.sol"; +import {RaindexV6SubParserContextTest} from "test/util/abstract/RaindexV6SubParserContextTest.sol"; -contract OrderBookV6SubParserContextOutputTokenTest is OrderBookV6SubParserContextTest { +contract RaindexV6SubParserContextOutputTokenTest is RaindexV6SubParserContextTest { function word() internal pure override returns (string memory) { return "output-token"; } diff --git a/test/concrete/parser/OrderBookV6SubParser.contextOutputTokenDecimals.t.sol b/test/concrete/parser/RaindexV6SubParser.contextOutputTokenDecimals.t.sol similarity index 57% rename from test/concrete/parser/OrderBookV6SubParser.contextOutputTokenDecimals.t.sol rename to test/concrete/parser/RaindexV6SubParser.contextOutputTokenDecimals.t.sol index 44c539b786..93cf09c5d2 100644 --- a/test/concrete/parser/OrderBookV6SubParser.contextOutputTokenDecimals.t.sol +++ b/test/concrete/parser/RaindexV6SubParser.contextOutputTokenDecimals.t.sol @@ -2,9 +2,9 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6SubParserContextTest} from "test/util/abstract/OrderBookV6SubParserContextTest.sol"; +import {RaindexV6SubParserContextTest} from "test/util/abstract/RaindexV6SubParserContextTest.sol"; -contract OrderBookV6SubParserContextOutputTokenDecimalsTest is OrderBookV6SubParserContextTest { +contract RaindexV6SubParserContextOutputTokenDecimalsTest is RaindexV6SubParserContextTest { function word() internal pure override returns (string memory) { return "output-token-decimals"; } diff --git a/test/concrete/parser/OrderBookV6SubParser.contextOutputVaultBalanceBefore.t.sol b/test/concrete/parser/RaindexV6SubParser.contextOutputVaultBalanceBefore.t.sol similarity index 56% rename from test/concrete/parser/OrderBookV6SubParser.contextOutputVaultBalanceBefore.t.sol rename to test/concrete/parser/RaindexV6SubParser.contextOutputVaultBalanceBefore.t.sol index e19466e653..bfc244b73e 100644 --- a/test/concrete/parser/OrderBookV6SubParser.contextOutputVaultBalanceBefore.t.sol +++ b/test/concrete/parser/RaindexV6SubParser.contextOutputVaultBalanceBefore.t.sol @@ -2,9 +2,9 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6SubParserContextTest} from "test/util/abstract/OrderBookV6SubParserContextTest.sol"; +import {RaindexV6SubParserContextTest} from "test/util/abstract/RaindexV6SubParserContextTest.sol"; -contract OrderBookV6SubParserContextOutputVaultBalanceBeforeTest is OrderBookV6SubParserContextTest { +contract RaindexV6SubParserContextOutputVaultBalanceBeforeTest is RaindexV6SubParserContextTest { function word() internal pure override returns (string memory) { return "output-vault-before"; } diff --git a/test/concrete/parser/OrderBookV6SubParser.contextOutputVaultBalanceDecrease.t.sol b/test/concrete/parser/RaindexV6SubParser.contextOutputVaultBalanceDecrease.t.sol similarity index 56% rename from test/concrete/parser/OrderBookV6SubParser.contextOutputVaultBalanceDecrease.t.sol rename to test/concrete/parser/RaindexV6SubParser.contextOutputVaultBalanceDecrease.t.sol index 1774ff6f64..cb5b73fb0c 100644 --- a/test/concrete/parser/OrderBookV6SubParser.contextOutputVaultBalanceDecrease.t.sol +++ b/test/concrete/parser/RaindexV6SubParser.contextOutputVaultBalanceDecrease.t.sol @@ -2,9 +2,9 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6SubParserContextTest} from "test/util/abstract/OrderBookV6SubParserContextTest.sol"; +import {RaindexV6SubParserContextTest} from "test/util/abstract/RaindexV6SubParserContextTest.sol"; -contract OrderBookV6SubParserContextOutputVaultBalanceDecreaseTest is OrderBookV6SubParserContextTest { +contract RaindexV6SubParserContextOutputVaultBalanceDecreaseTest is RaindexV6SubParserContextTest { function word() internal pure override returns (string memory) { return "output-vault-decrease"; } diff --git a/test/concrete/parser/OrderBookV6SubParser.contextOutputVaultId.t.sol b/test/concrete/parser/RaindexV6SubParser.contextOutputVaultId.t.sol similarity index 57% rename from test/concrete/parser/OrderBookV6SubParser.contextOutputVaultId.t.sol rename to test/concrete/parser/RaindexV6SubParser.contextOutputVaultId.t.sol index 3cc0b8d7b9..1d447e5344 100644 --- a/test/concrete/parser/OrderBookV6SubParser.contextOutputVaultId.t.sol +++ b/test/concrete/parser/RaindexV6SubParser.contextOutputVaultId.t.sol @@ -2,9 +2,9 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6SubParserContextTest} from "test/util/abstract/OrderBookV6SubParserContextTest.sol"; +import {RaindexV6SubParserContextTest} from "test/util/abstract/RaindexV6SubParserContextTest.sol"; -contract OrderBookV6SubParserContextOutputVaultIdTest is OrderBookV6SubParserContextTest { +contract RaindexV6SubParserContextOutputVaultIdTest is RaindexV6SubParserContextTest { function word() internal pure override returns (string memory) { return "output-vault-id"; } diff --git a/test/concrete/parser/OrderBookV6SubParser.contextOrderBook.t.sol b/test/concrete/parser/RaindexV6SubParser.contextRaindex.t.sol similarity index 50% rename from test/concrete/parser/OrderBookV6SubParser.contextOrderBook.t.sol rename to test/concrete/parser/RaindexV6SubParser.contextRaindex.t.sol index 24a536891d..fb27422924 100644 --- a/test/concrete/parser/OrderBookV6SubParser.contextOrderBook.t.sol +++ b/test/concrete/parser/RaindexV6SubParser.contextRaindex.t.sol @@ -2,10 +2,10 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6SubParserContextTest} from "test/util/abstract/OrderBookV6SubParserContextTest.sol"; +import {RaindexV6SubParserContextTest} from "test/util/abstract/RaindexV6SubParserContextTest.sol"; -contract OrderBookV6SubParserContextOrderBookTest is OrderBookV6SubParserContextTest { +contract RaindexV6SubParserContextRaindexTest is RaindexV6SubParserContextTest { function word() internal pure override returns (string memory) { - return "orderbook"; + return "raindex"; } } diff --git a/test/concrete/parser/RaindexV6SubParser.describedByMeta.t.sol b/test/concrete/parser/RaindexV6SubParser.describedByMeta.t.sol new file mode 100644 index 0000000000..64cab2cfb2 --- /dev/null +++ b/test/concrete/parser/RaindexV6SubParser.describedByMeta.t.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity =0.8.25; + +import {Test} from "forge-std/Test.sol"; +import {RaindexV6SubParser} from "../../../src/concrete/parser/RaindexV6SubParser.sol"; +import {LibRaindexDeploy} from "../../../src/lib/deploy/LibRaindexDeploy.sol"; +import {LibEtchRaindex} from "test/util/lib/LibEtchRaindex.sol"; + +contract RaindexV6SubParserDescribedByMetaV1Test is Test { + function setUp() public { + LibEtchRaindex.etchRaindex(vm); + } + + function testRaindexV6SubParserDescribedByMetaV1Happy() external view { + bytes memory describedByMeta = vm.readFileBinary("meta/RaindexV6SubParser.rain.meta"); + RaindexV6SubParser subParser = RaindexV6SubParser(LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS); + + assertEq(keccak256(describedByMeta), subParser.describedByMetaV1()); + } +} diff --git a/test/concrete/parser/OrderBookV6SubParser.ierc165.t.sol b/test/concrete/parser/RaindexV6SubParser.ierc165.t.sol similarity index 73% rename from test/concrete/parser/OrderBookV6SubParser.ierc165.t.sol rename to test/concrete/parser/RaindexV6SubParser.ierc165.t.sol index b8857c61e3..819c9d57c9 100644 --- a/test/concrete/parser/OrderBookV6SubParser.ierc165.t.sol +++ b/test/concrete/parser/RaindexV6SubParser.ierc165.t.sol @@ -5,27 +5,27 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {IERC165} from "openzeppelin-contracts/contracts/utils/introspection/IERC165.sol"; -import {OrderBookV6SubParser} from "../../../src/concrete/parser/OrderBookV6SubParser.sol"; +import {RaindexV6SubParser} from "../../../src/concrete/parser/RaindexV6SubParser.sol"; import {ISubParserV4} from "rain.interpreter.interface/interface/ISubParserV4.sol"; import {IDescribedByMetaV1} from "rain.metadata/interface/IDescribedByMetaV1.sol"; import {IParserToolingV1} from "rain.sol.codegen/interface/IParserToolingV1.sol"; import {ISubParserToolingV1} from "rain.sol.codegen/interface/ISubParserToolingV1.sol"; -import {LibOrderBookDeploy} from "../../../src/lib/deploy/LibOrderBookDeploy.sol"; -import {LibEtchOrderBook} from "test/util/lib/LibEtchOrderBook.sol"; +import {LibRaindexDeploy} from "../../../src/lib/deploy/LibRaindexDeploy.sol"; +import {LibEtchRaindex} from "test/util/lib/LibEtchRaindex.sol"; -contract OrderBookV6SubParserIERC165Test is Test { +contract RaindexV6SubParserIERC165Test is Test { function setUp() public { - LibEtchOrderBook.etchOrderBook(vm); + LibEtchRaindex.etchRaindex(vm); } - function testOrderBookV6SubParserIERC165(bytes4 badInterfaceId) external view { + function testRaindexV6SubParserIERC165(bytes4 badInterfaceId) external view { vm.assume(badInterfaceId != type(IERC165).interfaceId); vm.assume(badInterfaceId != type(ISubParserV4).interfaceId); vm.assume(badInterfaceId != type(IDescribedByMetaV1).interfaceId); vm.assume(badInterfaceId != type(IParserToolingV1).interfaceId); vm.assume(badInterfaceId != type(ISubParserToolingV1).interfaceId); - OrderBookV6SubParser subParser = OrderBookV6SubParser(LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS); + RaindexV6SubParser subParser = RaindexV6SubParser(LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS); assertTrue(subParser.supportsInterface(type(IERC165).interfaceId)); assertTrue(subParser.supportsInterface(type(ISubParserV4).interfaceId)); assertTrue(subParser.supportsInterface(type(IDescribedByMetaV1).interfaceId)); diff --git a/test/concrete/parser/OrderBookV6SubParser.pointers.t.sol b/test/concrete/parser/RaindexV6SubParser.pointers.t.sol similarity index 70% rename from test/concrete/parser/OrderBookV6SubParser.pointers.t.sol rename to test/concrete/parser/RaindexV6SubParser.pointers.t.sol index 2d6d14fd13..e292cda33f 100644 --- a/test/concrete/parser/OrderBookV6SubParser.pointers.t.sol +++ b/test/concrete/parser/RaindexV6SubParser.pointers.t.sol @@ -4,27 +4,27 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import { - LibOrderBookSubParser, + LibRaindexSubParser, AuthoringMetaV2, EXTERN_PARSE_META_BUILD_DEPTH -} from "../../../src/lib/LibOrderBookSubParser.sol"; +} from "../../../src/lib/LibRaindexSubParser.sol"; import { SUB_PARSER_PARSE_META, SUB_PARSER_WORD_PARSERS, SUB_PARSER_OPERAND_HANDLERS, - OrderBookV6SubParser -} from "../../../src/concrete/parser/OrderBookV6SubParser.sol"; + RaindexV6SubParser +} from "../../../src/concrete/parser/RaindexV6SubParser.sol"; import {LibGenParseMeta} from "rain.interpreter.interface/lib/codegen/LibGenParseMeta.sol"; -import {LibOrderBookDeploy} from "../../../src/lib/deploy/LibOrderBookDeploy.sol"; -import {LibEtchOrderBook} from "test/util/lib/LibEtchOrderBook.sol"; +import {LibRaindexDeploy} from "../../../src/lib/deploy/LibRaindexDeploy.sol"; +import {LibEtchRaindex} from "test/util/lib/LibEtchRaindex.sol"; -contract OrderBookV6SubParserPointersTest is Test { +contract RaindexV6SubParserPointersTest is Test { function setUp() public { - LibEtchOrderBook.etchOrderBook(vm); + LibEtchRaindex.etchRaindex(vm); } function testSubParserParseMeta() external pure { - bytes memory authoringMetaBytes = LibOrderBookSubParser.authoringMetaV2(); + bytes memory authoringMetaBytes = LibRaindexSubParser.authoringMetaV2(); AuthoringMetaV2[] memory authoringMeta = abi.decode(authoringMetaBytes, (AuthoringMetaV2[])); bytes memory expected = LibGenParseMeta.buildParseMetaV2(authoringMeta, EXTERN_PARSE_META_BUILD_DEPTH); bytes memory actual = SUB_PARSER_PARSE_META; @@ -32,14 +32,14 @@ contract OrderBookV6SubParserPointersTest is Test { } function testSubParserFunctionPointers() external pure { - OrderBookV6SubParser extern = OrderBookV6SubParser(LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS); + RaindexV6SubParser extern = RaindexV6SubParser(LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS); bytes memory expected = extern.buildSubParserWordParsers(); bytes memory actual = SUB_PARSER_WORD_PARSERS; assertEq(actual, expected); } function testSubParserOperandParsers() external pure { - OrderBookV6SubParser extern = OrderBookV6SubParser(LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS); + RaindexV6SubParser extern = RaindexV6SubParser(LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS); bytes memory expected = extern.buildOperandHandlerFunctionPointers(); bytes memory actual = SUB_PARSER_OPERAND_HANDLERS; assertEq(actual, expected); diff --git a/test/concrete/parser/OrderBookV6SubParser.signedContext.t.sol b/test/concrete/parser/RaindexV6SubParser.signedContext.t.sol similarity index 71% rename from test/concrete/parser/OrderBookV6SubParser.signedContext.t.sol rename to test/concrete/parser/RaindexV6SubParser.signedContext.t.sol index ae9e8f45f3..8925821aa7 100644 --- a/test/concrete/parser/OrderBookV6SubParser.signedContext.t.sol +++ b/test/concrete/parser/RaindexV6SubParser.signedContext.t.sol @@ -6,20 +6,20 @@ import {StackAllocationMismatch} from "rain.interpreter/error/ErrIntegrity.sol"; import {ExpectedOperand, UnexpectedOperandValue} from "rain.interpreter/error/ErrParse.sol"; import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol"; import {OpTest, StackItem} from "rain.interpreter/../test/abstract/OpTest.sol"; -import {LibOrderBookSubParserContextFixture} from "test/util/fixture/LibOrderBookSubParserContextFixture.sol"; -import {LibOrderBookDeploy} from "../../../src/lib/deploy/LibOrderBookDeploy.sol"; -import {LibEtchOrderBook} from "test/util/lib/LibEtchOrderBook.sol"; +import {LibRaindexSubParserContextFixture} from "test/util/fixture/LibRaindexSubParserContextFixture.sol"; +import {LibRaindexDeploy} from "../../../src/lib/deploy/LibRaindexDeploy.sol"; +import {LibEtchRaindex} from "test/util/lib/LibEtchRaindex.sol"; -contract OrderBookV6SubParserSignedContextTest is OpTest { +contract RaindexV6SubParserSignedContextTest is OpTest { using Strings for address; function setUp() public { - LibEtchOrderBook.etchOrderBook(vm); + LibEtchRaindex.etchRaindex(vm); } /// Test signed-context-0-0 function testSubParserContextSignedContextHappy0() external view { - address subParserAddress = LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS; + address subParserAddress = LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS; StackItem[] memory expectedStack = new StackItem[](1); expectedStack[0] = StackItem.wrap(keccak256(bytes("signed-context-0-0"))); @@ -28,13 +28,13 @@ contract OrderBookV6SubParserSignedContextTest is OpTest { bytes(string.concat("using-words-from ", subParserAddress.toHexString(), " _: signed-context<0 0>();")); checkHappy( - rainlang, LibOrderBookSubParserContextFixture.hashedNamesContext(), expectedStack, "signed-context-0-0" + rainlang, LibRaindexSubParserContextFixture.hashedNamesContext(), expectedStack, "signed-context-0-0" ); } /// Test signed-context-0-1 function testSubParserContextSignedContextHappy1() external view { - address subParserAddress = LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS; + address subParserAddress = LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS; StackItem[] memory expectedStack = new StackItem[](1); expectedStack[0] = StackItem.wrap(keccak256(bytes("signed-context-0-1"))); @@ -43,13 +43,13 @@ contract OrderBookV6SubParserSignedContextTest is OpTest { bytes(string.concat("using-words-from ", subParserAddress.toHexString(), " _: signed-context<0 1>();")); checkHappy( - rainlang, LibOrderBookSubParserContextFixture.hashedNamesContext(), expectedStack, "signed-context-0-1" + rainlang, LibRaindexSubParserContextFixture.hashedNamesContext(), expectedStack, "signed-context-0-1" ); } /// Test signed-context-1-0 function testSubParserContextSignedContextHappy2() external view { - address subParserAddress = LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS; + address subParserAddress = LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS; StackItem[] memory expectedStack = new StackItem[](1); expectedStack[0] = StackItem.wrap(keccak256(bytes("signed-context-1-0"))); @@ -58,13 +58,13 @@ contract OrderBookV6SubParserSignedContextTest is OpTest { bytes(string.concat("using-words-from ", subParserAddress.toHexString(), " _: signed-context<1 0>();")); checkHappy( - rainlang, LibOrderBookSubParserContextFixture.hashedNamesContext(), expectedStack, "signed-context-1-0" + rainlang, LibRaindexSubParserContextFixture.hashedNamesContext(), expectedStack, "signed-context-1-0" ); } /// Test signed-context-1-1 function testSubParserContextSignedContextHappy3() external view { - address subParserAddress = LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS; + address subParserAddress = LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS; StackItem[] memory expectedStack = new StackItem[](1); expectedStack[0] = StackItem.wrap(keccak256(bytes("signed-context-1-1"))); @@ -73,13 +73,13 @@ contract OrderBookV6SubParserSignedContextTest is OpTest { bytes(string.concat("using-words-from ", subParserAddress.toHexString(), " _: signed-context<1 1>();")); checkHappy( - rainlang, LibOrderBookSubParserContextFixture.hashedNamesContext(), expectedStack, "signed-context-1-1" + rainlang, LibRaindexSubParserContextFixture.hashedNamesContext(), expectedStack, "signed-context-1-1" ); } /// Test signed-context without an operand errors. function testSubParserContextSignedContextUnhappyNoOperand() external { - address subParserAddress = LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS; + address subParserAddress = LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS; bytes memory rainlang = bytes(string.concat("using-words-from ", subParserAddress.toHexString(), " _: signed-context();")); @@ -89,7 +89,7 @@ contract OrderBookV6SubParserSignedContextTest is OpTest { /// Test signed-context with too many operands errors. function testSubParserContextSignedContextUnhappyTooManyOperands() external { - address subParserAddress = LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS; + address subParserAddress = LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS; bytes memory rainlang = bytes(string.concat("using-words-from ", subParserAddress.toHexString(), " _: signed-context<0 0 0>();")); @@ -99,7 +99,7 @@ contract OrderBookV6SubParserSignedContextTest is OpTest { /// Test signed-context with an input errors. function testSubParserContextSignedContextUnhappyInput() external { - address subParserAddress = LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS; + address subParserAddress = LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS; bytes memory rainlang = bytes(string.concat("using-words-from ", subParserAddress.toHexString(), " _: signed-context<0 0>(0);")); diff --git a/test/concrete/parser/OrderBookV6SubParser.signers.t.sol b/test/concrete/parser/RaindexV6SubParser.signers.t.sol similarity index 70% rename from test/concrete/parser/OrderBookV6SubParser.signers.t.sol rename to test/concrete/parser/RaindexV6SubParser.signers.t.sol index 27e6c209fd..6249ebb3d0 100644 --- a/test/concrete/parser/OrderBookV6SubParser.signers.t.sol +++ b/test/concrete/parser/RaindexV6SubParser.signers.t.sol @@ -6,20 +6,20 @@ import {StackAllocationMismatch} from "rain.interpreter/error/ErrIntegrity.sol"; import {ExpectedOperand, UnexpectedOperandValue} from "rain.interpreter/error/ErrParse.sol"; import {OpTest, StackItem} from "rain.interpreter/../test/abstract/OpTest.sol"; import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol"; -import {LibOrderBookSubParserContextFixture} from "test/util/fixture/LibOrderBookSubParserContextFixture.sol"; -import {LibOrderBookDeploy} from "../../../src/lib/deploy/LibOrderBookDeploy.sol"; -import {LibEtchOrderBook} from "test/util/lib/LibEtchOrderBook.sol"; +import {LibRaindexSubParserContextFixture} from "test/util/fixture/LibRaindexSubParserContextFixture.sol"; +import {LibRaindexDeploy} from "../../../src/lib/deploy/LibRaindexDeploy.sol"; +import {LibEtchRaindex} from "test/util/lib/LibEtchRaindex.sol"; -contract OrderBookV6SubParserSignersTest is OpTest { +contract RaindexV6SubParserSignersTest is OpTest { using Strings for address; function setUp() public { - LibEtchOrderBook.etchOrderBook(vm); + LibEtchRaindex.etchRaindex(vm); } /// Test signer-0 function testSubParserContextSignerHappy0() external view { - address subParserAddress = LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS; + address subParserAddress = LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS; StackItem[] memory expectedStack = new StackItem[](1); expectedStack[0] = StackItem.wrap(keccak256(bytes("signer-0"))); @@ -27,12 +27,12 @@ contract OrderBookV6SubParserSignersTest is OpTest { bytes memory rainlang = bytes(string.concat("using-words-from ", subParserAddress.toHexString(), " _: signer<0>();")); - checkHappy(rainlang, LibOrderBookSubParserContextFixture.hashedNamesContext(), expectedStack, "signer-0"); + checkHappy(rainlang, LibRaindexSubParserContextFixture.hashedNamesContext(), expectedStack, "signer-0"); } /// Test signer-1 function testSubParserContextSignerHappy1() external view { - address subParserAddress = LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS; + address subParserAddress = LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS; StackItem[] memory expectedStack = new StackItem[](1); expectedStack[0] = StackItem.wrap(keccak256(bytes("signer-1"))); @@ -40,12 +40,12 @@ contract OrderBookV6SubParserSignersTest is OpTest { bytes memory rainlang = bytes(string.concat("using-words-from ", subParserAddress.toHexString(), " _: signer<1>();")); - checkHappy(rainlang, LibOrderBookSubParserContextFixture.hashedNamesContext(), expectedStack, "signer-1"); + checkHappy(rainlang, LibRaindexSubParserContextFixture.hashedNamesContext(), expectedStack, "signer-1"); } /// Test signer without an operand errors. function testSubParserContextSignerUnhappyNoOperand() external { - address subParserAddress = LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS; + address subParserAddress = LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS; bytes memory rainlang = bytes(string.concat("using-words-from ", subParserAddress.toHexString(), " _: signer();")); @@ -55,7 +55,7 @@ contract OrderBookV6SubParserSignersTest is OpTest { /// Test signer with too many operands errors. function testSubParserContextSignerUnhappyTooManyOperands() external { - address subParserAddress = LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS; + address subParserAddress = LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS; bytes memory rainlang = bytes(string.concat("using-words-from ", subParserAddress.toHexString(), " _: signer<0 1>();")); @@ -65,7 +65,7 @@ contract OrderBookV6SubParserSignersTest is OpTest { /// Test signer with an input errors. function testSubParserContextSignerUnhappyInput() external { - address subParserAddress = LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS; + address subParserAddress = LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS; bytes memory rainlang = bytes(string.concat("using-words-from ", subParserAddress.toHexString(), " _: signer<0>(0);")); diff --git a/test/lib/LibOrderBookArb.finalizeArbNativeGas.t.sol b/test/lib/LibRaindexArb.finalizeArbNativeGas.t.sol similarity index 95% rename from test/lib/LibOrderBookArb.finalizeArbNativeGas.t.sol rename to test/lib/LibRaindexArb.finalizeArbNativeGas.t.sol index d44f3b1582..ccba68efa5 100644 --- a/test/lib/LibOrderBookArb.finalizeArbNativeGas.t.sol +++ b/test/lib/LibRaindexArb.finalizeArbNativeGas.t.sol @@ -5,7 +5,7 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {LibTestArb, ArbResult} from "test/util/lib/LibTestArb.sol"; -contract LibOrderBookArbFinalizeArbNativeGasTest is Test { +contract LibRaindexArbFinalizeArbNativeGasTest is Test { /// finalizeArb MUST send native gas balance to msg.sender. function testFinalizeArbSendsNativeGas() external { uint256 senderBalanceBefore = address(this).balance; diff --git a/test/lib/LibOrderBookArb.finalizeArbOutputTokenProfit.t.sol b/test/lib/LibRaindexArb.finalizeArbOutputTokenProfit.t.sol similarity index 89% rename from test/lib/LibOrderBookArb.finalizeArbOutputTokenProfit.t.sol rename to test/lib/LibRaindexArb.finalizeArbOutputTokenProfit.t.sol index 29da5f9104..e6e8813172 100644 --- a/test/lib/LibOrderBookArb.finalizeArbOutputTokenProfit.t.sol +++ b/test/lib/LibRaindexArb.finalizeArbOutputTokenProfit.t.sol @@ -5,7 +5,7 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {LibTestArb, ArbResult} from "test/util/lib/LibTestArb.sol"; -contract LibOrderBookArbFinalizeArbOutputTokenProfitTest is Test { +contract LibRaindexArbFinalizeArbOutputTokenProfitTest is Test { /// finalizeArb MUST transfer remaining output token profit to msg.sender. function testFinalizeArbTransfersOutputTokenProfit() external { // OB has 100e18 output, pulls 80e18 input. Exchange has 80e18 input. @@ -20,7 +20,7 @@ contract LibOrderBookArbFinalizeArbOutputTokenProfitTest is Test { assertEq(result.inputToken.balanceOf(address(result.arb)), 0, "arb inputToken"); assertEq(result.outputToken.balanceOf(address(result.arb)), 0, "arb outputToken"); // OB got exactly what it pulled. - assertEq(result.inputToken.balanceOf(address(result.orderBook)), 80e18, "OB inputToken"); + assertEq(result.inputToken.balanceOf(address(result.raindex)), 80e18, "OB inputToken"); // Exchange did a partial swap. assertEq(result.outputToken.balanceOf(address(result.exchange)), 80e18, "exchange outputToken"); } diff --git a/test/lib/LibOrderBookArb.finalizeArbTaskContext.t.sol b/test/lib/LibRaindexArb.finalizeArbTaskContext.t.sol similarity index 95% rename from test/lib/LibOrderBookArb.finalizeArbTaskContext.t.sol rename to test/lib/LibRaindexArb.finalizeArbTaskContext.t.sol index 59b07c72f8..f1160065a5 100644 --- a/test/lib/LibOrderBookArb.finalizeArbTaskContext.t.sol +++ b/test/lib/LibRaindexArb.finalizeArbTaskContext.t.sol @@ -10,11 +10,11 @@ import {IParserV2} from "rain.interpreter.interface/interface/IParserV2.sol"; import {LibInterpreterDeploy} from "rain.interpreter/lib/deploy/LibInterpreterDeploy.sol"; import {LibTestArb, ArbResult} from "test/util/lib/LibTestArb.sol"; -/// @title LibOrderBookArbFinalizeArbTaskContextTest +/// @title LibRaindexArbFinalizeArbTaskContextTest /// @notice Verifies that finalizeArb passes correct Float-encoded context to /// the post-arb task: context<1 0>=input balance, context<1 1>=output balance, /// context<1 2>=gas balance. Column 0 is the calling context added by LibContext. -contract LibOrderBookArbFinalizeArbTaskContextTest is Test { +contract LibRaindexArbFinalizeArbTaskContextTest is Test { function testFinalizeArbTaskContextValues() external { LibInterpreterDeploy.etchRainlang(vm); diff --git a/test/lib/LibOrderBookArb.finalizeArbTokenTransfers.t.sol b/test/lib/LibRaindexArb.finalizeArbTokenTransfers.t.sol similarity index 88% rename from test/lib/LibOrderBookArb.finalizeArbTokenTransfers.t.sol rename to test/lib/LibRaindexArb.finalizeArbTokenTransfers.t.sol index 3c889d65c4..e6b3938f90 100644 --- a/test/lib/LibOrderBookArb.finalizeArbTokenTransfers.t.sol +++ b/test/lib/LibRaindexArb.finalizeArbTokenTransfers.t.sol @@ -5,7 +5,7 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {LibTestArb, ArbResult} from "test/util/lib/LibTestArb.sol"; -contract LibOrderBookArbFinalizeArbTokenTransfersTest is Test { +contract LibRaindexArbFinalizeArbTokenTransfersTest is Test { /// finalizeArb MUST transfer remaining input token profit to msg.sender. function testFinalizeArbTransfersInputTokenProfit() external { // OB has 100e18 output, pulls 80e18 input. Exchange has 100e18 input. @@ -18,7 +18,7 @@ contract LibOrderBookArbFinalizeArbTokenTransfersTest is Test { assertEq(result.inputToken.balanceOf(address(result.arb)), 0, "arb inputToken"); assertEq(result.outputToken.balanceOf(address(result.arb)), 0, "arb outputToken"); // OB got exactly what it pulled. - assertEq(result.inputToken.balanceOf(address(result.orderBook)), 80e18, "OB inputToken"); + assertEq(result.inputToken.balanceOf(address(result.raindex)), 80e18, "OB inputToken"); // Exchange did a full swap. assertEq(result.outputToken.balanceOf(address(result.exchange)), 100e18, "exchange outputToken"); } diff --git a/test/lib/deploy/LibOrderBookDeploy.t.sol b/test/lib/deploy/LibOrderBookDeploy.t.sol deleted file mode 100644 index 563693aee5..0000000000 --- a/test/lib/deploy/LibOrderBookDeploy.t.sol +++ /dev/null @@ -1,311 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity =0.8.25; - -import {Test} from "forge-std/Test.sol"; -import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; -import {LibOrderBookDeploy} from "../../../src/lib/deploy/LibOrderBookDeploy.sol"; -import {LibEtchOrderBook} from "test/util/lib/LibEtchOrderBook.sol"; -import {OrderBookV6} from "../../../src/concrete/ob/OrderBookV6.sol"; -import {OrderBookV6SubParser} from "../../../src/concrete/parser/OrderBookV6SubParser.sol"; -import { - CREATION_CODE as ORDERBOOK_CREATION_CODE, - RUNTIME_CODE as ORDERBOOK_RUNTIME_CODE, - DEPLOYED_ADDRESS as ORDERBOOK_GENERATED_ADDRESS -} from "../../../src/generated/OrderBookV6.pointers.sol"; -import { - CREATION_CODE as SUB_PARSER_CREATION_CODE, - RUNTIME_CODE as SUB_PARSER_RUNTIME_CODE, - DEPLOYED_ADDRESS as SUB_PARSER_GENERATED_ADDRESS -} from "../../../src/generated/OrderBookV6SubParser.pointers.sol"; -import { - RUNTIME_CODE as ROUTE_PROCESSOR_RUNTIME_CODE, - DEPLOYED_ADDRESS as ROUTE_PROCESSOR_GENERATED_ADDRESS, - BYTECODE_HASH as ROUTE_PROCESSOR_GENERATED_CODEHASH -} from "../../../src/generated/RouteProcessor4.pointers.sol"; -import {ROUTE_PROCESSOR_4_CREATION_CODE} from "../../../src/lib/deploy/LibRouteProcessor4CreationCode.sol"; -import {GenericPoolOrderBookV6ArbOrderTaker} from "../../../src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol"; -import { - RouteProcessorOrderBookV6ArbOrderTaker -} from "../../../src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol"; -import {GenericPoolOrderBookV6FlashBorrower} from "../../../src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol"; -import { - RUNTIME_CODE as GENERIC_POOL_ARB_OT_RUNTIME_CODE, - DEPLOYED_ADDRESS as GENERIC_POOL_ARB_OT_GENERATED_ADDRESS, - BYTECODE_HASH as GENERIC_POOL_ARB_OT_GENERATED_CODEHASH -} from "../../../src/generated/GenericPoolOrderBookV6ArbOrderTaker.pointers.sol"; -import { - RUNTIME_CODE as RP_ARB_OT_RUNTIME_CODE, - DEPLOYED_ADDRESS as RP_ARB_OT_GENERATED_ADDRESS, - BYTECODE_HASH as RP_ARB_OT_GENERATED_CODEHASH -} from "../../../src/generated/RouteProcessorOrderBookV6ArbOrderTaker.pointers.sol"; -import { - RUNTIME_CODE as GENERIC_POOL_FB_RUNTIME_CODE, - DEPLOYED_ADDRESS as GENERIC_POOL_FB_GENERATED_ADDRESS, - BYTECODE_HASH as GENERIC_POOL_FB_GENERATED_CODEHASH -} from "../../../src/generated/GenericPoolOrderBookV6FlashBorrower.pointers.sol"; - -contract LibOrderBookDeployTest is Test { - /// Deploying OrderBookV6 via Zoltu MUST produce the expected address and - /// codehash. - function testDeployAddressOrderBook() external { - LibRainDeploy.etchZoltuFactory(vm); - - address deployedAddress = LibRainDeploy.deployZoltu(type(OrderBookV6).creationCode); - - assertEq(deployedAddress, LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS); - assertTrue(address(deployedAddress).code.length > 0, "Deployed address has no code"); - assertEq(address(deployedAddress).codehash, LibOrderBookDeploy.ORDERBOOK_DEPLOYED_CODEHASH); - } - - /// Deploying OrderBookV6SubParser via Zoltu MUST produce the expected - /// address and codehash. - function testDeployAddressSubParser() external { - LibRainDeploy.etchZoltuFactory(vm); - - address deployedAddress = LibRainDeploy.deployZoltu(type(OrderBookV6SubParser).creationCode); - - assertEq(deployedAddress, LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS); - assertTrue(address(deployedAddress).code.length > 0, "Deployed address has no code"); - assertEq(address(deployedAddress).codehash, LibOrderBookDeploy.SUB_PARSER_DEPLOYED_CODEHASH); - } - - /// The codehash of a freshly deployed OrderBookV6 MUST match the expected - /// codehash constant. - function testExpectedCodeHashOrderBook() external { - OrderBookV6 ob = new OrderBookV6(); - assertEq(address(ob).codehash, LibOrderBookDeploy.ORDERBOOK_DEPLOYED_CODEHASH); - } - - /// The codehash of a freshly deployed OrderBookV6SubParser MUST match the - /// expected codehash constant. - function testExpectedCodeHashSubParser() external { - OrderBookV6SubParser subParser = new OrderBookV6SubParser(); - assertEq(address(subParser).codehash, LibOrderBookDeploy.SUB_PARSER_DEPLOYED_CODEHASH); - } - - /// The precompiled creation code constant for OrderBookV6 MUST match the - /// compiler's creation code. - function testCreationCodeOrderBook() external pure { - assertEq(keccak256(ORDERBOOK_CREATION_CODE), keccak256(type(OrderBookV6).creationCode)); - } - - /// The precompiled creation code constant for OrderBookV6SubParser MUST - /// match the compiler's creation code. - function testCreationCodeSubParser() external pure { - assertEq(keccak256(SUB_PARSER_CREATION_CODE), keccak256(type(OrderBookV6SubParser).creationCode)); - } - - /// The precompiled runtime code constant for OrderBookV6 MUST match the - /// deployed runtime bytecode. - function testRuntimeCodeOrderBook() external { - OrderBookV6 ob = new OrderBookV6(); - assertEq(keccak256(ORDERBOOK_RUNTIME_CODE), keccak256(address(ob).code)); - } - - /// The precompiled runtime code constant for OrderBookV6SubParser MUST - /// match the deployed runtime bytecode. - function testRuntimeCodeSubParser() external { - OrderBookV6SubParser subParser = new OrderBookV6SubParser(); - assertEq(keccak256(SUB_PARSER_RUNTIME_CODE), keccak256(address(subParser).code)); - } - - /// The generated deployed address for OrderBookV6 MUST match the deploy - /// library constant. - function testGeneratedDeployedAddressOrderBook() external pure { - assertEq(ORDERBOOK_GENERATED_ADDRESS, LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS); - } - - /// The generated deployed address for OrderBookV6SubParser MUST match the - /// deploy library constant. - function testGeneratedDeployedAddressSubParser() external pure { - assertEq(SUB_PARSER_GENERATED_ADDRESS, LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS); - } - - /// Deploying RouteProcessor4 via Zoltu MUST produce the expected address - /// and codehash. - function testDeployAddressRouteProcessor() external { - LibRainDeploy.etchZoltuFactory(vm); - - address deployedAddress = LibRainDeploy.deployZoltu(ROUTE_PROCESSOR_4_CREATION_CODE); - - assertEq(deployedAddress, LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS); - assertTrue(address(deployedAddress).code.length > 0, "Deployed address has no code"); - assertEq(address(deployedAddress).codehash, LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_CODEHASH); - } - - /// The precompiled runtime code constant for RouteProcessor4 MUST match - /// the deployed runtime bytecode. - function testRuntimeCodeRouteProcessor() external { - bytes memory creationCode = ROUTE_PROCESSOR_4_CREATION_CODE; - address deployed; - assembly ("memory-safe") { - deployed := create(0, add(creationCode, 0x20), mload(creationCode)) - } - assertTrue(deployed != address(0), "RouteProcessor4 deployment failed"); - assertEq(keccak256(ROUTE_PROCESSOR_RUNTIME_CODE), keccak256(deployed.code)); - } - - /// The generated deployed address for RouteProcessor4 MUST match the - /// deploy library constant. - function testGeneratedDeployedAddressRouteProcessor() external pure { - assertEq(ROUTE_PROCESSOR_GENERATED_ADDRESS, LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS); - } - - /// The generated codehash for RouteProcessor4 MUST match the deploy - /// library constant. - function testGeneratedCodehashRouteProcessor() external pure { - assertEq(ROUTE_PROCESSOR_GENERATED_CODEHASH, LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_CODEHASH); - } - - /// Deploying GenericPoolOrderBookV6ArbOrderTaker via Zoltu MUST produce - /// the expected address and codehash. - function testDeployAddressGenericPoolArbOrderTaker() external { - LibRainDeploy.etchZoltuFactory(vm); - - address deployedAddress = LibRainDeploy.deployZoltu(type(GenericPoolOrderBookV6ArbOrderTaker).creationCode); - - assertEq(deployedAddress, LibOrderBookDeploy.GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_ADDRESS); - assertTrue(address(deployedAddress).code.length > 0, "Deployed address has no code"); - assertEq(address(deployedAddress).codehash, LibOrderBookDeploy.GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_CODEHASH); - } - - /// Deploying RouteProcessorOrderBookV6ArbOrderTaker via Zoltu MUST produce - /// the expected address and codehash. - function testDeployAddressRouteProcessorArbOrderTaker() external { - LibRainDeploy.etchZoltuFactory(vm); - - address deployedAddress = LibRainDeploy.deployZoltu(type(RouteProcessorOrderBookV6ArbOrderTaker).creationCode); - - assertEq(deployedAddress, LibOrderBookDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_ADDRESS); - assertTrue(address(deployedAddress).code.length > 0, "Deployed address has no code"); - assertEq( - address(deployedAddress).codehash, LibOrderBookDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_CODEHASH - ); - } - - /// Deploying GenericPoolOrderBookV6FlashBorrower via Zoltu MUST produce - /// the expected address and codehash. - function testDeployAddressGenericPoolFlashBorrower() external { - LibRainDeploy.etchZoltuFactory(vm); - - address deployedAddress = LibRainDeploy.deployZoltu(type(GenericPoolOrderBookV6FlashBorrower).creationCode); - - assertEq(deployedAddress, LibOrderBookDeploy.GENERIC_POOL_FLASH_BORROWER_DEPLOYED_ADDRESS); - assertTrue(address(deployedAddress).code.length > 0, "Deployed address has no code"); - assertEq(address(deployedAddress).codehash, LibOrderBookDeploy.GENERIC_POOL_FLASH_BORROWER_DEPLOYED_CODEHASH); - } - - /// The codehash of a freshly deployed GenericPoolOrderBookV6ArbOrderTaker - /// MUST match the expected codehash constant. - function testExpectedCodeHashGenericPoolArbOrderTaker() external { - GenericPoolOrderBookV6ArbOrderTaker arb = new GenericPoolOrderBookV6ArbOrderTaker(); - assertEq(address(arb).codehash, LibOrderBookDeploy.GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_CODEHASH); - } - - /// The codehash of a freshly deployed RouteProcessorOrderBookV6ArbOrderTaker - /// MUST match the expected codehash constant. - function testExpectedCodeHashRouteProcessorArbOrderTaker() external { - RouteProcessorOrderBookV6ArbOrderTaker arb = new RouteProcessorOrderBookV6ArbOrderTaker(); - assertEq(address(arb).codehash, LibOrderBookDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_CODEHASH); - } - - /// The codehash of a freshly deployed GenericPoolOrderBookV6FlashBorrower - /// MUST match the expected codehash constant. - function testExpectedCodeHashGenericPoolFlashBorrower() external { - GenericPoolOrderBookV6FlashBorrower fb = new GenericPoolOrderBookV6FlashBorrower(); - assertEq(address(fb).codehash, LibOrderBookDeploy.GENERIC_POOL_FLASH_BORROWER_DEPLOYED_CODEHASH); - } - - /// The precompiled runtime code for GenericPoolOrderBookV6ArbOrderTaker - /// MUST match the deployed runtime bytecode. - function testRuntimeCodeGenericPoolArbOrderTaker() external { - GenericPoolOrderBookV6ArbOrderTaker arb = new GenericPoolOrderBookV6ArbOrderTaker(); - assertEq(keccak256(GENERIC_POOL_ARB_OT_RUNTIME_CODE), keccak256(address(arb).code)); - } - - /// The precompiled runtime code for RouteProcessorOrderBookV6ArbOrderTaker - /// MUST match the deployed runtime bytecode. - function testRuntimeCodeRouteProcessorArbOrderTaker() external { - RouteProcessorOrderBookV6ArbOrderTaker arb = new RouteProcessorOrderBookV6ArbOrderTaker(); - assertEq(keccak256(RP_ARB_OT_RUNTIME_CODE), keccak256(address(arb).code)); - } - - /// The precompiled runtime code for GenericPoolOrderBookV6FlashBorrower - /// MUST match the deployed runtime bytecode. - function testRuntimeCodeGenericPoolFlashBorrower() external { - GenericPoolOrderBookV6FlashBorrower fb = new GenericPoolOrderBookV6FlashBorrower(); - assertEq(keccak256(GENERIC_POOL_FB_RUNTIME_CODE), keccak256(address(fb).code)); - } - - /// The generated deployed address for GenericPoolOrderBookV6ArbOrderTaker - /// MUST match the deploy library constant. - function testGeneratedDeployedAddressGenericPoolArbOrderTaker() external pure { - assertEq( - GENERIC_POOL_ARB_OT_GENERATED_ADDRESS, LibOrderBookDeploy.GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_ADDRESS - ); - } - - /// The generated deployed address for RouteProcessorOrderBookV6ArbOrderTaker - /// MUST match the deploy library constant. - function testGeneratedDeployedAddressRouteProcessorArbOrderTaker() external pure { - assertEq(RP_ARB_OT_GENERATED_ADDRESS, LibOrderBookDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_ADDRESS); - } - - /// The generated deployed address for GenericPoolOrderBookV6FlashBorrower - /// MUST match the deploy library constant. - function testGeneratedDeployedAddressGenericPoolFlashBorrower() external pure { - assertEq(GENERIC_POOL_FB_GENERATED_ADDRESS, LibOrderBookDeploy.GENERIC_POOL_FLASH_BORROWER_DEPLOYED_ADDRESS); - } - - /// The generated codehash for GenericPoolOrderBookV6ArbOrderTaker MUST - /// match the deploy library constant. - function testGeneratedCodehashGenericPoolArbOrderTaker() external pure { - assertEq( - GENERIC_POOL_ARB_OT_GENERATED_CODEHASH, LibOrderBookDeploy.GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_CODEHASH - ); - } - - /// The generated codehash for RouteProcessorOrderBookV6ArbOrderTaker MUST - /// match the deploy library constant. - function testGeneratedCodehashRouteProcessorArbOrderTaker() external pure { - assertEq(RP_ARB_OT_GENERATED_CODEHASH, LibOrderBookDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_CODEHASH); - } - - /// The generated codehash for GenericPoolOrderBookV6FlashBorrower MUST - /// match the deploy library constant. - function testGeneratedCodehashGenericPoolFlashBorrower() external pure { - assertEq(GENERIC_POOL_FB_GENERATED_CODEHASH, LibOrderBookDeploy.GENERIC_POOL_FLASH_BORROWER_DEPLOYED_CODEHASH); - } - - /// After calling etchOrderBook, all three contracts MUST have the expected - /// codehash at their expected addresses. - function testEtchOrderBook() external { - LibEtchOrderBook.etchOrderBook(vm); - - assertEq(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS.codehash, LibOrderBookDeploy.ORDERBOOK_DEPLOYED_CODEHASH); - assertEq( - LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS.codehash, LibOrderBookDeploy.SUB_PARSER_DEPLOYED_CODEHASH - ); - assertEq( - LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS.codehash, - LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_CODEHASH - ); - } - - /// Calling etchOrderBook twice MUST be idempotent — codehashes remain - /// correct on the second call. - function testEtchOrderBookIdempotent() external { - LibEtchOrderBook.etchOrderBook(vm); - LibEtchOrderBook.etchOrderBook(vm); - - assertEq(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS.codehash, LibOrderBookDeploy.ORDERBOOK_DEPLOYED_CODEHASH); - assertEq( - LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS.codehash, LibOrderBookDeploy.SUB_PARSER_DEPLOYED_CODEHASH - ); - assertEq( - LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS.codehash, - LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_CODEHASH - ); - } -} diff --git a/test/lib/deploy/LibRaindexDeploy.t.sol b/test/lib/deploy/LibRaindexDeploy.t.sol new file mode 100644 index 0000000000..ec956f2ec8 --- /dev/null +++ b/test/lib/deploy/LibRaindexDeploy.t.sol @@ -0,0 +1,311 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity =0.8.25; + +import {Test} from "forge-std/Test.sol"; +import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; +import {LibRaindexDeploy} from "../../../src/lib/deploy/LibRaindexDeploy.sol"; +import {LibEtchRaindex} from "test/util/lib/LibEtchRaindex.sol"; +import {RaindexV6} from "../../../src/concrete/ob/RaindexV6.sol"; +import {RaindexV6SubParser} from "../../../src/concrete/parser/RaindexV6SubParser.sol"; +import { + CREATION_CODE as RAINDEX_CREATION_CODE, + RUNTIME_CODE as RAINDEX_RUNTIME_CODE, + DEPLOYED_ADDRESS as RAINDEX_GENERATED_ADDRESS +} from "../../../src/generated/RaindexV6.pointers.sol"; +import { + CREATION_CODE as SUB_PARSER_CREATION_CODE, + RUNTIME_CODE as SUB_PARSER_RUNTIME_CODE, + DEPLOYED_ADDRESS as SUB_PARSER_GENERATED_ADDRESS +} from "../../../src/generated/RaindexV6SubParser.pointers.sol"; +import { + RUNTIME_CODE as ROUTE_PROCESSOR_RUNTIME_CODE, + DEPLOYED_ADDRESS as ROUTE_PROCESSOR_GENERATED_ADDRESS, + BYTECODE_HASH as ROUTE_PROCESSOR_GENERATED_CODEHASH +} from "../../../src/generated/RouteProcessor4.pointers.sol"; +import {ROUTE_PROCESSOR_4_CREATION_CODE} from "../../../src/lib/deploy/LibRouteProcessor4CreationCode.sol"; +import {GenericPoolRaindexV6ArbOrderTaker} from "../../../src/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.sol"; +import { + RouteProcessorRaindexV6ArbOrderTaker +} from "../../../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; +import {GenericPoolRaindexV6FlashBorrower} from "../../../src/concrete/arb/GenericPoolRaindexV6FlashBorrower.sol"; +import { + RUNTIME_CODE as GENERIC_POOL_ARB_OT_RUNTIME_CODE, + DEPLOYED_ADDRESS as GENERIC_POOL_ARB_OT_GENERATED_ADDRESS, + BYTECODE_HASH as GENERIC_POOL_ARB_OT_GENERATED_CODEHASH +} from "../../../src/generated/GenericPoolRaindexV6ArbOrderTaker.pointers.sol"; +import { + RUNTIME_CODE as RP_ARB_OT_RUNTIME_CODE, + DEPLOYED_ADDRESS as RP_ARB_OT_GENERATED_ADDRESS, + BYTECODE_HASH as RP_ARB_OT_GENERATED_CODEHASH +} from "../../../src/generated/RouteProcessorRaindexV6ArbOrderTaker.pointers.sol"; +import { + RUNTIME_CODE as GENERIC_POOL_FB_RUNTIME_CODE, + DEPLOYED_ADDRESS as GENERIC_POOL_FB_GENERATED_ADDRESS, + BYTECODE_HASH as GENERIC_POOL_FB_GENERATED_CODEHASH +} from "../../../src/generated/GenericPoolRaindexV6FlashBorrower.pointers.sol"; + +contract LibRaindexDeployTest is Test { + /// Deploying RaindexV6 via Zoltu MUST produce the expected address and + /// codehash. + function testDeployAddressRaindex() external { + LibRainDeploy.etchZoltuFactory(vm); + + address deployedAddress = LibRainDeploy.deployZoltu(type(RaindexV6).creationCode); + + assertEq(deployedAddress, LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS); + assertTrue(address(deployedAddress).code.length > 0, "Deployed address has no code"); + assertEq(address(deployedAddress).codehash, LibRaindexDeploy.RAINDEX_DEPLOYED_CODEHASH); + } + + /// Deploying RaindexV6SubParser via Zoltu MUST produce the expected + /// address and codehash. + function testDeployAddressSubParser() external { + LibRainDeploy.etchZoltuFactory(vm); + + address deployedAddress = LibRainDeploy.deployZoltu(type(RaindexV6SubParser).creationCode); + + assertEq(deployedAddress, LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS); + assertTrue(address(deployedAddress).code.length > 0, "Deployed address has no code"); + assertEq(address(deployedAddress).codehash, LibRaindexDeploy.SUB_PARSER_DEPLOYED_CODEHASH); + } + + /// The codehash of a freshly deployed RaindexV6 MUST match the expected + /// codehash constant. + function testExpectedCodeHashRaindex() external { + RaindexV6 ob = new RaindexV6(); + assertEq(address(ob).codehash, LibRaindexDeploy.RAINDEX_DEPLOYED_CODEHASH); + } + + /// The codehash of a freshly deployed RaindexV6SubParser MUST match the + /// expected codehash constant. + function testExpectedCodeHashSubParser() external { + RaindexV6SubParser subParser = new RaindexV6SubParser(); + assertEq(address(subParser).codehash, LibRaindexDeploy.SUB_PARSER_DEPLOYED_CODEHASH); + } + + /// The precompiled creation code constant for RaindexV6 MUST match the + /// compiler's creation code. + function testCreationCodeRaindex() external pure { + assertEq(keccak256(RAINDEX_CREATION_CODE), keccak256(type(RaindexV6).creationCode)); + } + + /// The precompiled creation code constant for RaindexV6SubParser MUST + /// match the compiler's creation code. + function testCreationCodeSubParser() external pure { + assertEq(keccak256(SUB_PARSER_CREATION_CODE), keccak256(type(RaindexV6SubParser).creationCode)); + } + + /// The precompiled runtime code constant for RaindexV6 MUST match the + /// deployed runtime bytecode. + function testRuntimeCodeRaindex() external { + RaindexV6 ob = new RaindexV6(); + assertEq(keccak256(RAINDEX_RUNTIME_CODE), keccak256(address(ob).code)); + } + + /// The precompiled runtime code constant for RaindexV6SubParser MUST + /// match the deployed runtime bytecode. + function testRuntimeCodeSubParser() external { + RaindexV6SubParser subParser = new RaindexV6SubParser(); + assertEq(keccak256(SUB_PARSER_RUNTIME_CODE), keccak256(address(subParser).code)); + } + + /// The generated deployed address for RaindexV6 MUST match the deploy + /// library constant. + function testGeneratedDeployedAddressRaindex() external pure { + assertEq(RAINDEX_GENERATED_ADDRESS, LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS); + } + + /// The generated deployed address for RaindexV6SubParser MUST match the + /// deploy library constant. + function testGeneratedDeployedAddressSubParser() external pure { + assertEq(SUB_PARSER_GENERATED_ADDRESS, LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS); + } + + /// Deploying RouteProcessor4 via Zoltu MUST produce the expected address + /// and codehash. + function testDeployAddressRouteProcessor() external { + LibRainDeploy.etchZoltuFactory(vm); + + address deployedAddress = LibRainDeploy.deployZoltu(ROUTE_PROCESSOR_4_CREATION_CODE); + + assertEq(deployedAddress, LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS); + assertTrue(address(deployedAddress).code.length > 0, "Deployed address has no code"); + assertEq(address(deployedAddress).codehash, LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_CODEHASH); + } + + /// The precompiled runtime code constant for RouteProcessor4 MUST match + /// the deployed runtime bytecode. + function testRuntimeCodeRouteProcessor() external { + bytes memory creationCode = ROUTE_PROCESSOR_4_CREATION_CODE; + address deployed; + assembly ("memory-safe") { + deployed := create(0, add(creationCode, 0x20), mload(creationCode)) + } + assertTrue(deployed != address(0), "RouteProcessor4 deployment failed"); + assertEq(keccak256(ROUTE_PROCESSOR_RUNTIME_CODE), keccak256(deployed.code)); + } + + /// The generated deployed address for RouteProcessor4 MUST match the + /// deploy library constant. + function testGeneratedDeployedAddressRouteProcessor() external pure { + assertEq(ROUTE_PROCESSOR_GENERATED_ADDRESS, LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS); + } + + /// The generated codehash for RouteProcessor4 MUST match the deploy + /// library constant. + function testGeneratedCodehashRouteProcessor() external pure { + assertEq(ROUTE_PROCESSOR_GENERATED_CODEHASH, LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_CODEHASH); + } + + /// Deploying GenericPoolRaindexV6ArbOrderTaker via Zoltu MUST produce + /// the expected address and codehash. + function testDeployAddressGenericPoolArbOrderTaker() external { + LibRainDeploy.etchZoltuFactory(vm); + + address deployedAddress = LibRainDeploy.deployZoltu(type(GenericPoolRaindexV6ArbOrderTaker).creationCode); + + assertEq(deployedAddress, LibRaindexDeploy.GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_ADDRESS); + assertTrue(address(deployedAddress).code.length > 0, "Deployed address has no code"); + assertEq(address(deployedAddress).codehash, LibRaindexDeploy.GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_CODEHASH); + } + + /// Deploying RouteProcessorRaindexV6ArbOrderTaker via Zoltu MUST produce + /// the expected address and codehash. + function testDeployAddressRouteProcessorArbOrderTaker() external { + LibRainDeploy.etchZoltuFactory(vm); + + address deployedAddress = LibRainDeploy.deployZoltu(type(RouteProcessorRaindexV6ArbOrderTaker).creationCode); + + assertEq(deployedAddress, LibRaindexDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_ADDRESS); + assertTrue(address(deployedAddress).code.length > 0, "Deployed address has no code"); + assertEq( + address(deployedAddress).codehash, LibRaindexDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_CODEHASH + ); + } + + /// Deploying GenericPoolRaindexV6FlashBorrower via Zoltu MUST produce + /// the expected address and codehash. + function testDeployAddressGenericPoolFlashBorrower() external { + LibRainDeploy.etchZoltuFactory(vm); + + address deployedAddress = LibRainDeploy.deployZoltu(type(GenericPoolRaindexV6FlashBorrower).creationCode); + + assertEq(deployedAddress, LibRaindexDeploy.GENERIC_POOL_FLASH_BORROWER_DEPLOYED_ADDRESS); + assertTrue(address(deployedAddress).code.length > 0, "Deployed address has no code"); + assertEq(address(deployedAddress).codehash, LibRaindexDeploy.GENERIC_POOL_FLASH_BORROWER_DEPLOYED_CODEHASH); + } + + /// The codehash of a freshly deployed GenericPoolRaindexV6ArbOrderTaker + /// MUST match the expected codehash constant. + function testExpectedCodeHashGenericPoolArbOrderTaker() external { + GenericPoolRaindexV6ArbOrderTaker arb = new GenericPoolRaindexV6ArbOrderTaker(); + assertEq(address(arb).codehash, LibRaindexDeploy.GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_CODEHASH); + } + + /// The codehash of a freshly deployed RouteProcessorRaindexV6ArbOrderTaker + /// MUST match the expected codehash constant. + function testExpectedCodeHashRouteProcessorArbOrderTaker() external { + RouteProcessorRaindexV6ArbOrderTaker arb = new RouteProcessorRaindexV6ArbOrderTaker(); + assertEq(address(arb).codehash, LibRaindexDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_CODEHASH); + } + + /// The codehash of a freshly deployed GenericPoolRaindexV6FlashBorrower + /// MUST match the expected codehash constant. + function testExpectedCodeHashGenericPoolFlashBorrower() external { + GenericPoolRaindexV6FlashBorrower fb = new GenericPoolRaindexV6FlashBorrower(); + assertEq(address(fb).codehash, LibRaindexDeploy.GENERIC_POOL_FLASH_BORROWER_DEPLOYED_CODEHASH); + } + + /// The precompiled runtime code for GenericPoolRaindexV6ArbOrderTaker + /// MUST match the deployed runtime bytecode. + function testRuntimeCodeGenericPoolArbOrderTaker() external { + GenericPoolRaindexV6ArbOrderTaker arb = new GenericPoolRaindexV6ArbOrderTaker(); + assertEq(keccak256(GENERIC_POOL_ARB_OT_RUNTIME_CODE), keccak256(address(arb).code)); + } + + /// The precompiled runtime code for RouteProcessorRaindexV6ArbOrderTaker + /// MUST match the deployed runtime bytecode. + function testRuntimeCodeRouteProcessorArbOrderTaker() external { + RouteProcessorRaindexV6ArbOrderTaker arb = new RouteProcessorRaindexV6ArbOrderTaker(); + assertEq(keccak256(RP_ARB_OT_RUNTIME_CODE), keccak256(address(arb).code)); + } + + /// The precompiled runtime code for GenericPoolRaindexV6FlashBorrower + /// MUST match the deployed runtime bytecode. + function testRuntimeCodeGenericPoolFlashBorrower() external { + GenericPoolRaindexV6FlashBorrower fb = new GenericPoolRaindexV6FlashBorrower(); + assertEq(keccak256(GENERIC_POOL_FB_RUNTIME_CODE), keccak256(address(fb).code)); + } + + /// The generated deployed address for GenericPoolRaindexV6ArbOrderTaker + /// MUST match the deploy library constant. + function testGeneratedDeployedAddressGenericPoolArbOrderTaker() external pure { + assertEq( + GENERIC_POOL_ARB_OT_GENERATED_ADDRESS, LibRaindexDeploy.GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_ADDRESS + ); + } + + /// The generated deployed address for RouteProcessorRaindexV6ArbOrderTaker + /// MUST match the deploy library constant. + function testGeneratedDeployedAddressRouteProcessorArbOrderTaker() external pure { + assertEq(RP_ARB_OT_GENERATED_ADDRESS, LibRaindexDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_ADDRESS); + } + + /// The generated deployed address for GenericPoolRaindexV6FlashBorrower + /// MUST match the deploy library constant. + function testGeneratedDeployedAddressGenericPoolFlashBorrower() external pure { + assertEq(GENERIC_POOL_FB_GENERATED_ADDRESS, LibRaindexDeploy.GENERIC_POOL_FLASH_BORROWER_DEPLOYED_ADDRESS); + } + + /// The generated codehash for GenericPoolRaindexV6ArbOrderTaker MUST + /// match the deploy library constant. + function testGeneratedCodehashGenericPoolArbOrderTaker() external pure { + assertEq( + GENERIC_POOL_ARB_OT_GENERATED_CODEHASH, LibRaindexDeploy.GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_CODEHASH + ); + } + + /// The generated codehash for RouteProcessorRaindexV6ArbOrderTaker MUST + /// match the deploy library constant. + function testGeneratedCodehashRouteProcessorArbOrderTaker() external pure { + assertEq(RP_ARB_OT_GENERATED_CODEHASH, LibRaindexDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_CODEHASH); + } + + /// The generated codehash for GenericPoolRaindexV6FlashBorrower MUST + /// match the deploy library constant. + function testGeneratedCodehashGenericPoolFlashBorrower() external pure { + assertEq(GENERIC_POOL_FB_GENERATED_CODEHASH, LibRaindexDeploy.GENERIC_POOL_FLASH_BORROWER_DEPLOYED_CODEHASH); + } + + /// After calling etchRaindex, all three contracts MUST have the expected + /// codehash at their expected addresses. + function testEtchRaindex() external { + LibEtchRaindex.etchRaindex(vm); + + assertEq(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS.codehash, LibRaindexDeploy.RAINDEX_DEPLOYED_CODEHASH); + assertEq( + LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS.codehash, LibRaindexDeploy.SUB_PARSER_DEPLOYED_CODEHASH + ); + assertEq( + LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS.codehash, + LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_CODEHASH + ); + } + + /// Calling etchRaindex twice MUST be idempotent — codehashes remain + /// correct on the second call. + function testEtchRaindexIdempotent() external { + LibEtchRaindex.etchRaindex(vm); + LibEtchRaindex.etchRaindex(vm); + + assertEq(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS.codehash, LibRaindexDeploy.RAINDEX_DEPLOYED_CODEHASH); + assertEq( + LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS.codehash, LibRaindexDeploy.SUB_PARSER_DEPLOYED_CODEHASH + ); + assertEq( + LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS.codehash, + LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_CODEHASH + ); + } +} diff --git a/test/lib/deploy/LibOrderBookDeployIsStartBlockArbitrum.t.sol b/test/lib/deploy/LibRaindexDeployIsStartBlockArbitrum.t.sol similarity index 69% rename from test/lib/deploy/LibOrderBookDeployIsStartBlockArbitrum.t.sol rename to test/lib/deploy/LibRaindexDeployIsStartBlockArbitrum.t.sol index 773354ab58..baec111528 100644 --- a/test/lib/deploy/LibOrderBookDeployIsStartBlockArbitrum.t.sol +++ b/test/lib/deploy/LibRaindexDeployIsStartBlockArbitrum.t.sol @@ -4,24 +4,24 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; -import {LibOrderBookDeploy} from "src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "src/lib/deploy/LibRaindexDeploy.sol"; -/// @title LibOrderBookDeployIsStartBlockArbitrumTest +/// @title LibRaindexDeployIsStartBlockArbitrumTest /// @notice Cheaply validates the known Arbitrum start block constant by checking /// that code appears at the block but not the block before. /// Skipped because free Arbitrum RPCs cannot serve full historical state needed /// by rollFork. The start block was verified via manual cast binary search /// against an archival RPC. -contract LibOrderBookDeployIsStartBlockArbitrumTest is Test { +contract LibRaindexDeployIsStartBlockArbitrumTest is Test { function testIsStartBlockArbitrum() external { vm.skip(true); vm.createSelectFork(LibRainDeploy.ARBITRUM_ONE); assertTrue( LibRainDeploy.isStartBlock( vm, - LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS, - LibOrderBookDeploy.ORDERBOOK_DEPLOYED_CODEHASH, - LibOrderBookDeploy.ORDERBOOK_START_BLOCK_ARBITRUM + LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, + LibRaindexDeploy.RAINDEX_DEPLOYED_CODEHASH, + LibRaindexDeploy.RAINDEX_START_BLOCK_ARBITRUM ), "not start block: Arbitrum" ); diff --git a/test/lib/deploy/LibOrderBookDeployIsStartBlockBase.t.sol b/test/lib/deploy/LibRaindexDeployIsStartBlockBase.t.sol similarity index 63% rename from test/lib/deploy/LibOrderBookDeployIsStartBlockBase.t.sol rename to test/lib/deploy/LibRaindexDeployIsStartBlockBase.t.sol index 7cf87931cc..41eeaa2914 100644 --- a/test/lib/deploy/LibOrderBookDeployIsStartBlockBase.t.sol +++ b/test/lib/deploy/LibRaindexDeployIsStartBlockBase.t.sol @@ -4,20 +4,20 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; -import {LibOrderBookDeploy} from "src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "src/lib/deploy/LibRaindexDeploy.sol"; -/// @title LibOrderBookDeployIsStartBlockBaseTest +/// @title LibRaindexDeployIsStartBlockBaseTest /// @notice Cheaply validates the known Base start block constant by checking /// that code appears at the block but not the block before. -contract LibOrderBookDeployIsStartBlockBaseTest is Test { +contract LibRaindexDeployIsStartBlockBaseTest is Test { function testIsStartBlockBase() external { vm.createSelectFork(LibRainDeploy.BASE); assertTrue( LibRainDeploy.isStartBlock( vm, - LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS, - LibOrderBookDeploy.ORDERBOOK_DEPLOYED_CODEHASH, - LibOrderBookDeploy.ORDERBOOK_START_BLOCK_BASE + LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, + LibRaindexDeploy.RAINDEX_DEPLOYED_CODEHASH, + LibRaindexDeploy.RAINDEX_START_BLOCK_BASE ), "not start block: Base" ); diff --git a/test/lib/deploy/LibOrderBookDeployIsStartBlockFlare.t.sol b/test/lib/deploy/LibRaindexDeployIsStartBlockFlare.t.sol similarity index 63% rename from test/lib/deploy/LibOrderBookDeployIsStartBlockFlare.t.sol rename to test/lib/deploy/LibRaindexDeployIsStartBlockFlare.t.sol index 3f414b40ac..1d9fc39844 100644 --- a/test/lib/deploy/LibOrderBookDeployIsStartBlockFlare.t.sol +++ b/test/lib/deploy/LibRaindexDeployIsStartBlockFlare.t.sol @@ -4,20 +4,20 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; -import {LibOrderBookDeploy} from "src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "src/lib/deploy/LibRaindexDeploy.sol"; -/// @title LibOrderBookDeployIsStartBlockFlareTest +/// @title LibRaindexDeployIsStartBlockFlareTest /// @notice Cheaply validates the known Flare start block constant by checking /// that code appears at the block but not the block before. -contract LibOrderBookDeployIsStartBlockFlareTest is Test { +contract LibRaindexDeployIsStartBlockFlareTest is Test { function testIsStartBlockFlare() external { vm.createSelectFork(LibRainDeploy.FLARE); assertTrue( LibRainDeploy.isStartBlock( vm, - LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS, - LibOrderBookDeploy.ORDERBOOK_DEPLOYED_CODEHASH, - LibOrderBookDeploy.ORDERBOOK_START_BLOCK_FLARE + LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, + LibRaindexDeploy.RAINDEX_DEPLOYED_CODEHASH, + LibRaindexDeploy.RAINDEX_START_BLOCK_FLARE ), "not start block: Flare" ); diff --git a/test/lib/deploy/LibOrderBookDeployIsStartBlockPolygon.t.sol b/test/lib/deploy/LibRaindexDeployIsStartBlockPolygon.t.sol similarity index 63% rename from test/lib/deploy/LibOrderBookDeployIsStartBlockPolygon.t.sol rename to test/lib/deploy/LibRaindexDeployIsStartBlockPolygon.t.sol index fdaa9a2d49..62dc2b5437 100644 --- a/test/lib/deploy/LibOrderBookDeployIsStartBlockPolygon.t.sol +++ b/test/lib/deploy/LibRaindexDeployIsStartBlockPolygon.t.sol @@ -4,20 +4,20 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; -import {LibOrderBookDeploy} from "src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "src/lib/deploy/LibRaindexDeploy.sol"; -/// @title LibOrderBookDeployIsStartBlockPolygonTest +/// @title LibRaindexDeployIsStartBlockPolygonTest /// @notice Cheaply validates the known Polygon start block constant by checking /// that code appears at the block but not the block before. -contract LibOrderBookDeployIsStartBlockPolygonTest is Test { +contract LibRaindexDeployIsStartBlockPolygonTest is Test { function testIsStartBlockPolygon() external { vm.createSelectFork(LibRainDeploy.POLYGON); assertTrue( LibRainDeploy.isStartBlock( vm, - LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS, - LibOrderBookDeploy.ORDERBOOK_DEPLOYED_CODEHASH, - LibOrderBookDeploy.ORDERBOOK_START_BLOCK_POLYGON + LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, + LibRaindexDeploy.RAINDEX_DEPLOYED_CODEHASH, + LibRaindexDeploy.RAINDEX_START_BLOCK_POLYGON ), "not start block: Polygon" ); diff --git a/test/lib/deploy/LibOrderBookDeployNetworksJsonAddresses.t.sol b/test/lib/deploy/LibRaindexDeployNetworksJsonAddresses.t.sol similarity index 72% rename from test/lib/deploy/LibOrderBookDeployNetworksJsonAddresses.t.sol rename to test/lib/deploy/LibRaindexDeployNetworksJsonAddresses.t.sol index 72deeba469..7dd10900fd 100644 --- a/test/lib/deploy/LibOrderBookDeployNetworksJsonAddresses.t.sol +++ b/test/lib/deploy/LibRaindexDeployNetworksJsonAddresses.t.sol @@ -3,12 +3,12 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; -import {LibOrderBookDeploy} from "src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "src/lib/deploy/LibRaindexDeploy.sol"; -/// @title LibOrderBookDeployNetworksJsonAddressesTest +/// @title LibRaindexDeployNetworksJsonAddressesTest /// @notice Every address in subgraph/networks.json MUST match the deterministic -/// OrderBook deploy address from LibOrderBookDeploy. -contract LibOrderBookDeployNetworksJsonAddressesTest is Test { +/// Raindex deploy address from LibRaindexDeploy. +contract LibRaindexDeployNetworksJsonAddressesTest is Test { function testNetworksJsonAddresses() external view { string memory json = vm.readFile("subgraph/networks.json"); string[] memory networks = vm.parseJsonKeys(json, "$"); @@ -17,7 +17,7 @@ contract LibOrderBookDeployNetworksJsonAddressesTest is Test { address addr = vm.parseJsonAddress(json, path); assertEq( addr, - LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS, + LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, string.concat("networks.json address mismatch: ", networks[i]) ); } diff --git a/test/lib/deploy/LibOrderBookDeployNetworksJsonStartBlockArbitrum.t.sol b/test/lib/deploy/LibRaindexDeployNetworksJsonStartBlockArbitrum.t.sol similarity index 66% rename from test/lib/deploy/LibOrderBookDeployNetworksJsonStartBlockArbitrum.t.sol rename to test/lib/deploy/LibRaindexDeployNetworksJsonStartBlockArbitrum.t.sol index 328f91fb04..c004355104 100644 --- a/test/lib/deploy/LibOrderBookDeployNetworksJsonStartBlockArbitrum.t.sol +++ b/test/lib/deploy/LibRaindexDeployNetworksJsonStartBlockArbitrum.t.sol @@ -3,18 +3,18 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; -import {LibOrderBookDeploy} from "src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "src/lib/deploy/LibRaindexDeploy.sol"; -/// @title LibOrderBookDeployNetworksJsonStartBlockArbitrumTest +/// @title LibRaindexDeployNetworksJsonStartBlockArbitrumTest /// @notice The startBlock for arbitrum-one in subgraph/networks.json MUST match -/// the constant in LibOrderBookDeploy. -contract LibOrderBookDeployNetworksJsonStartBlockArbitrumTest is Test { +/// the constant in LibRaindexDeploy. +contract LibRaindexDeployNetworksJsonStartBlockArbitrumTest is Test { function testNetworksJsonStartBlockArbitrum() external view { string memory json = vm.readFile("subgraph/networks.json"); uint256 startBlock = vm.parseJsonUint(json, ".arbitrum-one.OrderBook.startBlock"); assertEq( startBlock, - LibOrderBookDeploy.ORDERBOOK_START_BLOCK_ARBITRUM, + LibRaindexDeploy.RAINDEX_START_BLOCK_ARBITRUM, "networks.json startBlock mismatch: arbitrum-one" ); } diff --git a/test/lib/deploy/LibOrderBookDeployNetworksJsonStartBlockBase.t.sol b/test/lib/deploy/LibRaindexDeployNetworksJsonStartBlockBase.t.sol similarity index 57% rename from test/lib/deploy/LibOrderBookDeployNetworksJsonStartBlockBase.t.sol rename to test/lib/deploy/LibRaindexDeployNetworksJsonStartBlockBase.t.sol index d128e7a087..4fe03a41c9 100644 --- a/test/lib/deploy/LibOrderBookDeployNetworksJsonStartBlockBase.t.sol +++ b/test/lib/deploy/LibRaindexDeployNetworksJsonStartBlockBase.t.sol @@ -3,15 +3,15 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; -import {LibOrderBookDeploy} from "src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "src/lib/deploy/LibRaindexDeploy.sol"; -/// @title LibOrderBookDeployNetworksJsonStartBlockBaseTest +/// @title LibRaindexDeployNetworksJsonStartBlockBaseTest /// @notice The startBlock for base in subgraph/networks.json MUST match -/// the constant in LibOrderBookDeploy. -contract LibOrderBookDeployNetworksJsonStartBlockBaseTest is Test { +/// the constant in LibRaindexDeploy. +contract LibRaindexDeployNetworksJsonStartBlockBaseTest is Test { function testNetworksJsonStartBlockBase() external view { string memory json = vm.readFile("subgraph/networks.json"); uint256 startBlock = vm.parseJsonUint(json, ".base.OrderBook.startBlock"); - assertEq(startBlock, LibOrderBookDeploy.ORDERBOOK_START_BLOCK_BASE, "networks.json startBlock mismatch: base"); + assertEq(startBlock, LibRaindexDeploy.RAINDEX_START_BLOCK_BASE, "networks.json startBlock mismatch: base"); } } diff --git a/test/lib/deploy/LibOrderBookDeployNetworksJsonStartBlockFlare.t.sol b/test/lib/deploy/LibRaindexDeployNetworksJsonStartBlockFlare.t.sol similarity index 57% rename from test/lib/deploy/LibOrderBookDeployNetworksJsonStartBlockFlare.t.sol rename to test/lib/deploy/LibRaindexDeployNetworksJsonStartBlockFlare.t.sol index 2c827ec887..3affbd171b 100644 --- a/test/lib/deploy/LibOrderBookDeployNetworksJsonStartBlockFlare.t.sol +++ b/test/lib/deploy/LibRaindexDeployNetworksJsonStartBlockFlare.t.sol @@ -3,15 +3,15 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; -import {LibOrderBookDeploy} from "src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "src/lib/deploy/LibRaindexDeploy.sol"; -/// @title LibOrderBookDeployNetworksJsonStartBlockFlareTest +/// @title LibRaindexDeployNetworksJsonStartBlockFlareTest /// @notice The startBlock for flare in subgraph/networks.json MUST match -/// the constant in LibOrderBookDeploy. -contract LibOrderBookDeployNetworksJsonStartBlockFlareTest is Test { +/// the constant in LibRaindexDeploy. +contract LibRaindexDeployNetworksJsonStartBlockFlareTest is Test { function testNetworksJsonStartBlockFlare() external view { string memory json = vm.readFile("subgraph/networks.json"); uint256 startBlock = vm.parseJsonUint(json, ".flare.OrderBook.startBlock"); - assertEq(startBlock, LibOrderBookDeploy.ORDERBOOK_START_BLOCK_FLARE, "networks.json startBlock mismatch: flare"); + assertEq(startBlock, LibRaindexDeploy.RAINDEX_START_BLOCK_FLARE, "networks.json startBlock mismatch: flare"); } } diff --git a/test/lib/deploy/LibOrderBookDeployNetworksJsonStartBlockPolygon.t.sol b/test/lib/deploy/LibRaindexDeployNetworksJsonStartBlockPolygon.t.sol similarity index 58% rename from test/lib/deploy/LibOrderBookDeployNetworksJsonStartBlockPolygon.t.sol rename to test/lib/deploy/LibRaindexDeployNetworksJsonStartBlockPolygon.t.sol index 28442d2ca5..2197a2ba9c 100644 --- a/test/lib/deploy/LibOrderBookDeployNetworksJsonStartBlockPolygon.t.sol +++ b/test/lib/deploy/LibRaindexDeployNetworksJsonStartBlockPolygon.t.sol @@ -3,17 +3,17 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; -import {LibOrderBookDeploy} from "src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "src/lib/deploy/LibRaindexDeploy.sol"; -/// @title LibOrderBookDeployNetworksJsonStartBlockPolygonTest +/// @title LibRaindexDeployNetworksJsonStartBlockPolygonTest /// @notice The startBlock for matic in subgraph/networks.json MUST match -/// the constant in LibOrderBookDeploy. -contract LibOrderBookDeployNetworksJsonStartBlockPolygonTest is Test { +/// the constant in LibRaindexDeploy. +contract LibRaindexDeployNetworksJsonStartBlockPolygonTest is Test { function testNetworksJsonStartBlockPolygon() external view { string memory json = vm.readFile("subgraph/networks.json"); uint256 startBlock = vm.parseJsonUint(json, ".matic.OrderBook.startBlock"); assertEq( - startBlock, LibOrderBookDeploy.ORDERBOOK_START_BLOCK_POLYGON, "networks.json startBlock mismatch: matic" + startBlock, LibRaindexDeploy.RAINDEX_START_BLOCK_POLYGON, "networks.json startBlock mismatch: matic" ); } } diff --git a/test/lib/deploy/LibOrderBookDeployProd.t.sol b/test/lib/deploy/LibRaindexDeployProd.t.sol similarity index 50% rename from test/lib/deploy/LibOrderBookDeployProd.t.sol rename to test/lib/deploy/LibRaindexDeployProd.t.sol index 82f0fd8880..5d36ed37b2 100644 --- a/test/lib/deploy/LibOrderBookDeployProd.t.sol +++ b/test/lib/deploy/LibRaindexDeployProd.t.sol @@ -4,52 +4,52 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; -import {LibOrderBookDeploy} from "../../../src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "../../../src/lib/deploy/LibRaindexDeploy.sol"; -/// @title LibOrderBookDeployProdTest -/// @notice Forks each supported network and verifies that all orderbook +/// @title LibRaindexDeployProdTest +/// @notice Forks each supported network and verifies that all raindex /// contracts are deployed at the expected addresses with the expected codehash. -contract LibOrderBookDeployProdTest is Test { +contract LibRaindexDeployProdTest is Test { function _checkAllContracts() internal view { - assertTrue(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS.code.length > 0, "OrderBookV6 not deployed"); - assertEq(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS.codehash, LibOrderBookDeploy.ORDERBOOK_DEPLOYED_CODEHASH); + assertTrue(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS.code.length > 0, "RaindexV6 not deployed"); + assertEq(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS.codehash, LibRaindexDeploy.RAINDEX_DEPLOYED_CODEHASH); - assertTrue(LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS.code.length > 0, "SubParser not deployed"); + assertTrue(LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS.code.length > 0, "SubParser not deployed"); assertEq( - LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS.codehash, LibOrderBookDeploy.SUB_PARSER_DEPLOYED_CODEHASH + LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS.codehash, LibRaindexDeploy.SUB_PARSER_DEPLOYED_CODEHASH ); - assertTrue(LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS.code.length > 0, "RouteProcessor4 not deployed"); + assertTrue(LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS.code.length > 0, "RouteProcessor4 not deployed"); assertEq( - LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS.codehash, - LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_CODEHASH + LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS.codehash, + LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_CODEHASH ); assertTrue( - LibOrderBookDeploy.GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_ADDRESS.code.length > 0, + LibRaindexDeploy.GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_ADDRESS.code.length > 0, "GenericPoolArbOrderTaker not deployed" ); assertEq( - LibOrderBookDeploy.GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_ADDRESS.codehash, - LibOrderBookDeploy.GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_CODEHASH + LibRaindexDeploy.GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_ADDRESS.codehash, + LibRaindexDeploy.GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_CODEHASH ); assertTrue( - LibOrderBookDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_ADDRESS.code.length > 0, + LibRaindexDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_ADDRESS.code.length > 0, "RouteProcessorArbOrderTaker not deployed" ); assertEq( - LibOrderBookDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_ADDRESS.codehash, - LibOrderBookDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_CODEHASH + LibRaindexDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_ADDRESS.codehash, + LibRaindexDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_CODEHASH ); assertTrue( - LibOrderBookDeploy.GENERIC_POOL_FLASH_BORROWER_DEPLOYED_ADDRESS.code.length > 0, + LibRaindexDeploy.GENERIC_POOL_FLASH_BORROWER_DEPLOYED_ADDRESS.code.length > 0, "GenericPoolFlashBorrower not deployed" ); assertEq( - LibOrderBookDeploy.GENERIC_POOL_FLASH_BORROWER_DEPLOYED_ADDRESS.codehash, - LibOrderBookDeploy.GENERIC_POOL_FLASH_BORROWER_DEPLOYED_CODEHASH + LibRaindexDeploy.GENERIC_POOL_FLASH_BORROWER_DEPLOYED_ADDRESS.codehash, + LibRaindexDeploy.GENERIC_POOL_FLASH_BORROWER_DEPLOYED_CODEHASH ); } diff --git a/test/lib/deploy/LibOrderBookDeployStartBlockArbitrum.t.sol b/test/lib/deploy/LibRaindexDeployStartBlockArbitrum.t.sol similarity index 64% rename from test/lib/deploy/LibOrderBookDeployStartBlockArbitrum.t.sol rename to test/lib/deploy/LibRaindexDeployStartBlockArbitrum.t.sol index c273a1c5d5..fa26dc23fe 100644 --- a/test/lib/deploy/LibOrderBookDeployStartBlockArbitrum.t.sol +++ b/test/lib/deploy/LibRaindexDeployStartBlockArbitrum.t.sol @@ -4,14 +4,14 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; -import {LibOrderBookDeploy} from "src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "src/lib/deploy/LibRaindexDeploy.sol"; -/// @title LibOrderBookDeployStartBlockArbitrumTest -/// @notice Binary-searches for the OrderBook deploy block on Arbitrum. +/// @title LibRaindexDeployStartBlockArbitrumTest +/// @notice Binary-searches for the Raindex deploy block on Arbitrum. /// Always skipped because Foundry's rollFork maps to L1 block numbers, not L2. /// The Arbitrum start block was found via manual binary search using /// eth_getCode RPC calls against L2 block numbers. -contract LibOrderBookDeployStartBlockArbitrumTest is Test { +contract LibRaindexDeployStartBlockArbitrumTest is Test { /// Arbitrum Nitro genesis block. Archive RPCs can't serve blocks before this. uint256 constant ARBITRUM_NITRO_GENESIS_BLOCK = 22207817; @@ -19,10 +19,10 @@ contract LibOrderBookDeployStartBlockArbitrumTest is Test { // vm.createSelectFork(LibRainDeploy.ARBITRUM_ONE); // uint256 startBlock = LibRainDeploy.findDeployBlock( // vm, - // LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS, - // LibOrderBookDeploy.ORDERBOOK_DEPLOYED_CODEHASH, + // LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, + // LibRaindexDeploy.RAINDEX_DEPLOYED_CODEHASH, // ARBITRUM_NITRO_GENESIS_BLOCK // ); - // assertEq(startBlock, LibOrderBookDeploy.ORDERBOOK_START_BLOCK_ARBITRUM); + // assertEq(startBlock, LibRaindexDeploy.RAINDEX_START_BLOCK_ARBITRUM); // } } diff --git a/test/lib/deploy/LibOrderBookDeployStartBlockBase.t.sol b/test/lib/deploy/LibRaindexDeployStartBlockBase.t.sol similarity index 56% rename from test/lib/deploy/LibOrderBookDeployStartBlockBase.t.sol rename to test/lib/deploy/LibRaindexDeployStartBlockBase.t.sol index 1dfd5c756b..f56ad4e7e1 100644 --- a/test/lib/deploy/LibOrderBookDeployStartBlockBase.t.sol +++ b/test/lib/deploy/LibRaindexDeployStartBlockBase.t.sol @@ -4,19 +4,19 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; -import {LibOrderBookDeploy} from "src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "src/lib/deploy/LibRaindexDeploy.sol"; -/// @title LibOrderBookDeployStartBlockBaseTest -/// @notice Binary-searches for the OrderBook deploy block on Base. +/// @title LibRaindexDeployStartBlockBaseTest +/// @notice Binary-searches for the Raindex deploy block on Base. /// Skipped in CI due to RPC rate limits; the isStartBlock test verifies /// correctness cheaply. -contract LibOrderBookDeployStartBlockBaseTest is Test { +contract LibRaindexDeployStartBlockBaseTest is Test { function testStartBlockBase() external { vm.skip(vm.envOr("CI", false)); vm.createSelectFork(LibRainDeploy.BASE); uint256 startBlock = LibRainDeploy.findDeployBlock( - vm, LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS, LibOrderBookDeploy.ORDERBOOK_DEPLOYED_CODEHASH, 0 + vm, LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, LibRaindexDeploy.RAINDEX_DEPLOYED_CODEHASH, 0 ); - assertEq(startBlock, LibOrderBookDeploy.ORDERBOOK_START_BLOCK_BASE); + assertEq(startBlock, LibRaindexDeploy.RAINDEX_START_BLOCK_BASE); } } diff --git a/test/lib/deploy/LibOrderBookDeployStartBlockFlare.t.sol b/test/lib/deploy/LibRaindexDeployStartBlockFlare.t.sol similarity index 56% rename from test/lib/deploy/LibOrderBookDeployStartBlockFlare.t.sol rename to test/lib/deploy/LibRaindexDeployStartBlockFlare.t.sol index f3b0cc4791..55673d3f7b 100644 --- a/test/lib/deploy/LibOrderBookDeployStartBlockFlare.t.sol +++ b/test/lib/deploy/LibRaindexDeployStartBlockFlare.t.sol @@ -4,19 +4,19 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; -import {LibOrderBookDeploy} from "src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "src/lib/deploy/LibRaindexDeploy.sol"; -/// @title LibOrderBookDeployStartBlockFlareTest -/// @notice Binary-searches for the OrderBook deploy block on Flare. +/// @title LibRaindexDeployStartBlockFlareTest +/// @notice Binary-searches for the Raindex deploy block on Flare. /// Skipped in CI due to RPC rate limits; the isStartBlock test verifies /// correctness cheaply. -contract LibOrderBookDeployStartBlockFlareTest is Test { +contract LibRaindexDeployStartBlockFlareTest is Test { function testStartBlockFlare() external { vm.skip(vm.envOr("CI", false)); vm.createSelectFork(LibRainDeploy.FLARE); uint256 startBlock = LibRainDeploy.findDeployBlock( - vm, LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS, LibOrderBookDeploy.ORDERBOOK_DEPLOYED_CODEHASH, 0 + vm, LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, LibRaindexDeploy.RAINDEX_DEPLOYED_CODEHASH, 0 ); - assertEq(startBlock, LibOrderBookDeploy.ORDERBOOK_START_BLOCK_FLARE); + assertEq(startBlock, LibRaindexDeploy.RAINDEX_START_BLOCK_FLARE); } } diff --git a/test/lib/deploy/LibOrderBookDeployStartBlockPolygon.t.sol b/test/lib/deploy/LibRaindexDeployStartBlockPolygon.t.sol similarity index 56% rename from test/lib/deploy/LibOrderBookDeployStartBlockPolygon.t.sol rename to test/lib/deploy/LibRaindexDeployStartBlockPolygon.t.sol index 3fd00c01f3..1ddbb0e80b 100644 --- a/test/lib/deploy/LibOrderBookDeployStartBlockPolygon.t.sol +++ b/test/lib/deploy/LibRaindexDeployStartBlockPolygon.t.sol @@ -4,19 +4,19 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; -import {LibOrderBookDeploy} from "src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "src/lib/deploy/LibRaindexDeploy.sol"; -/// @title LibOrderBookDeployStartBlockPolygonTest -/// @notice Binary-searches for the OrderBook deploy block on Polygon. +/// @title LibRaindexDeployStartBlockPolygonTest +/// @notice Binary-searches for the Raindex deploy block on Polygon. /// Skipped in CI due to RPC rate limits; the isStartBlock test verifies /// correctness cheaply. -contract LibOrderBookDeployStartBlockPolygonTest is Test { +contract LibRaindexDeployStartBlockPolygonTest is Test { function testStartBlockPolygon() external { vm.skip(vm.envOr("CI", false)); vm.createSelectFork(LibRainDeploy.POLYGON); uint256 startBlock = LibRainDeploy.findDeployBlock( - vm, LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS, LibOrderBookDeploy.ORDERBOOK_DEPLOYED_CODEHASH, 0 + vm, LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, LibRaindexDeploy.RAINDEX_DEPLOYED_CODEHASH, 0 ); - assertEq(startBlock, LibOrderBookDeploy.ORDERBOOK_START_BLOCK_POLYGON); + assertEq(startBlock, LibRaindexDeploy.RAINDEX_START_BLOCK_POLYGON); } } diff --git a/test/lib/deploy/LibOrderBookDeploySubgraphYamlAddress.t.sol b/test/lib/deploy/LibRaindexDeploySubgraphYamlAddress.t.sol similarity index 62% rename from test/lib/deploy/LibOrderBookDeploySubgraphYamlAddress.t.sol rename to test/lib/deploy/LibRaindexDeploySubgraphYamlAddress.t.sol index 77c463c8ce..123640064e 100644 --- a/test/lib/deploy/LibOrderBookDeploySubgraphYamlAddress.t.sol +++ b/test/lib/deploy/LibRaindexDeploySubgraphYamlAddress.t.sol @@ -3,12 +3,12 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; -import {LibOrderBookDeploy} from "src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "src/lib/deploy/LibRaindexDeploy.sol"; -/// @title LibOrderBookDeploySubgraphYamlAddressTest +/// @title LibRaindexDeploySubgraphYamlAddressTest /// @notice The placeholder address in subgraph/subgraph.yaml MUST match the -/// deterministic OrderBook deploy address from LibOrderBookDeploy. -contract LibOrderBookDeploySubgraphYamlAddressTest is Test { +/// deterministic Raindex deploy address from LibRaindexDeploy. +contract LibRaindexDeploySubgraphYamlAddressTest is Test { function testSubgraphYamlAddress() external { string[] memory inputs = new string[](3); inputs[0] = "yq"; @@ -16,6 +16,6 @@ contract LibOrderBookDeploySubgraphYamlAddressTest is Test { inputs[2] = "subgraph/subgraph.yaml"; bytes memory result = vm.ffi(inputs); address addr = address(bytes20(result)); - assertEq(addr, LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS, "subgraph.yaml address mismatch"); + assertEq(addr, LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, "subgraph.yaml address mismatch"); } } diff --git a/test/util/abstract/ArbTest.sol b/test/util/abstract/ArbTest.sol index 31e81e200b..75b59a911e 100644 --- a/test/util/abstract/ArbTest.sol +++ b/test/util/abstract/ArbTest.sol @@ -7,16 +7,16 @@ import {Test} from "forge-std/Test.sol"; import {ERC20} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; import {Refundoor} from "test/util/concrete/Refundoor.sol"; import { - FlashLendingMockOrderBook, + FlashLendingMockRaindex, OrderV4, TakeOrderConfigV4, IOV2, SignedContextV1, EvaluableV4 -} from "test/util/concrete/FlashLendingMockOrderBook.sol"; +} from "test/util/concrete/FlashLendingMockRaindex.sol"; import {LibTOFUTokenDecimals} from "rain.tofu.erc20-decimals/lib/LibTOFUTokenDecimals.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; -import {LibOrderBookDeploy} from "../../../src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "../../../src/lib/deploy/LibRaindexDeploy.sol"; contract Token is ERC20 { constructor() ERC20("Token", "TKN") {} @@ -30,7 +30,7 @@ abstract contract ArbTest is Test { Token immutable iTakerInput; Token immutable iTakerOutput; address immutable iRefundoor; - FlashLendingMockOrderBook immutable iOrderBook; + FlashLendingMockRaindex immutable iRaindex; address payable immutable iArb; function buildArb() internal virtual returns (address payable); @@ -45,12 +45,12 @@ abstract contract ArbTest is Test { vm.label(address(iTakerOutput), "iTakerOutput"); iRefundoor = address(new Refundoor()); vm.label(iRefundoor, "iRefundoor"); - // Deploy the mock then etch its code at the deterministic orderbook + // Deploy the mock then etch its code at the deterministic raindex // address so that onFlashLoan's BadLender check passes. - FlashLendingMockOrderBook mockOb = new FlashLendingMockOrderBook(); - vm.etch(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS, address(mockOb).code); - iOrderBook = FlashLendingMockOrderBook(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS); - vm.label(address(iOrderBook), "iOrderBook"); + FlashLendingMockRaindex mockOb = new FlashLendingMockRaindex(); + vm.etch(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, address(mockOb).code); + iRaindex = FlashLendingMockRaindex(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS); + vm.label(address(iRaindex), "iRaindex"); iArb = buildArb(); vm.label(iArb, "iArb"); diff --git a/test/util/abstract/GenericPoolOrderBookV6ArbOrderTakerTest.sol b/test/util/abstract/GenericPoolRaindexV6ArbOrderTakerTest.sol similarity index 53% rename from test/util/abstract/GenericPoolOrderBookV6ArbOrderTakerTest.sol rename to test/util/abstract/GenericPoolRaindexV6ArbOrderTakerTest.sol index faaa8f58e6..c2d9680b54 100644 --- a/test/util/abstract/GenericPoolOrderBookV6ArbOrderTakerTest.sol +++ b/test/util/abstract/GenericPoolRaindexV6ArbOrderTakerTest.sol @@ -3,11 +3,11 @@ pragma solidity =0.8.25; import {ArbTest} from "./ArbTest.sol"; -import {GenericPoolOrderBookV6ArbOrderTaker} from "../../../src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol"; +import {GenericPoolRaindexV6ArbOrderTaker} from "../../../src/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.sol"; -contract GenericPoolOrderBookV6ArbOrderTakerTest is ArbTest { +contract GenericPoolRaindexV6ArbOrderTakerTest is ArbTest { function buildArb() internal override returns (address payable) { - return payable(address(new GenericPoolOrderBookV6ArbOrderTaker())); + return payable(address(new GenericPoolRaindexV6ArbOrderTaker())); } constructor() ArbTest() {} diff --git a/test/util/abstract/MockOrderBookBase.sol b/test/util/abstract/MockRaindexBase.sol similarity index 94% rename from test/util/abstract/MockOrderBookBase.sol rename to test/util/abstract/MockRaindexBase.sol index 1573ca8b2d..d8e0a76328 100644 --- a/test/util/abstract/MockOrderBookBase.sol +++ b/test/util/abstract/MockRaindexBase.sol @@ -17,9 +17,9 @@ import { } from "rain.raindex.interface/interface/IRaindexV6.sol"; import {IERC3156FlashBorrower} from "rain.raindex.interface/interface/ierc3156/IERC3156FlashBorrower.sol"; -/// @dev Base for mock orderbooks that stub all IRaindexV6 functions. +/// @dev Base for mock raindex contracts that stub all IRaindexV6 functions. /// Inheritors override flashLoan and/or takeOrders4 with real token transfers. -abstract contract MockOrderBookBase is IRaindexV6 { +abstract contract MockRaindexBase is IRaindexV6 { using SafeERC20 for IERC20; function flashLoan(IERC3156FlashBorrower, address, uint256, bytes calldata) external virtual returns (bool) { diff --git a/test/util/abstract/OrderBookV6ExternalMockTest.sol b/test/util/abstract/RaindexV6ExternalMockTest.sol similarity index 82% rename from test/util/abstract/OrderBookV6ExternalMockTest.sol rename to test/util/abstract/RaindexV6ExternalMockTest.sol index da186f0f26..e7b4a54379 100644 --- a/test/util/abstract/OrderBookV6ExternalMockTest.sol +++ b/test/util/abstract/RaindexV6ExternalMockTest.sol @@ -14,28 +14,28 @@ import {IInterpreterStoreV3} from "rain.interpreter.interface/interface/IInterpr import {IRaindexV6, OrderConfigV4, OrderV4, TaskV2} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {LibOrder} from "../../../src/lib/LibOrder.sol"; -import {LibOrderBookDeploy} from "../../../src/lib/deploy/LibOrderBookDeploy.sol"; -import {LibEtchOrderBook} from "test/util/lib/LibEtchOrderBook.sol"; +import {LibRaindexDeploy} from "../../../src/lib/deploy/LibRaindexDeploy.sol"; +import {LibEtchRaindex} from "test/util/lib/LibEtchRaindex.sol"; import {EvaluableV4} from "rain.interpreter.interface/interface/IInterpreterCallerV4.sol"; import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {LibTOFUTokenDecimals} from "rain.tofu.erc20-decimals/lib/LibTOFUTokenDecimals.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; -/// @title OrderBookV6ExternalTest -/// Abstract contract that performs common setup needed for testing an orderbook +/// @title RaindexV6ExternalTest +/// Abstract contract that performs common setup needed for testing a raindex /// from its external interface. /// /// Notably: -/// - Deploys a real orderbook contract with correct meta. +/// - Deploys a real raindex contract with correct meta. /// - Deploys several mockable token contracts. /// - Deploys a mockable deployer contract for a DISpair. /// /// Inherits from Test so that it can be used as a base contract for other tests. /// Implements IRaindexV6 so that it has access to all the relevant events. -abstract contract OrderBookV6ExternalMockTest is Test, IMetaV1_2, IRaindexV6Stub { +abstract contract RaindexV6ExternalMockTest is Test, IMetaV1_2, IRaindexV6Stub { IInterpreterV4 immutable iInterpreter; IInterpreterStoreV3 immutable iStore; - IRaindexV6 immutable iOrderbook; + IRaindexV6 immutable iRaindex; IERC20 immutable iToken0; IERC20 immutable iToken1; @@ -49,8 +49,8 @@ abstract contract OrderBookV6ExternalMockTest is Test, IMetaV1_2, IRaindexV6Stub vm.etch(address(iInterpreter), REVERTING_MOCK_BYTECODE); iStore = IInterpreterStoreV3(address(uint160(uint256(keccak256("store.rain.test"))))); vm.etch(address(iStore), REVERTING_MOCK_BYTECODE); - LibEtchOrderBook.etchOrderBook(vm); - iOrderbook = IRaindexV6(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS); + LibEtchRaindex.etchRaindex(vm); + iRaindex = IRaindexV6(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS); iToken0 = IERC20(address(uint160(uint256(keccak256("token0.rain.test"))))); vm.etch(address(iToken0), REVERTING_MOCK_BYTECODE); @@ -68,7 +68,7 @@ abstract contract OrderBookV6ExternalMockTest is Test, IMetaV1_2, IRaindexV6Stub returns (OrderV4 memory, bytes32) { (OrderV4 memory order, bytes32 orderHash) = LibTestAddOrder.expectedOrder(owner, config); - assertTrue(!iOrderbook.orderExists(orderHash)); + assertTrue(!iRaindex.orderExists(orderHash)); vm.expectEmit(false, false, false, true); emit AddOrderV3(owner, orderHash, order); if (config.meta.length > 0) { @@ -79,15 +79,15 @@ abstract contract OrderBookV6ExternalMockTest is Test, IMetaV1_2, IRaindexV6Stub vm.record(); vm.recordLogs(); vm.prank(owner); - assertTrue(iOrderbook.addOrder4(config, new TaskV2[](0))); + assertTrue(iRaindex.addOrder4(config, new TaskV2[](0))); // MetaV1 is NOT emitted if the meta is empty. assertEq(vm.getRecordedLogs().length, config.meta.length > 0 ? 2 : 1); - (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iOrderbook)); + (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iRaindex)); // 3x for reentrancy guard, 1x for dead order check, 1x for live write. assertEq(reads.length, 5); // 2x for reentrancy guard, 1x for live write. assertEq(writes.length, 3); - assertTrue(iOrderbook.orderExists(orderHash)); + assertTrue(iRaindex.orderExists(orderHash)); // Adding the same order again MUST NOT change state. This MAY be // impossible to encounter for a real expression deployer, as the @@ -96,14 +96,14 @@ abstract contract OrderBookV6ExternalMockTest is Test, IMetaV1_2, IRaindexV6Stub vm.record(); vm.recordLogs(); vm.prank(owner); - assertFalse(iOrderbook.addOrder4(config, new TaskV2[](0))); + assertFalse(iRaindex.addOrder4(config, new TaskV2[](0))); assertEq(vm.getRecordedLogs().length, 0); - (reads, writes) = vm.accesses(address(iOrderbook)); + (reads, writes) = vm.accesses(address(iRaindex)); // 3x for reentrancy guard, 1x for dead order check. assertEq(reads.length, 4); // 2x for reentrancy guard. assertEq(writes.length, 2); - assertTrue(iOrderbook.orderExists(orderHash)); + assertTrue(iRaindex.orderExists(orderHash)); return (order, orderHash); } @@ -113,34 +113,34 @@ abstract contract OrderBookV6ExternalMockTest is Test, IMetaV1_2, IRaindexV6Stub function removeOrderWithChecks(address owner, OrderV4 memory order) internal { bytes32 orderHash = LibOrder.hash(order); // This check assumes the order exists before we try to remove it. - assertTrue(iOrderbook.orderExists(orderHash)); + assertTrue(iRaindex.orderExists(orderHash)); vm.expectEmit(false, false, false, true); emit RemoveOrderV3(owner, orderHash, order); vm.record(); vm.recordLogs(); vm.prank(owner); // An order was removed so this is true as there is a state change. - assertTrue(iOrderbook.removeOrder3(order, new TaskV2[](0))); + assertTrue(iRaindex.removeOrder3(order, new TaskV2[](0))); assertEq(vm.getRecordedLogs().length, 1); - (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iOrderbook)); + (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses(address(iRaindex)); // 3x for reentrancy guard, 1x for dead order check, 1x for dead write. assertEq(reads.length, 5); // 2x for reentrancy guard, 1x for dead write. assertEq(writes.length, 3); - assertFalse(iOrderbook.orderExists(orderHash)); + assertFalse(iRaindex.orderExists(orderHash)); // Removing the same order again MUST NOT change state. vm.record(); vm.recordLogs(); vm.prank(owner); // There is no state change so this is false. - assertFalse(iOrderbook.removeOrder3(order, new TaskV2[](0))); + assertFalse(iRaindex.removeOrder3(order, new TaskV2[](0))); assertEq(vm.getRecordedLogs().length, 0); - (reads, writes) = vm.accesses(address(iOrderbook)); + (reads, writes) = vm.accesses(address(iRaindex)); // 3x for reentrancy guard, 1x for dead order check. assertEq(reads.length, 4); // 2x for reentrancy guard. assertEq(writes.length, 2); - assertFalse(iOrderbook.orderExists(orderHash)); + assertFalse(iRaindex.orderExists(orderHash)); } } diff --git a/test/util/abstract/OrderBookV6ExternalRealTest.sol b/test/util/abstract/RaindexV6ExternalRealTest.sol similarity index 83% rename from test/util/abstract/OrderBookV6ExternalRealTest.sol rename to test/util/abstract/RaindexV6ExternalRealTest.sol index df57e31d17..6cb81b5d27 100644 --- a/test/util/abstract/OrderBookV6ExternalRealTest.sol +++ b/test/util/abstract/RaindexV6ExternalRealTest.sol @@ -15,36 +15,36 @@ import { SignedContextV1 } from "rain.raindex.interface/interface/IRaindexV6.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import {OrderBookV6SubParser} from "../../../src/concrete/parser/OrderBookV6SubParser.sol"; +import {RaindexV6SubParser} from "../../../src/concrete/parser/RaindexV6SubParser.sol"; import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {LibDecimalFloat, Float} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibTOFUTokenDecimals} from "rain.tofu.erc20-decimals/lib/LibTOFUTokenDecimals.sol"; import {LibInterpreterDeploy} from "rain.interpreter/lib/deploy/LibInterpreterDeploy.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; -import {LibOrderBookDeploy} from "../../../src/lib/deploy/LibOrderBookDeploy.sol"; -import {LibEtchOrderBook} from "test/util/lib/LibEtchOrderBook.sol"; +import {LibRaindexDeploy} from "../../../src/lib/deploy/LibRaindexDeploy.sol"; +import {LibEtchRaindex} from "test/util/lib/LibEtchRaindex.sol"; -abstract contract OrderBookV6ExternalRealTest is Test, IRaindexV6Stub { +abstract contract RaindexV6ExternalRealTest is Test, IRaindexV6Stub { IInterpreterV4 internal immutable iInterpreter; IInterpreterStoreV3 internal immutable iStore; IParserV2 internal immutable iParserV2; - IRaindexV6 internal immutable iOrderbook; + IRaindexV6 internal immutable iRaindex; IERC20 internal immutable iToken0; IERC20 internal immutable iToken1; - OrderBookV6SubParser internal immutable iSubParser; + RaindexV6SubParser internal immutable iSubParser; constructor() { LibRainDeploy.etchZoltuFactory(vm); LibRainDeploy.deployZoltu(LibTOFUTokenDecimals.TOFU_DECIMALS_EXPECTED_CREATION_CODE); LibInterpreterDeploy.etchRainlang(vm); - LibEtchOrderBook.etchOrderBook(vm); + LibEtchRaindex.etchRaindex(vm); iInterpreter = IInterpreterV4(LibInterpreterDeploy.INTERPRETER_DEPLOYED_ADDRESS); iStore = IInterpreterStoreV3(LibInterpreterDeploy.STORE_DEPLOYED_ADDRESS); iParserV2 = IParserV2(LibInterpreterDeploy.EXPRESSION_DEPLOYER_DEPLOYED_ADDRESS); - iOrderbook = IRaindexV6(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS); + iRaindex = IRaindexV6(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS); iToken0 = IERC20(address(uint160(uint256(keccak256("token0.rain.test"))))); vm.etch(address(iToken0), REVERTING_MOCK_BYTECODE); @@ -54,7 +54,7 @@ abstract contract OrderBookV6ExternalRealTest is Test, IRaindexV6Stub { vm.etch(address(iToken1), REVERTING_MOCK_BYTECODE); vm.mockCall(address(iToken1), abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(18)); - iSubParser = OrderBookV6SubParser(LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS); + iSubParser = RaindexV6SubParser(LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS); } function assumeEtchable(address account) internal view { @@ -64,10 +64,10 @@ abstract contract OrderBookV6ExternalRealTest is Test, IRaindexV6Stub { vm.assume(account != address(iParserV2)); vm.assume(account != LibInterpreterDeploy.PARSER_DEPLOYED_ADDRESS); - vm.assume(account != LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS); + vm.assume(account != LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS); vm.assume(account != address(iToken0)); vm.assume(account != address(iToken1)); - vm.assume(account != LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS); + vm.assume(account != LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS); vm.assume(account != address(this)); vm.assume(account != address(vm)); @@ -90,11 +90,11 @@ abstract contract OrderBookV6ExternalRealTest is Test, IRaindexV6Stub { vm.mockCall(token, abi.encodeWithSelector(IERC20.balanceOf.selector, owner), abi.encode(depositAmount18)); vm.mockCall( token, - abi.encodeWithSelector(IERC20.allowance.selector, owner, address(iOrderbook)), + abi.encodeWithSelector(IERC20.allowance.selector, owner, address(iRaindex)), abi.encode(depositAmount18) ); vm.mockCall( - token, abi.encodeWithSelector(IERC20.transferFrom.selector, owner, address(iOrderbook)), abi.encode(true) + token, abi.encodeWithSelector(IERC20.transferFrom.selector, owner, address(iRaindex)), abi.encode(true) ); } @@ -103,7 +103,7 @@ abstract contract OrderBookV6ExternalRealTest is Test, IRaindexV6Stub { /// the expected amount is non-zero. function mockVault0Input(address token, address owner, uint256 expectAmount18) internal { vm.mockCall(token, abi.encodeWithSelector(IERC20.balanceOf.selector, owner), abi.encode(0)); - vm.mockCall(token, abi.encodeWithSelector(IERC20.allowance.selector, owner, address(iOrderbook)), abi.encode(0)); + vm.mockCall(token, abi.encodeWithSelector(IERC20.allowance.selector, owner, address(iRaindex)), abi.encode(0)); if (expectAmount18 > 0) { vm.mockCall( token, abi.encodeWithSelector(IERC20.transfer.selector, owner, expectAmount18), abi.encode(true) diff --git a/test/util/abstract/OrderBookV6SelfTest.sol b/test/util/abstract/RaindexV6SelfTest.sol similarity index 62% rename from test/util/abstract/OrderBookV6SelfTest.sol rename to test/util/abstract/RaindexV6SelfTest.sol index 2f444234ec..21adc394dd 100644 --- a/test/util/abstract/OrderBookV6SelfTest.sol +++ b/test/util/abstract/RaindexV6SelfTest.sol @@ -6,10 +6,10 @@ import {Test} from "forge-std/Test.sol"; import {REVERTING_MOCK_BYTECODE} from "test/util/lib/LibTestConstants.sol"; -import {OrderBookV6} from "../../../src/concrete/ob/OrderBookV6.sol"; +import {RaindexV6} from "../../../src/concrete/ob/RaindexV6.sol"; -/// @title OrderBookV6SelfTest -/// Abstract contract that is an `OrderBookV6` and can be used to test itself. +/// @title RaindexV6SelfTest +/// Abstract contract that is an `RaindexV6` and can be used to test itself. /// Inherits from Test so that it can be used as a base contract for other tests. /// Mocks all externalities during construction. -abstract contract OrderBookV6SelfTest is Test, OrderBookV6 {} +abstract contract RaindexV6SelfTest is Test, RaindexV6 {} diff --git a/test/util/abstract/OrderBookV6SubParserContextTest.sol b/test/util/abstract/RaindexV6SubParserContextTest.sol similarity index 68% rename from test/util/abstract/OrderBookV6SubParserContextTest.sol rename to test/util/abstract/RaindexV6SubParserContextTest.sol index 2998fb99d8..0cb7768997 100644 --- a/test/util/abstract/OrderBookV6SubParserContextTest.sol +++ b/test/util/abstract/RaindexV6SubParserContextTest.sol @@ -5,22 +5,22 @@ pragma solidity =0.8.25; import {StackAllocationMismatch} from "rain.interpreter/error/ErrIntegrity.sol"; import {OpTest, StackItem} from "rain.interpreter/../test/abstract/OpTest.sol"; import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol"; -import {LibOrderBookSubParserContextFixture} from "test/util/fixture/LibOrderBookSubParserContextFixture.sol"; -import {LibOrderBookDeploy} from "../../../src/lib/deploy/LibOrderBookDeploy.sol"; -import {LibEtchOrderBook} from "test/util/lib/LibEtchOrderBook.sol"; +import {LibRaindexSubParserContextFixture} from "test/util/fixture/LibRaindexSubParserContextFixture.sol"; +import {LibRaindexDeploy} from "../../../src/lib/deploy/LibRaindexDeploy.sol"; +import {LibEtchRaindex} from "test/util/lib/LibEtchRaindex.sol"; -abstract contract OrderBookV6SubParserContextTest is OpTest { +abstract contract RaindexV6SubParserContextTest is OpTest { using Strings for address; function setUp() public { - LibEtchOrderBook.etchOrderBook(vm); + LibEtchRaindex.etchRaindex(vm); } function word() internal pure virtual returns (string memory); function testSubParserContextHappy() external view { string memory w = word(); - address subParserAddress = LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS; + address subParserAddress = LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS; StackItem[] memory expectedStack = new StackItem[](1); expectedStack[0] = StackItem.wrap(keccak256(bytes(w))); @@ -28,12 +28,12 @@ abstract contract OrderBookV6SubParserContextTest is OpTest { bytes memory rainlang = bytes(string.concat("using-words-from ", subParserAddress.toHexString(), " _: ", w, "();")); - checkHappy(rainlang, LibOrderBookSubParserContextFixture.hashedNamesContext(), expectedStack, w); + checkHappy(rainlang, LibRaindexSubParserContextFixture.hashedNamesContext(), expectedStack, w); } function testSubParserContextUnhappyDisallowedOperand() external { string memory w = word(); - address subParserAddress = LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS; + address subParserAddress = LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS; bytes memory rainlang = bytes(string.concat("using-words-from ", subParserAddress.toHexString(), " _: ", w, "<1>();")); @@ -43,7 +43,7 @@ abstract contract OrderBookV6SubParserContextTest is OpTest { function testSubParserContextUnhappyDisallowedInputs() external { string memory w = word(); - address subParserAddress = LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS; + address subParserAddress = LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS; bytes memory rainlang = bytes(string.concat("using-words-from ", subParserAddress.toHexString(), " _: ", w, "(1);")); diff --git a/test/util/abstract/RouteProcessorOrderBookV6ArbOrderTakerTest.sol b/test/util/abstract/RouteProcessorRaindexV6ArbOrderTakerTest.sol similarity index 53% rename from test/util/abstract/RouteProcessorOrderBookV6ArbOrderTakerTest.sol rename to test/util/abstract/RouteProcessorRaindexV6ArbOrderTakerTest.sol index a78ccf54b7..79c2eaf0cf 100644 --- a/test/util/abstract/RouteProcessorOrderBookV6ArbOrderTakerTest.sol +++ b/test/util/abstract/RouteProcessorRaindexV6ArbOrderTakerTest.sol @@ -4,12 +4,12 @@ pragma solidity =0.8.25; import {ArbTest} from "./ArbTest.sol"; import { - RouteProcessorOrderBookV6ArbOrderTaker -} from "../../../src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol"; + RouteProcessorRaindexV6ArbOrderTaker +} from "../../../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; -contract RouteProcessorOrderBookV6ArbOrderTakerTest is ArbTest { +contract RouteProcessorRaindexV6ArbOrderTakerTest is ArbTest { function buildArb() internal override returns (address payable) { - return payable(address(new RouteProcessorOrderBookV6ArbOrderTaker())); + return payable(address(new RouteProcessorRaindexV6ArbOrderTaker())); } constructor() ArbTest() {} diff --git a/test/util/concrete/ChildOrderBookV6ArbOrderTaker.sol b/test/util/concrete/ChildRaindexV6ArbOrderTaker.sol similarity index 62% rename from test/util/concrete/ChildOrderBookV6ArbOrderTaker.sol rename to test/util/concrete/ChildRaindexV6ArbOrderTaker.sol index 8a55063b88..4a82ddadca 100644 --- a/test/util/concrete/ChildOrderBookV6ArbOrderTaker.sol +++ b/test/util/concrete/ChildRaindexV6ArbOrderTaker.sol @@ -2,10 +2,10 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ArbOrderTaker} from "../../../src/abstract/OrderBookV6ArbOrderTaker.sol"; +import {RaindexV6ArbOrderTaker} from "../../../src/abstract/RaindexV6ArbOrderTaker.sol"; /// @dev We need a contract that is deployable in order to test the abstract /// base contract. -contract ChildOrderBookV6ArbOrderTaker is OrderBookV6ArbOrderTaker { +contract ChildRaindexV6ArbOrderTaker is RaindexV6ArbOrderTaker { constructor() {} } diff --git a/test/util/concrete/ChildOrderBookV6ArbTaskGated.sol b/test/util/concrete/ChildRaindexV6ArbTaskGated.sol similarity index 63% rename from test/util/concrete/ChildOrderBookV6ArbTaskGated.sol rename to test/util/concrete/ChildRaindexV6ArbTaskGated.sol index 8a250fd1a7..e4af8af415 100644 --- a/test/util/concrete/ChildOrderBookV6ArbTaskGated.sol +++ b/test/util/concrete/ChildRaindexV6ArbTaskGated.sol @@ -2,13 +2,13 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {OrderBookV6ArbTaskGated, OrderBookV6ArbConfig} from "../../../src/abstract/OrderBookV6ArbTaskGated.sol"; +import {RaindexV6ArbTaskGated, RaindexV6ArbConfig} from "../../../src/abstract/RaindexV6ArbTaskGated.sol"; import {TaskV2} from "rain.raindex.interface/interface/IRaindexV6.sol"; /// @dev We need a contract that is deployable in order to test the abstract /// base contract. Exposes `_checkTaskHash` as an external function. -contract ChildOrderBookV6ArbTaskGated is OrderBookV6ArbTaskGated { - constructor(OrderBookV6ArbConfig memory config) OrderBookV6ArbTaskGated(config) {} +contract ChildRaindexV6ArbTaskGated is RaindexV6ArbTaskGated { + constructor(RaindexV6ArbConfig memory config) RaindexV6ArbTaskGated(config) {} function checkTaskHash(TaskV2 memory task) external view { _checkTaskHash(task); diff --git a/test/util/concrete/FlashLendingMockOrderBook.sol b/test/util/concrete/FlashLendingMockRaindex.sol similarity index 97% rename from test/util/concrete/FlashLendingMockOrderBook.sol rename to test/util/concrete/FlashLendingMockRaindex.sol index e606ba642b..4697b3b2d8 100644 --- a/test/util/concrete/FlashLendingMockOrderBook.sol +++ b/test/util/concrete/FlashLendingMockRaindex.sol @@ -18,7 +18,7 @@ import { } from "rain.raindex.interface/interface/IRaindexV6.sol"; import {IERC3156FlashBorrower} from "rain.raindex.interface/interface/ierc3156/IERC3156FlashBorrower.sol"; -contract FlashLendingMockOrderBook is IRaindexV6 { +contract FlashLendingMockRaindex is IRaindexV6 { function flashLoan(IERC3156FlashBorrower receiver, address token, uint256 amount, bytes calldata data) external returns (bool) diff --git a/test/util/concrete/MaliciousLender.sol b/test/util/concrete/MaliciousLender.sol index f6b845ea3e..23531167db 100644 --- a/test/util/concrete/MaliciousLender.sol +++ b/test/util/concrete/MaliciousLender.sol @@ -4,14 +4,14 @@ pragma solidity =0.8.25; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; -import {GenericPoolOrderBookV6FlashBorrower} from "../../../src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol"; +import {GenericPoolRaindexV6FlashBorrower} from "../../../src/concrete/arb/GenericPoolRaindexV6FlashBorrower.sol"; /// @dev Malicious lender that calls onFlashLoan directly, pretending to be a /// flash loan provider while passing the arb's own address as initiator. contract MaliciousLender { using SafeERC20 for IERC20; - function attack(GenericPoolOrderBookV6FlashBorrower arb, address token, uint256 amount, bytes calldata data) + function attack(GenericPoolRaindexV6FlashBorrower arb, address token, uint256 amount, bytes calldata data) external { IERC20(token).safeTransfer(address(arb), amount); diff --git a/test/util/concrete/MaliciousOrderBook.sol b/test/util/concrete/MaliciousRaindex.sol similarity index 85% rename from test/util/concrete/MaliciousOrderBook.sol rename to test/util/concrete/MaliciousRaindex.sol index f84d9c6693..f48ceffb55 100644 --- a/test/util/concrete/MaliciousOrderBook.sol +++ b/test/util/concrete/MaliciousRaindex.sol @@ -4,12 +4,12 @@ pragma solidity =0.8.25; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {IERC3156FlashBorrower} from "rain.raindex.interface/interface/ierc3156/IERC3156FlashBorrower.sol"; -import {MockOrderBookBase} from "test/util/abstract/MockOrderBookBase.sol"; +import {MockRaindexBase} from "test/util/abstract/MockRaindexBase.sol"; -/// @dev Malicious orderbook that records the token allowances it has from the +/// @dev Malicious raindex that records the token allowances it has from the /// borrower during flashLoan, before calling onFlashLoan (which will revert -/// with BadLender since this contract is not the deterministic orderbook). -contract MaliciousOrderBook is MockOrderBookBase { +/// with BadLender since this contract is not the deterministic raindex). +contract MaliciousRaindex is MockRaindexBase { uint256 public inputAllowanceDuringFlashLoan; uint256 public outputAllowanceDuringFlashLoan; address public inputToken; @@ -31,7 +31,7 @@ contract MaliciousOrderBook is MockOrderBookBase { outputAllowanceDuringFlashLoan = IERC20(outputToken).allowance(address(receiver), address(this)); // This will revert with BadLender since we are not the deterministic - // orderbook address. + // raindex address. receiver.onFlashLoan(address(receiver), token, amount, 0, data); return true; diff --git a/test/util/concrete/RealisticFlashLendingMockOrderBook.sol b/test/util/concrete/RealisticFlashLendingMockRaindex.sol similarity index 89% rename from test/util/concrete/RealisticFlashLendingMockOrderBook.sol rename to test/util/concrete/RealisticFlashLendingMockRaindex.sol index bdc4bf0929..60abc6d723 100644 --- a/test/util/concrete/RealisticFlashLendingMockOrderBook.sol +++ b/test/util/concrete/RealisticFlashLendingMockRaindex.sol @@ -9,11 +9,11 @@ import { IERC3156FlashBorrower, ON_FLASH_LOAN_CALLBACK_SUCCESS } from "rain.raindex.interface/interface/ierc3156/IERC3156FlashBorrower.sol"; -import {MockOrderBookBase} from "test/util/abstract/MockOrderBookBase.sol"; +import {MockRaindexBase} from "test/util/abstract/MockRaindexBase.sol"; -/// @dev Mock orderbook with real ERC3156 flash loan transfers and real +/// @dev Mock raindex with real ERC3156 flash loan transfers and real /// takeOrders4 transfers (no onTakeOrders2 callback). -contract RealisticFlashLendingMockOrderBook is MockOrderBookBase { +contract RealisticFlashLendingMockRaindex is MockRaindexBase { using SafeERC20 for IERC20; function flashLoan(IERC3156FlashBorrower receiver, address token, uint256 amount, bytes calldata data) diff --git a/test/util/concrete/RealisticOrderTakerMockOrderBook.sol b/test/util/concrete/RealisticOrderTakerMockRaindex.sol similarity index 89% rename from test/util/concrete/RealisticOrderTakerMockOrderBook.sol rename to test/util/concrete/RealisticOrderTakerMockRaindex.sol index 717817f2a8..bd44582a4b 100644 --- a/test/util/concrete/RealisticOrderTakerMockOrderBook.sol +++ b/test/util/concrete/RealisticOrderTakerMockRaindex.sol @@ -6,12 +6,12 @@ import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import {TakeOrdersConfigV5, Float} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {IRaindexV6OrderTaker} from "rain.raindex.interface/interface/IRaindexV6OrderTaker.sol"; -import {MockOrderBookBase} from "test/util/abstract/MockOrderBookBase.sol"; +import {MockRaindexBase} from "test/util/abstract/MockRaindexBase.sol"; -/// @dev Mock orderbook with real takeOrders4 transfers and onTakeOrders2 +/// @dev Mock raindex with real takeOrders4 transfers and onTakeOrders2 /// callback. Pulls a configurable amount of inputToken from the taker, /// leaving any surplus as profit for finalizeArb to sweep. -contract RealisticOrderTakerMockOrderBook is MockOrderBookBase { +contract RealisticOrderTakerMockRaindex is MockRaindexBase { using SafeERC20 for IERC20; uint256 public immutable iPullAmount; diff --git a/test/util/concrete/ReentrantExchange.sol b/test/util/concrete/ReentrantExchange.sol index 91599fe805..2a5a5227f3 100644 --- a/test/util/concrete/ReentrantExchange.sol +++ b/test/util/concrete/ReentrantExchange.sol @@ -2,7 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity =0.8.25; -import {GenericPoolOrderBookV6FlashBorrower} from "../../../src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol"; +import {GenericPoolRaindexV6FlashBorrower} from "../../../src/concrete/arb/GenericPoolRaindexV6FlashBorrower.sol"; import { IRaindexV6, TakeOrdersConfigV5, @@ -19,12 +19,12 @@ import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; /// @dev Exchange that re-enters arb4 when called during _exchange. contract ReentrantExchange { - GenericPoolOrderBookV6FlashBorrower internal immutable iArb; - IRaindexV6 internal immutable iOrderBook; + GenericPoolRaindexV6FlashBorrower internal immutable iArb; + IRaindexV6 internal immutable iRaindex; - constructor(GenericPoolOrderBookV6FlashBorrower arb, IRaindexV6 orderBook) { + constructor(GenericPoolRaindexV6FlashBorrower arb, IRaindexV6 raindex) { iArb = arb; - iOrderBook = orderBook; + iRaindex = raindex; } /// Called by pool.functionCallWithValue during _exchange. Re-enters arb4. @@ -46,7 +46,7 @@ contract ReentrantExchange { orders[0] = TakeOrderConfigV4(order, 0, 0, new SignedContextV1[](0)); iArb.arb4( - iOrderBook, + iRaindex, TakeOrdersConfigV5({ minimumIO: LibDecimalFloat.packLossless(1, 0), maximumIO: LibDecimalFloat.packLossless(type(int224).max, 0), diff --git a/test/util/concrete/ReentrantMockOrderBook.sol b/test/util/concrete/ReentrantMockRaindex.sol similarity index 84% rename from test/util/concrete/ReentrantMockOrderBook.sol rename to test/util/concrete/ReentrantMockRaindex.sol index effb0f5328..e4a8d66863 100644 --- a/test/util/concrete/ReentrantMockOrderBook.sol +++ b/test/util/concrete/ReentrantMockRaindex.sol @@ -4,7 +4,7 @@ pragma solidity =0.8.25; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; -import {GenericPoolOrderBookV6ArbOrderTaker} from "../../../src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol"; +import {GenericPoolRaindexV6ArbOrderTaker} from "../../../src/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.sol"; import { IRaindexV6, TakeOrdersConfigV5, @@ -15,10 +15,10 @@ import { } from "rain.raindex.interface/interface/IRaindexV6.sol"; import {IInterpreterV4} from "rain.interpreter.interface/interface/IInterpreterV4.sol"; import {IInterpreterStoreV3} from "rain.interpreter.interface/interface/IInterpreterStoreV3.sol"; -import {MockOrderBookBase} from "test/util/abstract/MockOrderBookBase.sol"; +import {MockRaindexBase} from "test/util/abstract/MockRaindexBase.sol"; /// @dev Mock OB whose takeOrders4 callback re-enters arb5 on the taker. -contract ReentrantMockOrderBook is MockOrderBookBase { +contract ReentrantMockRaindex is MockRaindexBase { using SafeERC20 for IERC20; bool internal sReentered; @@ -33,7 +33,7 @@ contract ReentrantMockOrderBook is MockOrderBookBase { if (!sReentered) { sReentered = true; // Re-enter arb5 from the OB callback. - GenericPoolOrderBookV6ArbOrderTaker(payable(msg.sender)) + GenericPoolRaindexV6ArbOrderTaker(payable(msg.sender)) .arb5( IRaindexV6(address(this)), config, diff --git a/test/util/fixture/LibOrderBookSubParserContextFixture.sol b/test/util/fixture/LibRaindexSubParserContextFixture.sol similarity index 97% rename from test/util/fixture/LibOrderBookSubParserContextFixture.sol rename to test/util/fixture/LibRaindexSubParserContextFixture.sol index dfe057440b..f0074e3e25 100644 --- a/test/util/fixture/LibOrderBookSubParserContextFixture.sol +++ b/test/util/fixture/LibRaindexSubParserContextFixture.sol @@ -3,7 +3,7 @@ pragma solidity =0.8.25; import { - WORD_ORDERBOOK, + WORD_RAINDEX, WORD_ORDER_CLEARER, WORD_ORDER_HASH, WORD_ORDER_OWNER, @@ -44,16 +44,16 @@ import { WORD_OUTPUT_VAULT_BALANCE_DECREASE, CONTEXT_SIGNED_CONTEXT_SIGNERS_COLUMN, CONTEXT_SIGNED_CONTEXT_START_COLUMN -} from "../../../src/lib/LibOrderBookSubParser.sol"; +} from "../../../src/lib/LibRaindexSubParser.sol"; -library LibOrderBookSubParserContextFixture { +library LibRaindexSubParserContextFixture { function hashedNamesContext() internal pure returns (bytes32[][] memory) { // Add 3 to account for the signers and 2x signed context columns. bytes32[][] memory context = new bytes32[][](CONTEXT_COLUMNS + 3); bytes32[] memory contextBase = new bytes32[](CONTEXT_BASE_ROWS); contextBase[CONTEXT_BASE_ROW_SENDER] = keccak256(WORD_ORDER_CLEARER); - contextBase[CONTEXT_BASE_ROW_CALLING_CONTRACT] = keccak256(WORD_ORDERBOOK); + contextBase[CONTEXT_BASE_ROW_CALLING_CONTRACT] = keccak256(WORD_RAINDEX); bytes32[] memory contextCallingContext = new bytes32[](CONTEXT_CALLING_CONTEXT_ROWS); contextCallingContext[CONTEXT_CALLING_CONTEXT_ROW_ORDER_HASH] = keccak256(WORD_ORDER_HASH); diff --git a/test/util/lib/LibEtchOrderBook.sol b/test/util/lib/LibEtchOrderBook.sol deleted file mode 100644 index 1c3e1eceba..0000000000 --- a/test/util/lib/LibEtchOrderBook.sol +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-DCL-1.0 -// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd -pragma solidity =0.8.25; - -import {Vm} from "forge-std/Vm.sol"; -import {LibOrderBookDeploy} from "../../../src/lib/deploy/LibOrderBookDeploy.sol"; -import {RUNTIME_CODE as ORDERBOOK_RUNTIME_CODE} from "../../../src/generated/OrderBookV6.pointers.sol"; -import {RUNTIME_CODE as SUB_PARSER_RUNTIME_CODE} from "../../../src/generated/OrderBookV6SubParser.pointers.sol"; -import {RUNTIME_CODE as ROUTE_PROCESSOR_RUNTIME_CODE} from "../../../src/generated/RouteProcessor4.pointers.sol"; - -/// @title LibEtchOrderBook -/// @notice Etches the runtime bytecode of the orderbook, sub parser, and -/// route processor at their expected deterministic addresses. -library LibEtchOrderBook { - /// @notice Etches the runtime bytecode of the orderbook, sub parser, and - /// route processor at their expected deterministic addresses. Skips any - /// contract whose codehash already matches. - /// @param vm The Forge `Vm` cheatcode interface. - function etchOrderBook(Vm vm) internal { - if (LibOrderBookDeploy.ORDERBOOK_DEPLOYED_CODEHASH != LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS.codehash) { - vm.etch(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS, ORDERBOOK_RUNTIME_CODE); - } - if (LibOrderBookDeploy.SUB_PARSER_DEPLOYED_CODEHASH != LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS.codehash) - { - vm.etch(LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS, SUB_PARSER_RUNTIME_CODE); - } - if ( - LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_CODEHASH - != LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS.codehash - ) { - vm.etch(LibOrderBookDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS, ROUTE_PROCESSOR_RUNTIME_CODE); - } - } -} diff --git a/test/util/lib/LibEtchRaindex.sol b/test/util/lib/LibEtchRaindex.sol new file mode 100644 index 0000000000..a5f9a79f08 --- /dev/null +++ b/test/util/lib/LibEtchRaindex.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: LicenseRef-DCL-1.0 +// SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd +pragma solidity =0.8.25; + +import {Vm} from "forge-std/Vm.sol"; +import {LibRaindexDeploy} from "../../../src/lib/deploy/LibRaindexDeploy.sol"; +import {RUNTIME_CODE as RAINDEX_RUNTIME_CODE} from "../../../src/generated/RaindexV6.pointers.sol"; +import {RUNTIME_CODE as SUB_PARSER_RUNTIME_CODE} from "../../../src/generated/RaindexV6SubParser.pointers.sol"; +import {RUNTIME_CODE as ROUTE_PROCESSOR_RUNTIME_CODE} from "../../../src/generated/RouteProcessor4.pointers.sol"; + +/// @title LibEtchRaindex +/// @notice Etches the runtime bytecode of the raindex, sub parser, and +/// route processor at their expected deterministic addresses. +library LibEtchRaindex { + /// @notice Etches the runtime bytecode of the raindex, sub parser, and + /// route processor at their expected deterministic addresses. Skips any + /// contract whose codehash already matches. + /// @param vm The Forge `Vm` cheatcode interface. + function etchRaindex(Vm vm) internal { + if (LibRaindexDeploy.RAINDEX_DEPLOYED_CODEHASH != LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS.codehash) { + vm.etch(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, RAINDEX_RUNTIME_CODE); + } + if (LibRaindexDeploy.SUB_PARSER_DEPLOYED_CODEHASH != LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS.codehash) + { + vm.etch(LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS, SUB_PARSER_RUNTIME_CODE); + } + if ( + LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_CODEHASH + != LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS.codehash + ) { + vm.etch(LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS, ROUTE_PROCESSOR_RUNTIME_CODE); + } + } +} diff --git a/test/util/lib/LibTestAddOrder.sol b/test/util/lib/LibTestAddOrder.sol index 4fc8c536aa..1ec02dcb2a 100644 --- a/test/util/lib/LibTestAddOrder.sol +++ b/test/util/lib/LibTestAddOrder.sol @@ -8,7 +8,7 @@ import {OrderConfigV4, OrderV4, IOV2} from "rain.raindex.interface/interface/IRa import {IInterpreterV4, SourceIndexV2} from "rain.interpreter.interface/interface/IInterpreterV4.sol"; import {IInterpreterStoreV3} from "rain.interpreter.interface/interface/IInterpreterStoreV3.sol"; import {EvaluableV4} from "rain.interpreter.interface/interface/IInterpreterCallerV4.sol"; -import {HANDLE_IO_ENTRYPOINT} from "../../../src/concrete/ob/OrderBookV6.sol"; +import {HANDLE_IO_ENTRYPOINT} from "../../../src/concrete/ob/RaindexV6.sol"; import {LibBytecode} from "rain.interpreter.interface/lib/bytecode/LibBytecode.sol"; library LibTestAddOrder { diff --git a/test/util/lib/LibTestArb.sol b/test/util/lib/LibTestArb.sol index 264e0bfd14..318c24a0a6 100644 --- a/test/util/lib/LibTestArb.sol +++ b/test/util/lib/LibTestArb.sol @@ -20,26 +20,26 @@ import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; import {LibInterpreterDeploy} from "rain.interpreter/lib/deploy/LibInterpreterDeploy.sol"; import {LibTOFUTokenDecimals} from "rain.tofu.erc20-decimals/lib/LibTOFUTokenDecimals.sol"; -import {GenericPoolOrderBookV6ArbOrderTaker} from "../../../src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol"; +import {GenericPoolRaindexV6ArbOrderTaker} from "../../../src/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.sol"; import {MockToken} from "test/util/concrete/MockToken.sol"; import {MockExchange} from "test/util/concrete/MockExchange.sol"; -import {RealisticOrderTakerMockOrderBook} from "test/util/concrete/RealisticOrderTakerMockOrderBook.sol"; +import {RealisticOrderTakerMockRaindex} from "test/util/concrete/RealisticOrderTakerMockRaindex.sol"; /// @dev Return value from `setupAndArb`. struct ArbResult { - GenericPoolOrderBookV6ArbOrderTaker arb; + GenericPoolRaindexV6ArbOrderTaker arb; MockToken inputToken; MockToken outputToken; - RealisticOrderTakerMockOrderBook orderBook; + RealisticOrderTakerMockRaindex raindex; MockExchange exchange; } /// @dev Return value from `setup`. Caller keeps their own exchange reference. struct OrderTakerSetup { - GenericPoolOrderBookV6ArbOrderTaker arb; + GenericPoolRaindexV6ArbOrderTaker arb; MockToken inputToken; MockToken outputToken; - IRaindexV6 orderBook; + IRaindexV6 raindex; TakeOrdersConfigV5 takeOrdersConfig; } @@ -85,13 +85,13 @@ library LibTestArb { MockToken inputToken = new MockToken("Input", "IN", 18); MockToken outputToken = new MockToken("Output", "OUT", 18); - RealisticOrderTakerMockOrderBook orderBook = new RealisticOrderTakerMockOrderBook(obPullAmount); + RealisticOrderTakerMockRaindex raindex = new RealisticOrderTakerMockRaindex(obPullAmount); MockExchange exchange = new MockExchange(); - outputToken.mint(address(orderBook), obOutputAmount); + outputToken.mint(address(raindex), obOutputAmount); inputToken.mint(address(exchange), exchangeInputAmount); - GenericPoolOrderBookV6ArbOrderTaker arb = new GenericPoolOrderBookV6ArbOrderTaker(); + GenericPoolRaindexV6ArbOrderTaker arb = new GenericPoolRaindexV6ArbOrderTaker(); bytes memory exchangeData = abi.encodeCall(MockExchange.swap, (IERC20(address(outputToken)), IERC20(address(inputToken)), swapAmount)); @@ -128,10 +128,10 @@ library LibTestArb { }); } - arb.arb5{value: ethValue}(IRaindexV6(address(orderBook)), takeOrdersConfig, task); + arb.arb5{value: ethValue}(IRaindexV6(address(raindex)), takeOrdersConfig, task); return ArbResult({ - arb: arb, inputToken: inputToken, outputToken: outputToken, orderBook: orderBook, exchange: exchange + arb: arb, inputToken: inputToken, outputToken: outputToken, raindex: raindex, exchange: exchange }); } @@ -149,12 +149,12 @@ library LibTestArb { MockToken inputToken = new MockToken("Input", "IN", 18); MockToken outputToken = new MockToken("Output", "OUT", 18); - RealisticOrderTakerMockOrderBook orderBook = new RealisticOrderTakerMockOrderBook(amount); + RealisticOrderTakerMockRaindex raindex = new RealisticOrderTakerMockRaindex(amount); - outputToken.mint(address(orderBook), amount); + outputToken.mint(address(raindex), amount); inputToken.mint(exchange, amount); - GenericPoolOrderBookV6ArbOrderTaker arb = new GenericPoolOrderBookV6ArbOrderTaker(); + GenericPoolRaindexV6ArbOrderTaker arb = new GenericPoolRaindexV6ArbOrderTaker(); bytes memory exchangeData = abi.encodeCall(MockExchange.swap, (IERC20(address(outputToken)), IERC20(address(inputToken)), amount)); @@ -195,7 +195,7 @@ library LibTestArb { arb: arb, inputToken: inputToken, outputToken: outputToken, - orderBook: IRaindexV6(address(orderBook)), + raindex: IRaindexV6(address(raindex)), takeOrdersConfig: takeOrdersConfig }); } diff --git a/test/util/lib/LibTestFlashBorrowerArb.sol b/test/util/lib/LibTestFlashBorrowerArb.sol index b4b966e646..990cf3e180 100644 --- a/test/util/lib/LibTestFlashBorrowerArb.sol +++ b/test/util/lib/LibTestFlashBorrowerArb.sol @@ -19,18 +19,18 @@ import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; import {LibTOFUTokenDecimals} from "rain.tofu.erc20-decimals/lib/LibTOFUTokenDecimals.sol"; import {LibInterpreterDeploy} from "rain.interpreter/lib/deploy/LibInterpreterDeploy.sol"; -import {LibOrderBookDeploy} from "../../../src/lib/deploy/LibOrderBookDeploy.sol"; -import {GenericPoolOrderBookV6FlashBorrower} from "../../../src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol"; +import {LibRaindexDeploy} from "../../../src/lib/deploy/LibRaindexDeploy.sol"; +import {GenericPoolRaindexV6FlashBorrower} from "../../../src/concrete/arb/GenericPoolRaindexV6FlashBorrower.sol"; import {MockToken} from "test/util/concrete/MockToken.sol"; import {MockExchange} from "test/util/concrete/MockExchange.sol"; -import {RealisticFlashLendingMockOrderBook} from "test/util/concrete/RealisticFlashLendingMockOrderBook.sol"; +import {RealisticFlashLendingMockRaindex} from "test/util/concrete/RealisticFlashLendingMockRaindex.sol"; /// @dev Return value from `setup`. Caller keeps their own exchange reference. struct FlashBorrowerSetup { - GenericPoolOrderBookV6FlashBorrower arb; + GenericPoolRaindexV6FlashBorrower arb; MockToken inputToken; MockToken outputToken; - IRaindexV6 orderBook; + IRaindexV6 raindex; TakeOrdersConfigV5 takeOrdersConfig; bytes exchangeData; } @@ -44,7 +44,7 @@ library LibTestFlashBorrowerArb { /// @param exchange The exchange contract address. /// @param amount Token amount for the swap (18 decimals). Used as /// exchangeInputAmount, swapAmount, and minimumIO (flash loan size). - /// The orderbook receives 10x amount of outputToken. + /// The raindex receives 10x amount of outputToken. function setup(Vm vm, address exchange, uint256 amount) internal returns (FlashBorrowerSetup memory) { LibRainDeploy.etchZoltuFactory(vm); LibRainDeploy.deployZoltu(LibTOFUTokenDecimals.TOFU_DECIMALS_EXPECTED_CREATION_CODE); @@ -52,14 +52,14 @@ library LibTestFlashBorrowerArb { MockToken inputToken = new MockToken("Input", "IN", 18); MockToken outputToken = new MockToken("Output", "OUT", 18); - RealisticFlashLendingMockOrderBook mockOb = new RealisticFlashLendingMockOrderBook(); - vm.etch(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS, address(mockOb).code); - IRaindexV6 orderBook = IRaindexV6(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS); + RealisticFlashLendingMockRaindex mockOb = new RealisticFlashLendingMockRaindex(); + vm.etch(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, address(mockOb).code); + IRaindexV6 raindex = IRaindexV6(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS); - outputToken.mint(address(orderBook), 10 * amount); + outputToken.mint(address(raindex), 10 * amount); inputToken.mint(exchange, amount); - GenericPoolOrderBookV6FlashBorrower arb = new GenericPoolOrderBookV6FlashBorrower(); + GenericPoolRaindexV6FlashBorrower arb = new GenericPoolRaindexV6FlashBorrower(); bytes memory exchangeData = abi.encode( exchange, @@ -105,7 +105,7 @@ library LibTestFlashBorrowerArb { arb: arb, inputToken: inputToken, outputToken: outputToken, - orderBook: orderBook, + raindex: raindex, takeOrdersConfig: takeOrdersConfig, exchangeData: exchangeData }); diff --git a/test/util/lib/LibTestTakeOrder.sol b/test/util/lib/LibTestTakeOrder.sol index 3673357880..3a0f8751d5 100644 --- a/test/util/lib/LibTestTakeOrder.sol +++ b/test/util/lib/LibTestTakeOrder.sol @@ -19,7 +19,7 @@ import {IParserV2} from "rain.interpreter.interface/interface/IParserV2.sol"; import {SignedContextV1} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; import {Float, LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibInterpreterDeploy} from "rain.interpreter/lib/deploy/LibInterpreterDeploy.sol"; -import {LibOrderBookDeploy} from "../../../src/lib/deploy/LibOrderBookDeploy.sol"; +import {LibRaindexDeploy} from "../../../src/lib/deploy/LibRaindexDeploy.sol"; library LibTestTakeOrder { /// Extract OrderV4 from the first log entry emitted by addOrder4. @@ -30,7 +30,7 @@ library LibTestTakeOrder { /// Parse an expression string, add the order as `owner`, and return the /// resulting OrderV4. Uses deploy constants for interpreter/store/parser - /// and the orderbook. + /// and the raindex. function addOrderWithExpression( Vm vm, address owner, @@ -41,7 +41,7 @@ library LibTestTakeOrder { bytes32 outputVaultId ) internal returns (OrderV4 memory) { IParserV2 parser = IParserV2(LibInterpreterDeploy.EXPRESSION_DEPLOYER_DEPLOYED_ADDRESS); - IRaindexV6 orderbook = IRaindexV6(LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS); + IRaindexV6 raindex = IRaindexV6(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS); bytes memory bytecode = parser.parse2(expression); IOV2[] memory inputs = new IOV2[](1); @@ -58,7 +58,7 @@ library LibTestTakeOrder { vm.prank(owner); vm.recordLogs(); - orderbook.addOrder4(orderConfig, new TaskV2[](0)); + raindex.addOrder4(orderConfig, new TaskV2[](0)); return extractOrderFromLogs(vm.getRecordedLogs()); } From 90c410ebe189b1d10866a26748d6863a4f868889 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Thu, 26 Mar 2026 17:19:19 +0400 Subject: [PATCH 03/69] Rename OrderBook to Raindex in Rust workspace Update root Cargo.toml, crate Cargo.toml files, and all Rust source files. Rename crate names from rain_orderbook_* to raindex_*. Update settings crate types (OrderbookCfg -> RaindexCfg, etc.), YAML keys, module declarations, and file names. Co-Authored-By: Claude Opus 4.6 (1M context) --- Cargo.lock | 78 +-- Cargo.toml | 22 +- crates/bindings/ARCHITECTURE.md | 10 +- crates/bindings/Cargo.toml | 4 +- crates/bindings/src/lib.rs | 6 +- crates/cli/Cargo.toml | 16 +- crates/cli/src/commands/chart.rs | 6 +- crates/cli/src/commands/local_db/README.md | 4 +- crates/cli/src/commands/local_db/cli.rs | 12 +- crates/cli/src/commands/local_db/executor.rs | 2 +- .../commands/local_db/pipeline/bootstrap.rs | 18 +- .../local_db/pipeline/runner/environment.rs | 12 +- .../local_db/pipeline/runner/export.rs | 18 +- .../local_db/pipeline/runner/manifest.rs | 18 +- .../commands/local_db/pipeline/runner/mod.rs | 56 +-- .../src/commands/local_db/pipeline/status.rs | 2 +- crates/cli/src/commands/order/add.rs | 14 +- crates/cli/src/commands/order/calldata.rs | 8 +- crates/cli/src/commands/order/compose.rs | 4 +- crates/cli/src/commands/order/detail.rs | 4 +- crates/cli/src/commands/order/list.rs | 4 +- .../order/listorderfrontmatterkeys.rs | 4 +- crates/cli/src/commands/order/mod.rs | 10 +- ...rderbook_address.rs => raindex_address.rs} | 4 +- crates/cli/src/commands/order/remove.rs | 6 +- crates/cli/src/commands/quote/mod.rs | 2 +- crates/cli/src/commands/subgraph/mod.rs | 2 +- crates/cli/src/commands/trade/detail.rs | 2 +- crates/cli/src/commands/trade/list.rs | 4 +- crates/cli/src/commands/vault/deposit.rs | 2 +- crates/cli/src/commands/vault/detail.rs | 2 +- crates/cli/src/commands/vault/list.rs | 6 +- .../commands/vault/list_balance_changes.rs | 4 +- crates/cli/src/commands/vault/withdraw.rs | 4 +- crates/cli/src/commands/words.rs | 4 +- crates/cli/src/lib.rs | 2 +- crates/cli/src/main.rs | 2 +- crates/cli/src/subgraph.rs | 4 +- crates/cli/src/transaction.rs | 2 +- crates/common/ARCHITECTURE.md | 12 +- crates/common/Cargo.toml | 14 +- crates/common/src/add_order.rs | 8 +- crates/common/src/deposit.rs | 4 +- crates/common/src/dotrain_add_order_lsp.rs | 4 +- crates/common/src/dotrain_order.rs | 8 +- crates/common/src/erc20.rs | 8 +- crates/common/src/fuzz/impls.rs | 14 +- crates/common/src/fuzz/mod.rs | 2 +- .../common/src/local_db/address_collectors.rs | 12 +- crates/common/src/local_db/decode.rs | 4 +- crates/common/src/local_db/fetch.rs | 4 +- crates/common/src/local_db/insert.rs | 8 +- crates/common/src/local_db/mod.rs | 4 +- .../src/local_db/pipeline/adapters/apply.rs | 4 +- .../local_db/pipeline/adapters/bootstrap.rs | 2 +- .../src/local_db/pipeline/adapters/events.rs | 2 +- .../src/local_db/pipeline/adapters/tokens.rs | 2 +- crates/common/src/local_db/pipeline/engine.rs | 6 +- .../local_db/pipeline/runner/environment.rs | 14 +- .../src/local_db/pipeline/runner/remotes.rs | 18 +- .../src/local_db/pipeline/runner/utils.rs | 16 +- .../mod.rs | 0 .../query.sql | 0 crates/common/src/local_db/token_fetch.rs | 2 +- crates/common/src/meta.rs | 4 +- crates/common/src/oracle.rs | 2 +- .../common/src/raindex_client/add_orders.rs | 4 +- .../common/src/raindex_client/local_db/mod.rs | 4 +- .../local_db/pipeline/bootstrap.rs | 2 +- .../local_db/pipeline/runner/config.rs | 6 +- .../local_db/pipeline/runner/mod.rs | 10 +- .../pipeline/runner/scheduler/native.rs | 4 +- .../pipeline/runner/scheduler/wasm.rs | 4 +- .../src/raindex_client/local_db/state.rs | 10 +- crates/common/src/raindex_client/mod.rs | 10 +- .../common/src/raindex_client/order_quotes.rs | 8 +- crates/common/src/raindex_client/orders.rs | 14 +- .../{orderbook_yaml.rs => raindex_yaml.rs} | 2 +- .../src/raindex_client/remove_orders.rs | 8 +- .../raindex_client/take_orders/approval.rs | 2 +- .../raindex_client/take_orders/e2e_tests.rs | 2 +- .../src/raindex_client/take_orders/mod.rs | 2 +- .../src/raindex_client/take_orders/result.rs | 6 +- .../src/raindex_client/take_orders/single.rs | 12 +- .../take_orders/single_tests.rs | 4 +- crates/common/src/raindex_client/trades.rs | 6 +- .../common/src/raindex_client/transactions.rs | 4 +- crates/common/src/raindex_client/vaults.rs | 16 +- .../common/src/raindex_client/vaults_list.rs | 2 +- crates/common/src/rainlang.rs | 2 +- crates/common/src/remove_order.rs | 10 +- crates/common/src/replays.rs | 4 +- crates/common/src/rpc_client.rs | 2 +- crates/common/src/subgraph.rs | 2 +- crates/common/src/take_orders/candidates.rs | 2 +- crates/common/src/take_orders/config.rs | 2 +- crates/common/src/take_orders/preflight.rs | 20 +- crates/common/src/test_helpers.rs | 24 +- crates/common/src/transaction.rs | 2 +- .../common/src/types/order_detail_extended.rs | 4 +- .../src/types/order_takes_list_flattened.rs | 6 +- .../common/src/types/orders_list_flattened.rs | 8 +- .../common/src/types/token_vault_flattened.rs | 6 +- .../types/vault_balance_change_flattened.rs | 6 +- crates/common/src/unit_tests.rs | 6 +- crates/common/src/withdraw.rs | 2 +- crates/integration_tests/Cargo.toml | 8 +- crates/integration_tests/src/lib.rs | 6 +- crates/js_api/ARCHITECTURE.md | 12 +- crates/js_api/Cargo.toml | 12 +- crates/js_api/src/bindings/mod.rs | 2 +- crates/js_api/src/gui/deposits.rs | 2 +- crates/js_api/src/gui/mod.rs | 18 +- crates/js_api/src/gui/order_operations.rs | 8 +- crates/js_api/src/gui/select_tokens.rs | 6 +- crates/js_api/src/gui/state_management.rs | 8 +- crates/js_api/src/gui/validation.rs | 4 +- crates/js_api/src/lib.rs | 6 +- crates/js_api/src/rainlang.rs | 6 +- crates/js_api/src/yaml/mod.rs | 10 +- crates/math/ARCHITECTURE.md | 8 +- crates/math/Cargo.toml | 4 +- crates/quote/ARCHITECTURE.md | 16 +- crates/quote/Cargo.toml | 14 +- crates/quote/src/cli/input.rs | 4 +- crates/quote/src/cli/mod.rs | 2 +- crates/quote/src/error.rs | 4 +- crates/quote/src/main.rs | 2 +- crates/quote/src/oracle.rs | 6 +- crates/quote/src/order_quotes.rs | 14 +- crates/quote/src/quote.rs | 8 +- crates/quote/src/quote_debug.rs | 12 +- crates/quote/src/rpc.rs | 6 +- crates/rest_api/Cargo.toml | 8 +- crates/rest_api/src/error.rs | 2 +- crates/rest_api/src/routes/take_orders.rs | 16 +- crates/settings/Cargo.toml | 6 +- crates/settings/src/gui.rs | 2 +- crates/settings/src/lib.rs | 4 +- crates/settings/src/order.rs | 38 +- .../settings/src/{orderbook.rs => raindex.rs} | 456 +++++++++--------- crates/settings/src/test.rs | 8 +- crates/settings/src/yaml/context.rs | 8 +- crates/settings/src/yaml/dotrain.rs | 16 +- crates/settings/src/yaml/emitter.rs | 6 +- crates/settings/src/yaml/mod.rs | 18 +- .../src/yaml/{orderbook.rs => raindex.rs} | 252 +++++----- crates/subgraph/Cargo.toml | 8 +- .../{orderbook.graphql => raindex.graphql} | 0 ...book_client.rs => multi_raindex_client.rs} | 0 crates/subgraph/src/performance/apy.rs | 2 +- crates/subgraph/src/performance/mod.rs | 4 +- .../src/performance/order_performance.rs | 2 +- .../mod.rs | 0 .../order.rs | 0 .../order_trade.rs | 0 .../performance.rs | 0 .../token.rs | 0 .../transaction.rs | 0 .../vault.rs | 0 .../subgraph/src/types/order_detail_traits.rs | 4 +- crates/subgraph/tests/batch_order_test.rs | 4 +- crates/subgraph/tests/order_test.rs | 4 +- crates/subgraph/tests/order_trade_test.rs | 4 +- crates/subgraph/tests/order_trades_test.rs | 4 +- crates/subgraph/tests/orders_test.rs | 4 +- .../tests/vault_balance_changes_test.rs | 4 +- crates/subgraph/tests/vault_test.rs | 4 +- crates/subgraph/tests/vaults_test.rs | 4 +- crates/test_fixtures/Cargo.toml | 2 +- 170 files changed, 957 insertions(+), 957 deletions(-) rename crates/cli/src/commands/order/{orderbook_address.rs => raindex_address.rs} (98%) rename crates/common/src/local_db/query/{clear_orderbook_data => clear_raindex_data}/mod.rs (100%) rename crates/common/src/local_db/query/{clear_orderbook_data => clear_raindex_data}/query.sql (100%) rename crates/common/src/raindex_client/{orderbook_yaml.rs => raindex_yaml.rs} (99%) rename crates/settings/src/{orderbook.rs => raindex.rs} (66%) rename crates/settings/src/yaml/{orderbook.rs => raindex.rs} (84%) rename crates/subgraph/schema/{orderbook.graphql => raindex.graphql} (100%) rename crates/subgraph/src/{multi_orderbook_client.rs => multi_raindex_client.rs} (100%) rename crates/subgraph/src/{orderbook_client => raindex_client}/mod.rs (100%) rename crates/subgraph/src/{orderbook_client => raindex_client}/order.rs (100%) rename crates/subgraph/src/{orderbook_client => raindex_client}/order_trade.rs (100%) rename crates/subgraph/src/{orderbook_client => raindex_client}/performance.rs (100%) rename crates/subgraph/src/{orderbook_client => raindex_client}/token.rs (100%) rename crates/subgraph/src/{orderbook_client => raindex_client}/transaction.rs (100%) rename crates/subgraph/src/{orderbook_client => raindex_client}/vault.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 2629a1b6e7..e2f1a70c0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6865,14 +6865,14 @@ dependencies = [ ] [[package]] -name = "rain_orderbook_app_settings" +name = "raindex_app_settings" version = "0.0.0-alpha.0" dependencies = [ "alloy", "derive_builder 0.20.2", "futures", "httpmock", - "rain_orderbook_bindings", + "raindex_bindings", "reqwest 0.12.20", "serde", "serde_json", @@ -6885,7 +6885,7 @@ dependencies = [ ] [[package]] -name = "rain_orderbook_bindings" +name = "raindex_bindings" version = "0.0.0-alpha.0" dependencies = [ "alloy", @@ -6899,7 +6899,7 @@ dependencies = [ ] [[package]] -name = "rain_orderbook_cli" +name = "raindex_cli" version = "0.0.0-alpha.0" dependencies = [ "alloy", @@ -6917,12 +6917,12 @@ dependencies = [ "rain-math-float", "rain-metadata 0.0.2-alpha.6", "rain_interpreter_bindings", - "rain_orderbook_app_settings", - "rain_orderbook_bindings", - "rain_orderbook_common", - "rain_orderbook_quote", - "rain_orderbook_subgraph_client", - "rain_orderbook_test_fixtures", + "raindex_app_settings", + "raindex_bindings", + "raindex_common", + "raindex_quote", + "raindex_subgraph_client", + "raindex_test_fixtures", "rusqlite", "rust-bigint", "serde", @@ -6936,7 +6936,7 @@ dependencies = [ ] [[package]] -name = "rain_orderbook_common" +name = "raindex_common" version = "0.0.0-alpha.0" dependencies = [ "alloy", @@ -6965,11 +6965,11 @@ dependencies = [ "rain_interpreter_bindings", "rain_interpreter_dispair", "rain_interpreter_parser", - "rain_orderbook_app_settings", - "rain_orderbook_bindings", - "rain_orderbook_quote", - "rain_orderbook_subgraph_client", - "rain_orderbook_test_fixtures", + "raindex_app_settings", + "raindex_bindings", + "raindex_quote", + "raindex_subgraph_client", + "raindex_test_fixtures", "reqwest 0.12.20", "rusqlite", "serde", @@ -6991,20 +6991,20 @@ dependencies = [ ] [[package]] -name = "rain_orderbook_integration_tests" +name = "raindex_integration_tests" version = "0.0.0-alpha.0" dependencies = [ "alloy", "rain-math-float", - "rain_orderbook_app_settings", - "rain_orderbook_common", - "rain_orderbook_test_fixtures", + "raindex_app_settings", + "raindex_common", + "raindex_test_fixtures", "serde_json", "tokio", ] [[package]] -name = "rain_orderbook_js_api" +name = "raindex_js_api" version = "0.0.0-alpha.0" dependencies = [ "alloy", @@ -7019,11 +7019,11 @@ dependencies = [ "rain-math-float", "rain-metaboard-subgraph", "rain-metadata 0.0.2-alpha.6", - "rain_orderbook_app_settings", - "rain_orderbook_bindings", - "rain_orderbook_common", - "rain_orderbook_quote", - "rain_orderbook_subgraph_client", + "raindex_app_settings", + "raindex_bindings", + "raindex_common", + "raindex_quote", + "raindex_subgraph_client", "reqwest 0.12.20", "serde", "serde_json", @@ -7037,7 +7037,7 @@ dependencies = [ ] [[package]] -name = "rain_orderbook_math" +name = "raindex_math" version = "0.0.0-alpha.0" dependencies = [ "alloy", @@ -7046,7 +7046,7 @@ dependencies = [ ] [[package]] -name = "rain_orderbook_quote" +name = "raindex_quote" version = "0.0.0-alpha.0" dependencies = [ "alloy", @@ -7062,11 +7062,11 @@ dependencies = [ "rain-interpreter-eval", "rain-math-float", "rain-metadata 0.0.2-alpha.6", - "rain_orderbook_app_settings", - "rain_orderbook_bindings", - "rain_orderbook_common", - "rain_orderbook_subgraph_client", - "rain_orderbook_test_fixtures", + "raindex_app_settings", + "raindex_bindings", + "raindex_common", + "raindex_subgraph_client", + "raindex_test_fixtures", "reqwest 0.12.20", "serde", "serde_json", @@ -7081,11 +7081,11 @@ dependencies = [ ] [[package]] -name = "rain_orderbook_rest_api" +name = "raindex_rest_api" version = "0.0.0-alpha.0" dependencies = [ "alloy", - "rain_orderbook_common", + "raindex_common", "rocket", "rocket_cors", "serde", @@ -7097,7 +7097,7 @@ dependencies = [ ] [[package]] -name = "rain_orderbook_subgraph_client" +name = "raindex_subgraph_client" version = "0.0.0-alpha.0" dependencies = [ "alloy", @@ -7110,8 +7110,8 @@ dependencies = [ "insta", "once_cell", "rain-math-float", - "rain_orderbook_bindings", - "rain_orderbook_math", + "raindex_bindings", + "raindex_math", "reqwest 0.12.20", "serde", "serde_json", @@ -7122,7 +7122,7 @@ dependencies = [ ] [[package]] -name = "rain_orderbook_test_fixtures" +name = "raindex_test_fixtures" version = "0.0.0-alpha.0" dependencies = [ "alloy", diff --git a/Cargo.toml b/Cargo.toml index 000360d8ee..3e2df4963f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ resolver = "2" edition = "2021" license = "LicenseRef-DCL-1.0" version = "0.0.0-alpha.0" -homepage = "https://github.com/rainprotocol/rain.orderbook" +homepage = "https://github.com/rainprotocol/raindex" [workspace.dependencies] foundry-block-explorers = "0.2.6" @@ -63,34 +63,34 @@ tower = "0.5.2" getrandom = { version = "0.2", features = ["js"] } itertools = "0.14.0" -[workspace.dependencies.rain_orderbook_bindings] +[workspace.dependencies.raindex_bindings] path = "crates/bindings" -[workspace.dependencies.rain_orderbook_common] +[workspace.dependencies.raindex_common] path = "crates/common" -[workspace.dependencies.rain_orderbook_cli] +[workspace.dependencies.raindex_cli] path = "crates/cli" -[workspace.dependencies.rain_orderbook_subgraph_client] +[workspace.dependencies.raindex_subgraph_client] path = "crates/subgraph" -[workspace.dependencies.rain_orderbook_app_settings] +[workspace.dependencies.raindex_app_settings] path = "crates/settings" -[workspace.dependencies.rain_orderbook_quote] +[workspace.dependencies.raindex_quote] path = "crates/quote" -[workspace.dependencies.rain_orderbook_test_fixtures] +[workspace.dependencies.raindex_test_fixtures] path = "crates/test_fixtures" -[workspace.dependencies.rain_orderbook_math] +[workspace.dependencies.raindex_math] path = "crates/math" -[workspace.dependencies.rain_orderbook_js_api] +[workspace.dependencies.raindex_js_api] path = "crates/js_api" -[workspace.dependencies.rain_orderbook_rest_api] +[workspace.dependencies.raindex_rest_api] path = "crates/rest_api" # release profile for wasm build optimized for size reduction diff --git a/crates/bindings/ARCHITECTURE.md b/crates/bindings/ARCHITECTURE.md index 1cb8c4c4f9..3651861423 100644 --- a/crates/bindings/ARCHITECTURE.md +++ b/crates/bindings/ARCHITECTURE.md @@ -5,7 +5,7 @@ Summary - Scope: ABI-based type generation via Alloy, a read‑only provider builder with multi‑RPC fallback, and WASM interop shims (TypeScript typings + conversions). File Layout -- Cargo.toml: Declares the crate `rain_orderbook_bindings`. Key deps: `alloy` (codegen + types + RPC), `serde` (Serialize/Deserialize), `tower` (layers), `url`, `thiserror`. For WASM builds it uses `wasm-bindgen-utils` and `wasm-bindgen-test` for tests. +- Cargo.toml: Declares the crate `raindex_bindings`. Key deps: `alloy` (codegen + types + RPC), `serde` (Serialize/Deserialize), `tower` (layers), `url`, `thiserror`. For WASM builds it uses `wasm-bindgen-utils` and `wasm-bindgen-test` for tests. - src/lib.rs: Declares contract bindings using Alloy’s `sol!` macro and re‑exports internal modules. Conditionally includes WASM modules. - src/provider.rs: Builds a read‑only provider with multi‑RPC fallback and sensible default request fillers. - src/js_api.rs (wasm only): JS/WASM interop. Implements wasm conversion traits and custom TypeScript interfaces for selected ABI types used in the GUI. @@ -111,10 +111,10 @@ Error Handling - ABI call errors, revert decoding, and multicall aggregation are handled in consumer crates (e.g., `quote`), leveraging these bindings for encoding/decoding. Build and Test -- Build (workspace): `nix develop -c cargo build -p rain_orderbook_bindings`. +- Build (workspace): `nix develop -c cargo build -p raindex_bindings`. - Tests (native and wasm; wasm executed via runner in the flake): - - Native: `nix develop -c cargo test -p rain_orderbook_bindings`. - - WASM: the workspace’s Nix config sets `CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER='wasm-bindgen-test-runner'` and runs `cargo test --target wasm32-unknown-unknown -p rain_orderbook_bindings`. + - Native: `nix develop -c cargo test -p raindex_bindings`. + - WASM: the workspace’s Nix config sets `CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER='wasm-bindgen-test-runner'` and runs `cargo test --target wasm32-unknown-unknown -p raindex_bindings`. Examples - Constructing a read provider and querying via an instance (native): @@ -123,7 +123,7 @@ Examples - Call a view: `let quote = ob.quote2(config).await?;` - Building calldata without an instance: - - `use rain_orderbook_bindings::IOrderBookV5::removeOrder3Call;` + - `use raindex_bindings::IOrderBookV5::removeOrder3Call;` - Construct the struct and encode: `let bytes = removeOrder3Call { order, tasks }.abi_encode();` Limitations and Notes diff --git a/crates/bindings/Cargo.toml b/crates/bindings/Cargo.toml index bce3aef708..c3413923b1 100644 --- a/crates/bindings/Cargo.toml +++ b/crates/bindings/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "rain_orderbook_bindings" -description = "Bindings for the Rain Orderbook Solidity contracts to Rust types." +name = "raindex_bindings" +description = "Bindings for the Raindex Solidity contracts to Rust types." version.workspace = true edition.workspace = true license.workspace = true diff --git a/crates/bindings/src/lib.rs b/crates/bindings/src/lib.rs index 2456622ad6..3e3a6dfc22 100644 --- a/crates/bindings/src/lib.rs +++ b/crates/bindings/src/lib.rs @@ -9,7 +9,7 @@ sol!( sol!( #![sol(all_derives = true)] #![sol(extra_derives(serde::Serialize, serde::Deserialize))] - OrderBook, "../../out/OrderBookV6.sol/OrderBookV6.json" + Raindex, "../../out/RaindexV6.sol/RaindexV6.json" ); // Inline definition avoids non-deterministic artifact collision between @@ -60,11 +60,11 @@ pub mod topics { IRaindexV6::{ AddOrderV3, AfterClearV2, ClearV3, DepositV2, RemoveOrderV3, TakeOrderV3, WithdrawV2, }, - OrderBook::MetaV1_2, + Raindex::MetaV1_2, }; use alloy::{primitives::B256, sol_types::SolEvent}; - pub const ORDERBOOK_EVENT_TOPICS: [B256; 8] = [ + pub const RAINDEX_EVENT_TOPICS: [B256; 8] = [ AddOrderV3::SIGNATURE_HASH, TakeOrderV3::SIGNATURE_HASH, WithdrawV2::SIGNATURE_HASH, diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 69e9e44b46..75ce54d437 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "rain_orderbook_cli" -description = "Rain Orderbook CLI." +name = "raindex_cli" +description = "Raindex CLI." version.workspace = true edition.workspace = true license.workspace = true @@ -11,11 +11,11 @@ homepage.workspace = true [dependencies] alloy-ethers-typecast = { workspace = true } alloy = { workspace = true } -rain_orderbook_subgraph_client = { workspace = true } -rain_orderbook_bindings = { workspace = true } -rain_orderbook_common = { workspace = true } -rain_orderbook_app_settings = { workspace = true } -rain_orderbook_quote = { workspace = true } +raindex_subgraph_client = { workspace = true } +raindex_bindings = { workspace = true } +raindex_common = { workspace = true } +raindex_app_settings = { workspace = true } +raindex_quote = { workspace = true } anyhow = { workspace = true } async-trait = { workspace = true } clap = { workspace = true } @@ -52,4 +52,4 @@ httpmock = "0.7.0" rain-metadata = { workspace = true } rain_interpreter_bindings = { workspace = true } tempfile.workspace = true -rain_orderbook_test_fixtures = { workspace = true } +raindex_test_fixtures = { workspace = true } diff --git a/crates/cli/src/commands/chart.rs b/crates/cli/src/commands/chart.rs index 5116782b23..be60565539 100644 --- a/crates/cli/src/commands/chart.rs +++ b/crates/cli/src/commands/chart.rs @@ -1,7 +1,7 @@ use crate::execute::Execute; use anyhow::{anyhow, Result}; use clap::Args; -use rain_orderbook_common::fuzz::{FuzzRunner, FuzzRunnerContext}; +use raindex_common::fuzz::{FuzzRunner, FuzzRunnerContext}; use std::fs::read_to_string; use std::path::PathBuf; use tracing::info; @@ -31,8 +31,8 @@ impl Execute for Chart { #[cfg(test)] mod tests { use super::*; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_test_fixtures::LocalEvm; use std::io::Write; use tempfile::NamedTempFile; diff --git a/crates/cli/src/commands/local_db/README.md b/crates/cli/src/commands/local_db/README.md index 3a885689d7..1447f42484 100644 --- a/crates/cli/src/commands/local_db/README.md +++ b/crates/cli/src/commands/local_db/README.md @@ -12,7 +12,7 @@ The legacy subcommands in this directory have been replaced by a single orchestr Run the command from the workspace root so the CLI crate is available: ```bash -nix develop -c cargo run -p rain_orderbook_cli -- local-db sync \ +nix develop -c cargo run -p raindex_cli -- local-db sync \ --settings-yaml "https://github.com/rainlanguage/rain.strategies/blob/main/settings.yaml" \ --api-token "$HYPERRPC_TOKEN" \ --release-base-url "https://github.com/rainlanguage/rain.local-db.remote/releases/latest" \ @@ -32,7 +32,7 @@ The runner consumes the same schema as `crates/cli/settings.yaml`: - `local-db-remotes`: map of manifest aliases to URLs; manifests describe previously published dumps that can be used as a bootstrap baseline. - `local-db-sync`: per-network fetch configuration (batch size, concurrency, retry policy, finality depth). -Validation is handled by `rain_orderbook_app_settings`, and missing sections will surface as CLI errors before any network calls are made. +Validation is handled by `raindex_app_settings`, and missing sections will surface as CLI errors before any network calls are made. ## Outputs All artifacts live under `--out-root`: diff --git a/crates/cli/src/commands/local_db/cli.rs b/crates/cli/src/commands/local_db/cli.rs index f1ebef0b71..4f30e2c912 100644 --- a/crates/cli/src/commands/local_db/cli.rs +++ b/crates/cli/src/commands/local_db/cli.rs @@ -2,7 +2,7 @@ use super::pipeline::runner::ProducerRunReport; use crate::commands::local_db::pipeline::runner::ProducerRunner; use anyhow::Result; use clap::Parser; -use rain_orderbook_common::local_db::pipeline::runner::TargetFailure; +use raindex_common::local_db::pipeline::runner::TargetFailure; use std::io::{self, Write}; use std::path::PathBuf; use url::Url; @@ -176,15 +176,15 @@ mod tests { use super::*; use alloy::primitives::{address, Address}; - use rain_orderbook_common::local_db::pipeline::engine::SyncInputs; - use rain_orderbook_common::local_db::pipeline::runner::utils::RunnerTarget; - use rain_orderbook_common::local_db::pipeline::runner::{ + use raindex_common::local_db::pipeline::engine::SyncInputs; + use raindex_common::local_db::pipeline::runner::utils::RunnerTarget; + use raindex_common::local_db::pipeline::runner::{ TargetFailure, TargetStage, TargetSuccess, }; - use rain_orderbook_common::local_db::pipeline::{ + use raindex_common::local_db::pipeline::{ FinalityConfig, SyncConfig, SyncOutcome, WindowOverrides, }; - use rain_orderbook_common::local_db::{FetchConfig, LocalDbError, OrderbookIdentifier}; + use raindex_common::local_db::{FetchConfig, LocalDbError, OrderbookIdentifier}; use std::collections::HashMap; #[test] diff --git a/crates/cli/src/commands/local_db/executor.rs b/crates/cli/src/commands/local_db/executor.rs index 761817f406..c4414c764d 100644 --- a/crates/cli/src/commands/local_db/executor.rs +++ b/crates/cli/src/commands/local_db/executor.rs @@ -1 +1 @@ -pub use rain_orderbook_common::local_db::executor::RusqliteExecutor; +pub use raindex_common::local_db::executor::RusqliteExecutor; diff --git a/crates/cli/src/commands/local_db/pipeline/bootstrap.rs b/crates/cli/src/commands/local_db/pipeline/bootstrap.rs index 03855b52fe..fbb4495b6d 100644 --- a/crates/cli/src/commands/local_db/pipeline/bootstrap.rs +++ b/crates/cli/src/commands/local_db/pipeline/bootstrap.rs @@ -1,4 +1,4 @@ -use rain_orderbook_common::local_db::{ +use raindex_common::local_db::{ pipeline::adapters::bootstrap::{BootstrapConfig, BootstrapPipeline}, query::LocalDbQueryExecutor, LocalDbError, @@ -44,14 +44,14 @@ mod tests { use super::*; use alloy::primitives::Address; use async_trait::async_trait; - use rain_orderbook_app_settings::local_db_manifest::DB_SCHEMA_VERSION; - use rain_orderbook_common::local_db::query::clear_tables::clear_tables_stmt; - use rain_orderbook_common::local_db::query::create_tables::create_tables_stmt; - use rain_orderbook_common::local_db::query::insert_db_metadata::insert_db_metadata_stmt; - use rain_orderbook_common::local_db::query::{ + use raindex_app_settings::local_db_manifest::DB_SCHEMA_VERSION; + use raindex_common::local_db::query::clear_tables::clear_tables_stmt; + use raindex_common::local_db::query::create_tables::create_tables_stmt; + use raindex_common::local_db::query::insert_db_metadata::insert_db_metadata_stmt; + use raindex_common::local_db::query::{ FromDbJson, LocalDbQueryError, LocalDbQueryExecutor, SqlStatement, SqlStatementBatch, }; - use rain_orderbook_common::local_db::OrderbookIdentifier; + use raindex_common::local_db::OrderbookIdentifier; const TEST_BLOCK_NUMBER_THRESHOLD: u32 = 10_000; @@ -73,7 +73,7 @@ mod tests { } fn with_views(self) -> Self { - rain_orderbook_common::local_db::query::create_views::create_views_batch() + raindex_common::local_db::query::create_views::create_views_batch() .statements() .iter() .fold(self, |db, stmt| db.with_text(stmt, "ok")) @@ -171,7 +171,7 @@ mod tests { let calls = db.calls(); let expected_views: Vec = - rain_orderbook_common::local_db::query::create_views::create_views_batch() + raindex_common::local_db::query::create_views::create_views_batch() .statements() .iter() .map(|s| s.sql().to_string()) diff --git a/crates/cli/src/commands/local_db/pipeline/runner/environment.rs b/crates/cli/src/commands/local_db/pipeline/runner/environment.rs index 57e8ab1f0b..b467341d56 100644 --- a/crates/cli/src/commands/local_db/pipeline/runner/environment.rs +++ b/crates/cli/src/commands/local_db/pipeline/runner/environment.rs @@ -1,4 +1,4 @@ -use rain_orderbook_common::local_db::pipeline::{ +use raindex_common::local_db::pipeline::{ adapters::{ apply::DefaultApplyPipeline, events::DefaultEventsPipeline, tokens::DefaultTokensPipeline, window::DefaultWindowPipeline, @@ -59,11 +59,11 @@ pub fn default_environment( mod tests { use super::*; use alloy::primitives::address; - use rain_orderbook_common::local_db::fetch::FetchConfig; - use rain_orderbook_common::local_db::pipeline::engine::SyncInputs; - use rain_orderbook_common::local_db::pipeline::{FinalityConfig, SyncConfig, WindowOverrides}; - use rain_orderbook_common::local_db::{LocalDbError, OrderbookIdentifier}; - use rain_orderbook_common::rpc_client::RpcClientError; + use raindex_common::local_db::fetch::FetchConfig; + use raindex_common::local_db::pipeline::engine::SyncInputs; + use raindex_common::local_db::pipeline::{FinalityConfig, SyncConfig, WindowOverrides}; + use raindex_common::local_db::{LocalDbError, OrderbookIdentifier}; + use raindex_common::rpc_client::RpcClientError; use url::Url; fn sample_target(chain_id: u32) -> RunnerTarget { diff --git a/crates/cli/src/commands/local_db/pipeline/runner/export.rs b/crates/cli/src/commands/local_db/pipeline/runner/export.rs index 58cfa1a33d..dcbf481e72 100644 --- a/crates/cli/src/commands/local_db/pipeline/runner/export.rs +++ b/crates/cli/src/commands/local_db/pipeline/runner/export.rs @@ -2,14 +2,14 @@ use crate::commands::local_db::executor::RusqliteExecutor; use alloy::primitives::hex::encode_prefixed; use flate2::write::GzEncoder; use flate2::Compression; -use rain_orderbook_common::local_db::export::{export_data_only, ExportError}; -use rain_orderbook_common::local_db::pipeline::runner::utils::RunnerTarget; -use rain_orderbook_common::local_db::pipeline::SyncOutcome; -use rain_orderbook_common::local_db::query::fetch_target_watermark::{ +use raindex_common::local_db::export::{export_data_only, ExportError}; +use raindex_common::local_db::pipeline::runner::utils::RunnerTarget; +use raindex_common::local_db::pipeline::SyncOutcome; +use raindex_common::local_db::query::fetch_target_watermark::{ fetch_target_watermark_stmt, TargetWatermarkRow, }; -use rain_orderbook_common::local_db::query::LocalDbQueryExecutor; -use rain_orderbook_common::local_db::LocalDbError; +use raindex_common::local_db::query::LocalDbQueryExecutor; +use raindex_common::local_db::LocalDbError; use std::io::Write; use std::path::{Path, PathBuf}; use tokio::fs::create_dir_all; @@ -73,7 +73,7 @@ mod tests { use super::*; use alloy::primitives::address; use flate2::read::GzDecoder; - use rain_orderbook_common::local_db::{ + use raindex_common::local_db::{ pipeline::{engine::SyncInputs, FinalityConfig, SyncConfig, WindowOverrides}, FetchConfig, OrderbookIdentifier, }; @@ -89,7 +89,7 @@ mod tests { let db_path = temp_dir.path().join("orderbook.sqlite"); let conn = Connection::open(&db_path).expect("open sqlite db"); conn.execute_batch( - rain_orderbook_common::local_db::query::create_tables::CREATE_TABLES_SQL, + raindex_common::local_db::query::create_tables::CREATE_TABLES_SQL, ) .expect("create tables"); @@ -210,7 +210,7 @@ mod tests { let db_path = temp_dir.path().join("orderbook.sqlite"); let conn = Connection::open(&db_path).expect("open sqlite db"); conn.execute_batch( - rain_orderbook_common::local_db::query::create_tables::CREATE_TABLES_SQL, + raindex_common::local_db::query::create_tables::CREATE_TABLES_SQL, ) .expect("create tables"); drop(conn); diff --git a/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs b/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs index 093d61a99b..43bd33b9c6 100644 --- a/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs +++ b/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs @@ -1,10 +1,10 @@ use super::export::ExportMetadata; use alloy::primitives::{Address, Bytes}; -use rain_orderbook_app_settings::local_db_manifest::{LocalDbManifest, ManifestOrderbook}; -use rain_orderbook_app_settings::remote::manifest::ManifestMap; -use rain_orderbook_common::local_db::pipeline::runner::utils::RunnerTarget; -use rain_orderbook_common::local_db::pipeline::runner::TargetSuccess; -use rain_orderbook_common::local_db::{LocalDbError, OrderbookIdentifier}; +use raindex_app_settings::local_db_manifest::{LocalDbManifest, ManifestOrderbook}; +use raindex_app_settings::remote::manifest::ManifestMap; +use raindex_common::local_db::pipeline::runner::utils::RunnerTarget; +use raindex_common::local_db::pipeline::runner::TargetSuccess; +use raindex_common::local_db::{LocalDbError, OrderbookIdentifier}; use std::collections::HashMap; use std::path::Path; use std::str::FromStr; @@ -156,14 +156,14 @@ mod tests { use super::*; use crate::commands::local_db::pipeline::runner::export::ExportMetadata; use alloy::primitives::address; - use rain_orderbook_app_settings::local_db_manifest::{ + use raindex_app_settings::local_db_manifest::{ LocalDbManifest, ManifestNetwork, ManifestOrderbook, DB_SCHEMA_VERSION, MANIFEST_VERSION, }; - use rain_orderbook_common::local_db::pipeline::engine::SyncInputs; - use rain_orderbook_common::local_db::pipeline::{ + use raindex_common::local_db::pipeline::engine::SyncInputs; + use raindex_common::local_db::pipeline::{ FinalityConfig, SyncConfig, SyncOutcome, WindowOverrides, }; - use rain_orderbook_common::local_db::{FetchConfig, OrderbookIdentifier}; + use raindex_common::local_db::{FetchConfig, OrderbookIdentifier}; use std::collections::HashMap; use tempfile::TempDir; diff --git a/crates/cli/src/commands/local_db/pipeline/runner/mod.rs b/crates/cli/src/commands/local_db/pipeline/runner/mod.rs index 21f74857c7..1c6f508ea7 100644 --- a/crates/cli/src/commands/local_db/pipeline/runner/mod.rs +++ b/crates/cli/src/commands/local_db/pipeline/runner/mod.rs @@ -12,15 +12,15 @@ use environment::default_environment; use export::export_dump; pub use export::ExportMetadata; use manifest::{build_manifest, write_manifest_to_path}; -use rain_orderbook_app_settings::local_db_manifest::ManifestOrderbook; -use rain_orderbook_common::local_db::pipeline::adapters::apply::ApplyPipeline; -use rain_orderbook_common::local_db::pipeline::runner::{ +use raindex_app_settings::local_db_manifest::ManifestOrderbook; +use raindex_common::local_db::pipeline::adapters::apply::ApplyPipeline; +use raindex_common::local_db::pipeline::runner::{ environment::RunnerEnvironment, remotes::lookup_manifest_entry, utils::{build_runner_targets, parse_runner_settings, ParsedRunnerSettings, RunnerTarget}, RunReport, TargetFailure, TargetStage, TargetSuccess, }; -use rain_orderbook_common::local_db::pipeline::{ +use raindex_common::local_db::pipeline::{ adapters::{ apply::DefaultApplyPipeline, bootstrap::BootstrapPipeline, events::DefaultEventsPipeline, tokens::DefaultTokensPipeline, window::DefaultWindowPipeline, @@ -28,7 +28,7 @@ use rain_orderbook_common::local_db::pipeline::{ engine::SyncInputs, EventsPipeline, StatusBus, TokensPipeline, WindowPipeline, }; -use rain_orderbook_common::local_db::{LocalDbError, OrderbookIdentifier}; +use raindex_common::local_db::{LocalDbError, OrderbookIdentifier}; use std::collections::HashMap; use std::path::{Path, PathBuf}; use std::sync::Arc; @@ -347,26 +347,26 @@ mod tests { use alloy::primitives::{address, hex::encode_prefixed, Address, Bytes, B256}; use async_trait::async_trait; use flate2::read::GzDecoder; - use rain_orderbook_app_settings::local_db_manifest::{ + use raindex_app_settings::local_db_manifest::{ LocalDbManifest, ManifestNetwork, ManifestOrderbook, DB_SCHEMA_VERSION, MANIFEST_VERSION, }; - use rain_orderbook_app_settings::orderbook::OrderbookCfg; - use rain_orderbook_app_settings::remote::manifest::ManifestMap; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_common::local_db::pipeline::adapters::apply::ApplyPipelineTargetInfo; - use rain_orderbook_common::local_db::pipeline::adapters::bootstrap::{ + use raindex_app_settings::orderbook::OrderbookCfg; + use raindex_app_settings::remote::manifest::ManifestMap; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_common::local_db::pipeline::adapters::apply::ApplyPipelineTargetInfo; + use raindex_common::local_db::pipeline::adapters::bootstrap::{ BootstrapConfig, BootstrapPipeline, BootstrapState, }; - use rain_orderbook_common::local_db::pipeline::runner::environment::{ + use raindex_common::local_db::pipeline::runner::environment::{ DumpFuture, EnginePipelines, ManifestFuture, }; - use rain_orderbook_common::local_db::pipeline::{ + use raindex_common::local_db::pipeline::{ EventsPipeline, StatusBus, SyncPhase, TokensPipeline, WindowPipeline, }; - use rain_orderbook_common::local_db::query::{ + use raindex_common::local_db::query::{ LocalDbQueryExecutor, SqlStatement, SqlStatementBatch, }; - use rain_orderbook_common::local_db::{FetchConfig, LocalDbError}; + use raindex_common::local_db::{FetchConfig, LocalDbError}; use std::collections::HashMap; use std::fs::File; use std::io::Read; @@ -758,7 +758,7 @@ mod tests { &self, _db: &DB, _target: &OrderbookIdentifier, - _cfg: &rain_orderbook_common::local_db::pipeline::SyncConfig, + _cfg: &raindex_common::local_db::pipeline::SyncConfig, _latest_block: u64, ) -> Result<(u64, u64), LocalDbError> where @@ -785,7 +785,7 @@ mod tests { _from_block: u64, _to_block: u64, _cfg: &FetchConfig, - ) -> Result, LocalDbError> + ) -> Result, LocalDbError> { Ok(Vec::new()) } @@ -796,18 +796,18 @@ mod tests { _from_block: u64, _to_block: u64, _cfg: &FetchConfig, - ) -> Result, LocalDbError> + ) -> Result, LocalDbError> { Ok(Vec::new()) } fn decode( &self, - _logs: &[rain_orderbook_common::rpc_client::LogEntryResponse], + _logs: &[raindex_common::rpc_client::LogEntryResponse], ) -> Result< Vec< - rain_orderbook_common::local_db::decode::DecodedEventData< - rain_orderbook_common::local_db::decode::DecodedEvent, + raindex_common::local_db::decode::DecodedEventData< + raindex_common::local_db::decode::DecodedEvent, >, >, LocalDbError, @@ -831,7 +831,7 @@ mod tests { _ob_id: &OrderbookIdentifier, _token_addrs_lower: &[Address], ) -> Result< - Vec, + Vec, LocalDbError, > where @@ -844,7 +844,7 @@ mod tests { &self, _missing: Vec
, _cfg: &FetchConfig, - ) -> Result, LocalDbError> { + ) -> Result, LocalDbError> { Ok(Vec::new()) } } @@ -865,14 +865,14 @@ mod tests { fn build_batch( &self, _target_info: &ApplyPipelineTargetInfo, - _raw_logs: &[rain_orderbook_common::rpc_client::LogEntryResponse], - _decoded_events: &[rain_orderbook_common::local_db::decode::DecodedEventData< - rain_orderbook_common::local_db::decode::DecodedEvent, + _raw_logs: &[raindex_common::rpc_client::LogEntryResponse], + _decoded_events: &[raindex_common::local_db::decode::DecodedEventData< + raindex_common::local_db::decode::DecodedEvent, >], _existing_tokens: &[ - rain_orderbook_common::local_db::query::fetch_erc20_tokens_by_addresses::Erc20TokenRow + raindex_common::local_db::query::fetch_erc20_tokens_by_addresses::Erc20TokenRow ], - _tokens_to_upsert: &[(Address, rain_orderbook_common::erc20::TokenInfo)], + _tokens_to_upsert: &[(Address, raindex_common::erc20::TokenInfo)], ) -> Result { Ok(SqlStatementBatch::new()) } diff --git a/crates/cli/src/commands/local_db/pipeline/status.rs b/crates/cli/src/commands/local_db/pipeline/status.rs index c0c07360b9..1a411942bd 100644 --- a/crates/cli/src/commands/local_db/pipeline/status.rs +++ b/crates/cli/src/commands/local_db/pipeline/status.rs @@ -1,4 +1,4 @@ -use rain_orderbook_common::local_db::{ +use raindex_common::local_db::{ pipeline::{StatusBus, SyncPhase}, LocalDbError, OrderbookIdentifier, }; diff --git a/crates/cli/src/commands/order/add.rs b/crates/cli/src/commands/order/add.rs index 000e5f38a9..5679f77137 100644 --- a/crates/cli/src/commands/order/add.rs +++ b/crates/cli/src/commands/order/add.rs @@ -3,11 +3,11 @@ use crate::{ }; use anyhow::{anyhow, Result}; use clap::{ArgAction, Args}; -use rain_orderbook_app_settings::yaml::dotrain::{DotrainYaml, DotrainYamlValidation}; -use rain_orderbook_app_settings::yaml::YamlParsable; -use rain_orderbook_common::add_order::AddOrderArgs; -use rain_orderbook_common::dotrain::RainDocument; -use rain_orderbook_common::transaction::TransactionArgs; +use raindex_app_settings::yaml::dotrain::{DotrainYaml, DotrainYamlValidation}; +use raindex_app_settings::yaml::YamlParsable; +use raindex_common::add_order::AddOrderArgs; +use raindex_common::dotrain::RainDocument; +use raindex_common::transaction::TransactionArgs; use std::fs::read_to_string; use std::path::PathBuf; use tracing::info; @@ -79,8 +79,8 @@ impl Execute for CliOrderAddArgs { mod tests { use super::*; use alloy::primitives::{address, Address, B256, U256}; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_bindings::IRaindexV6::IOV2; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_bindings::IRaindexV6::IOV2; use std::{collections::HashMap, str::FromStr}; use tempfile::NamedTempFile; diff --git a/crates/cli/src/commands/order/calldata.rs b/crates/cli/src/commands/order/calldata.rs index fec1723b76..ac7677c13e 100644 --- a/crates/cli/src/commands/order/calldata.rs +++ b/crates/cli/src/commands/order/calldata.rs @@ -3,8 +3,8 @@ use crate::output::{output, SupportedOutputEncoding}; use alloy::sol_types::SolCall; use anyhow::{anyhow, Result}; use clap::Parser; -use rain_orderbook_common::add_order::AddOrderArgs; -use rain_orderbook_common::dotrain_order::DotrainOrder; +use raindex_common::add_order::AddOrderArgs; +use raindex_common::dotrain_order::DotrainOrder; use std::fs::read_to_string; use std::path::PathBuf; @@ -75,8 +75,8 @@ mod tests { use rain_interpreter_bindings::Rainlang::{ expressionDeployerAddressCall, interpreterAddressCall, parserAddressCall, storeAddressCall, }; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_app_settings::yaml::{FieldErrorKind, YamlError}; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_app_settings::yaml::{FieldErrorKind, YamlError}; use serde_json::json; use std::io::Write; use std::str::FromStr; diff --git a/crates/cli/src/commands/order/compose.rs b/crates/cli/src/commands/order/compose.rs index 2ecb7725eb..a905f09df7 100644 --- a/crates/cli/src/commands/order/compose.rs +++ b/crates/cli/src/commands/order/compose.rs @@ -2,7 +2,7 @@ use crate::execute::Execute; use crate::output::{output, SupportedOutputEncoding}; use anyhow::{anyhow, Result}; use clap::Args; -use rain_orderbook_common::dotrain_order::DotrainOrder; +use raindex_common::dotrain_order::DotrainOrder; use std::fs::read_to_string; use std::path::PathBuf; @@ -62,7 +62,7 @@ impl Execute for Compose { #[cfg(test)] mod tests { - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::spec_version::SpecVersion; use tempfile::NamedTempFile; use super::*; diff --git a/crates/cli/src/commands/order/detail.rs b/crates/cli/src/commands/order/detail.rs index 025d8c7f2b..eef7b5f0cd 100644 --- a/crates/cli/src/commands/order/detail.rs +++ b/crates/cli/src/commands/order/detail.rs @@ -1,7 +1,7 @@ use crate::{execute::Execute, subgraph::CliSubgraphArgs}; use anyhow::Result; use clap::Args; -use rain_orderbook_common::{subgraph::SubgraphArgs, types::OrderDetailExtended}; +use raindex_common::{subgraph::SubgraphArgs, types::OrderDetailExtended}; use tracing::info; #[derive(Args, Clone)] @@ -32,7 +32,7 @@ mod tests { use super::*; use alloy::{hex::encode_prefixed, primitives::B256, sol_types::SolValue}; use httpmock::MockServer; - use rain_orderbook_bindings::IRaindexV6::{OrderV4, IOV2}; + use raindex_bindings::IRaindexV6::{OrderV4, IOV2}; use serde_json::{json, Value}; #[tokio::test] diff --git a/crates/cli/src/commands/order/list.rs b/crates/cli/src/commands/order/list.rs index 0c9a4ec432..03fef2a529 100644 --- a/crates/cli/src/commands/order/list.rs +++ b/crates/cli/src/commands/order/list.rs @@ -5,7 +5,7 @@ use crate::{ use anyhow::Result; use clap::Args; use comfy_table::Table; -use rain_orderbook_common::{ +use raindex_common::{ csv::TryIntoCsv, subgraph::SubgraphArgs, types::{FlattenError, OrderFlattened, LIST_DELIMITER}, @@ -99,7 +99,7 @@ mod tests { use super::*; use alloy::{hex::encode_prefixed, primitives::B256, sol_types::SolValue}; use httpmock::MockServer; - use rain_orderbook_bindings::IRaindexV6::{OrderV4, IOV2}; + use raindex_bindings::IRaindexV6::{OrderV4, IOV2}; use serde_json::{json, Value}; #[tokio::test] diff --git a/crates/cli/src/commands/order/listorderfrontmatterkeys.rs b/crates/cli/src/commands/order/listorderfrontmatterkeys.rs index 49f46ad936..f1a7d2523e 100644 --- a/crates/cli/src/commands/order/listorderfrontmatterkeys.rs +++ b/crates/cli/src/commands/order/listorderfrontmatterkeys.rs @@ -2,7 +2,7 @@ use crate::execute::Execute; use crate::output::{output, SupportedOutputEncoding}; use anyhow::{anyhow, Result}; use clap::Parser; -use rain_orderbook_common::dotrain_order::DotrainOrder; +use raindex_common::dotrain_order::DotrainOrder; use std::fs::read_to_string; use std::path::PathBuf; @@ -71,7 +71,7 @@ impl Execute for ListOrderFrontmatterKeys { #[cfg(test)] mod tests { use clap::CommandFactory; - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::spec_version::SpecVersion; use std::str::FromStr; use tempfile::NamedTempFile; diff --git a/crates/cli/src/commands/order/mod.rs b/crates/cli/src/commands/order/mod.rs index 356cb24ad7..ef60e2a7c5 100644 --- a/crates/cli/src/commands/order/mod.rs +++ b/crates/cli/src/commands/order/mod.rs @@ -4,10 +4,10 @@ mod compose; mod detail; mod list; mod listorderfrontmatterkeys; -mod orderbook_address; +mod raindex_address; mod remove; -use crate::commands::order::orderbook_address::OrderbookAddress; +use crate::commands::order::raindex_address::RaindexAddress; use crate::execute::Execute; use add::CliOrderAddArgs; use anyhow::Result; @@ -44,10 +44,10 @@ pub enum Order { Calldata(AddOrderCalldata), #[command( - about = "Get the orderbook address for a given order", + about = "Get the raindex address for a given order", alias = "ob-addr" )] - OrderbookAddress(OrderbookAddress), + RaindexAddress(RaindexAddress), #[command(about = "Get frontmatter keys from a dotrain file", alias = "keys")] ListOrderFrontmatterKeys(ListOrderFrontmatterKeys), @@ -62,7 +62,7 @@ impl Execute for Order { Order::Remove(remove) => remove.execute().await, Order::Compose(compose) => compose.execute().await, Order::Calldata(calldata) => calldata.execute().await, - Order::OrderbookAddress(orderbook_address) => orderbook_address.execute().await, + Order::RaindexAddress(raindex_address) => raindex_address.execute().await, Order::ListOrderFrontmatterKeys(keys) => keys.execute().await, } } diff --git a/crates/cli/src/commands/order/orderbook_address.rs b/crates/cli/src/commands/order/raindex_address.rs similarity index 98% rename from crates/cli/src/commands/order/orderbook_address.rs rename to crates/cli/src/commands/order/raindex_address.rs index 9f3855d9c4..793a1f27cc 100644 --- a/crates/cli/src/commands/order/orderbook_address.rs +++ b/crates/cli/src/commands/order/raindex_address.rs @@ -2,7 +2,7 @@ use crate::execute::Execute; use crate::output::{output, SupportedOutputEncoding}; use anyhow::{anyhow, Result}; use clap::Parser; -use rain_orderbook_common::dotrain_order::DotrainOrder; +use raindex_common::dotrain_order::DotrainOrder; use std::fs::read_to_string; use std::path::PathBuf; @@ -65,7 +65,7 @@ impl Execute for OrderbookAddress { mod tests { use super::*; use clap::CommandFactory; - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::spec_version::SpecVersion; use std::str::FromStr; use tempfile::NamedTempFile; diff --git a/crates/cli/src/commands/order/remove.rs b/crates/cli/src/commands/order/remove.rs index 80f7c56b85..2200842a97 100644 --- a/crates/cli/src/commands/order/remove.rs +++ b/crates/cli/src/commands/order/remove.rs @@ -4,9 +4,9 @@ use crate::{ }; use anyhow::Result; use clap::Args; -use rain_orderbook_common::remove_order::RemoveOrderArgs; -use rain_orderbook_common::subgraph::SubgraphArgs; -use rain_orderbook_common::transaction::TransactionArgs; +use raindex_common::remove_order::RemoveOrderArgs; +use raindex_common::subgraph::SubgraphArgs; +use raindex_common::transaction::TransactionArgs; use tracing::info; #[derive(Args, Clone)] diff --git a/crates/cli/src/commands/quote/mod.rs b/crates/cli/src/commands/quote/mod.rs index 8e05ee65a9..06264c27c5 100644 --- a/crates/cli/src/commands/quote/mod.rs +++ b/crates/cli/src/commands/quote/mod.rs @@ -1,5 +1,5 @@ use crate::execute::Execute; -use rain_orderbook_quote::cli::Quoter; +use raindex_quote::cli::Quoter; impl Execute for Quoter { async fn execute(&self) -> anyhow::Result<()> { diff --git a/crates/cli/src/commands/subgraph/mod.rs b/crates/cli/src/commands/subgraph/mod.rs index 99b7e8cf1d..148f0f046e 100644 --- a/crates/cli/src/commands/subgraph/mod.rs +++ b/crates/cli/src/commands/subgraph/mod.rs @@ -1,7 +1,7 @@ use crate::execute::Execute; use anyhow::Result; use clap::Parser; -use rain_orderbook_subgraph_client::validate::validate_subgraph_schema; +use raindex_subgraph_client::validate::validate_subgraph_schema; #[derive(Parser)] pub enum Subgraph { diff --git a/crates/cli/src/commands/trade/detail.rs b/crates/cli/src/commands/trade/detail.rs index a4916812f5..9bd05a4551 100644 --- a/crates/cli/src/commands/trade/detail.rs +++ b/crates/cli/src/commands/trade/detail.rs @@ -2,7 +2,7 @@ use crate::{execute::Execute, subgraph::CliSubgraphArgs}; use anyhow::Result; use clap::Args; -use rain_orderbook_common::subgraph::SubgraphArgs; +use raindex_common::subgraph::SubgraphArgs; use tracing::info; diff --git a/crates/cli/src/commands/trade/list.rs b/crates/cli/src/commands/trade/list.rs index 5f413db762..93e61f9503 100644 --- a/crates/cli/src/commands/trade/list.rs +++ b/crates/cli/src/commands/trade/list.rs @@ -5,7 +5,7 @@ use crate::{ use anyhow::Result; use clap::Args; use comfy_table::Table; -use rain_orderbook_common::{ +use raindex_common::{ csv::TryIntoCsv, subgraph::SubgraphArgs, types::{FlattenError, OrderTakeFlattened, NO_SYMBOL}, @@ -98,7 +98,7 @@ mod tests { primitives::{Address, B256}, }; use httpmock::MockServer; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; use serde_json::{json, Value}; #[tokio::test] diff --git a/crates/cli/src/commands/vault/deposit.rs b/crates/cli/src/commands/vault/deposit.rs index 16cbecf547..0be13ae3aa 100644 --- a/crates/cli/src/commands/vault/deposit.rs +++ b/crates/cli/src/commands/vault/deposit.rs @@ -5,7 +5,7 @@ use alloy::primitives::{Address, B256, U256}; use anyhow::Result; use clap::Args; use rain_math_float::Float; -use rain_orderbook_common::{deposit::DepositArgs, erc20::ERC20, transaction::TransactionArgs}; +use raindex_common::{deposit::DepositArgs, erc20::ERC20, transaction::TransactionArgs}; use tracing::info; #[derive(Args, Clone)] diff --git a/crates/cli/src/commands/vault/detail.rs b/crates/cli/src/commands/vault/detail.rs index b218e1efed..258760b628 100644 --- a/crates/cli/src/commands/vault/detail.rs +++ b/crates/cli/src/commands/vault/detail.rs @@ -1,7 +1,7 @@ use crate::{execute::Execute, subgraph::CliSubgraphArgs}; use anyhow::Result; use clap::Args; -use rain_orderbook_common::subgraph::SubgraphArgs; +use raindex_common::subgraph::SubgraphArgs; use tracing::info; #[derive(Args, Clone)] diff --git a/crates/cli/src/commands/vault/list.rs b/crates/cli/src/commands/vault/list.rs index 40aced8580..43b7042342 100644 --- a/crates/cli/src/commands/vault/list.rs +++ b/crates/cli/src/commands/vault/list.rs @@ -5,12 +5,12 @@ use crate::{ use anyhow::Result; use clap::Args; use comfy_table::Table; -use rain_orderbook_common::{ +use raindex_common::{ csv::TryIntoCsv, subgraph::SubgraphArgs, types::{FlattenError, TokenVaultFlattened, NO_SYMBOL}, }; -use rain_orderbook_subgraph_client::SgPaginationArgs; +use raindex_subgraph_client::SgPaginationArgs; use tracing::info; #[derive(Args, Clone)] @@ -92,7 +92,7 @@ mod tests { primitives::{Address, B256}, }; use httpmock::MockServer; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; use serde_json::{json, Value}; #[tokio::test] diff --git a/crates/cli/src/commands/vault/list_balance_changes.rs b/crates/cli/src/commands/vault/list_balance_changes.rs index 45871260f2..856e3e5b68 100644 --- a/crates/cli/src/commands/vault/list_balance_changes.rs +++ b/crates/cli/src/commands/vault/list_balance_changes.rs @@ -5,7 +5,7 @@ use crate::{ use anyhow::Result; use clap::Args; use comfy_table::Table; -use rain_orderbook_common::{ +use raindex_common::{ csv::TryIntoCsv, subgraph::SubgraphArgs, types::{FlattenError, VaultBalanceChangeFlattened}, @@ -93,7 +93,7 @@ mod tests { primitives::{Address, B256}, }; use httpmock::MockServer; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; use serde_json::{json, Value}; #[tokio::test] diff --git a/crates/cli/src/commands/vault/withdraw.rs b/crates/cli/src/commands/vault/withdraw.rs index 5f7eefec9a..2e92f02a3b 100644 --- a/crates/cli/src/commands/vault/withdraw.rs +++ b/crates/cli/src/commands/vault/withdraw.rs @@ -4,8 +4,8 @@ use alloy::primitives::{Address, B256}; use anyhow::Result; use clap::Args; use rain_math_float::{Float, FloatError}; -use rain_orderbook_common::transaction::TransactionArgs; -use rain_orderbook_common::withdraw::WithdrawArgs; +use raindex_common::transaction::TransactionArgs; +use raindex_common::withdraw::WithdrawArgs; use tracing::info; #[derive(Args, Clone)] diff --git a/crates/cli/src/commands/words.rs b/crates/cli/src/commands/words.rs index ee2de34f32..9392d476d7 100644 --- a/crates/cli/src/commands/words.rs +++ b/crates/cli/src/commands/words.rs @@ -2,7 +2,7 @@ use crate::execute::Execute; use anyhow::{anyhow, Result}; use clap::{ArgAction, Args, Parser}; use csv::Writer; -use rain_orderbook_common::dotrain_order::{AuthoringMetaV2, DotrainOrder, WordsResult}; +use raindex_common::dotrain_order::{AuthoringMetaV2, DotrainOrder, WordsResult}; use std::{fs::read_to_string, path::PathBuf}; /// Get words of a rainlang contract from the given inputs @@ -225,7 +225,7 @@ mod tests { use clap::CommandFactory; use httpmock::MockServer; use rain_metadata::{KnownMagic, RainMetaDocumentV1Item}; - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::spec_version::SpecVersion; use serde_bytes::ByteBuf; use serde_json::json; use tempfile::NamedTempFile; diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index eba89a4991..9e65022a35 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -3,7 +3,7 @@ use crate::execute::Execute; use anyhow::Result; use clap::Subcommand; use commands::local_db::LocalDbCommands; -use rain_orderbook_quote::cli::Quoter; +use raindex_quote::cli::Quoter; mod commands; mod execute; diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 182a663540..a2129528a8 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -1,6 +1,6 @@ use anyhow::Result; use clap::Parser; -use rain_orderbook_cli::Orderbook; +use raindex_cli::Orderbook; use tracing_subscriber::filter::{EnvFilter, LevelFilter}; #[derive(Parser)] diff --git a/crates/cli/src/subgraph.rs b/crates/cli/src/subgraph.rs index feeee60f99..afd670a75b 100644 --- a/crates/cli/src/subgraph.rs +++ b/crates/cli/src/subgraph.rs @@ -1,6 +1,6 @@ use clap::Args; -use rain_orderbook_common::subgraph::SubgraphArgs; -use rain_orderbook_subgraph_client::{ +use raindex_common::subgraph::SubgraphArgs; +use raindex_subgraph_client::{ types::common::{ SgBytes, SgOrdersListFilterArgs, SgOrdersTokensFilterArgs, SgVaultsListFilterArgs, }, diff --git a/crates/cli/src/transaction.rs b/crates/cli/src/transaction.rs index f79aff7546..ad4d922606 100644 --- a/crates/cli/src/transaction.rs +++ b/crates/cli/src/transaction.rs @@ -1,6 +1,6 @@ use alloy::primitives::Address; use clap::Args; -use rain_orderbook_common::transaction::TransactionArgs; +use raindex_common::transaction::TransactionArgs; #[derive(Args, Clone)] pub struct CliTransactionArgs { diff --git a/crates/common/ARCHITECTURE.md b/crates/common/ARCHITECTURE.md index 8c0c382d04..2e12e7bfec 100644 --- a/crates/common/ARCHITECTURE.md +++ b/crates/common/ARCHITECTURE.md @@ -1,4 +1,4 @@ -# rain_orderbook_common — Architecture & Reference +# raindex_common — Architecture & Reference This crate provides the shared core for the Rain Orderbook toolchain across native (CLI, services) and WebAssembly (browser) targets. It bundles higher‑level orchestration around: @@ -41,7 +41,7 @@ Target gating is used extensively: ## Key Data Flow & Responsibilities ### 1) DOTRAIN → Rainlang → Bytecode (add_order) -- Inputs: DOTRAIN (YAML frontmatter + Rainlang sections), selected scenario/deployment (from `rain_orderbook_app_settings`), and bindings. +- Inputs: DOTRAIN (YAML frontmatter + Rainlang sections), selected scenario/deployment (from `raindex_app_settings`), and bindings. - `AddOrderArgs::compose_to_rainlang` uses `rainlang::compose_to_rainlang` to produce the Rainlang snippet for order entrypoints (`calculate-io`, `handle-io`). - Parser address is discovered via `DISPair::from_deployer`; the Rainlang text is parsed by `ParserV2::parse_text` over provided RPCs to produce bytecode. - Metadata is generated as a Rain Meta V1 document containing `RainlangSourceV1` and CBOR‑encoded with `rain-metadata`. @@ -200,10 +200,10 @@ Where functionality cannot run in WASM, equivalent calldata generation methods a ## Notable Dependencies (workspace crates) -- `rain_orderbook_bindings` — Strongly‑typed ABI for Orderbook and ERC20 contracts (`addOrder3`, `removeOrder3`, `deposit3`, `withdraw3`, multicall). -- `rain_orderbook_subgraph_client` — GraphQL types and clients for orderbook data; provides `Sg*` models and helpers. -- `rain_orderbook_app_settings` — DOTRAIN/orderbook YAML structures, validation, and spec versioning. -- `rain_orderbook_quote` — Batch quote engine for orders. +- `raindex_bindings` — Strongly‑typed ABI for Orderbook and ERC20 contracts (`addOrder3`, `removeOrder3`, `deposit3`, `withdraw3`, multicall). +- `raindex_subgraph_client` — GraphQL types and clients for orderbook data; provides `Sg*` models and helpers. +- `raindex_app_settings` — DOTRAIN/orderbook YAML structures, validation, and spec versioning. +- `raindex_quote` — Batch quote engine for orders. - `rain_interpreter_*` — Parser, eval, DISP pair, bindings used to compile/evaluate Rainlang. - `rain_metadata` — CBOR‑encoded metadata with magic prefixes; used to embed Rainlang source. - `rain_error_decoding` — ABI error decoding to readable types/names. diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml index a5c1cebc53..699c73d85a 100644 --- a/crates/common/Cargo.toml +++ b/crates/common/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "rain_orderbook_common" -description = "Rain Orderbook CLI." +name = "raindex_common" +description = "Raindex CLI." version.workspace = true edition.workspace = true license.workspace = true @@ -16,10 +16,10 @@ browser-tests = [] crate-type = ["rlib", "cdylib"] [dependencies] -rain_orderbook_bindings = { workspace = true } -rain_orderbook_subgraph_client = { workspace = true } -rain_orderbook_app_settings = { workspace = true } -rain_orderbook_quote = { workspace = true } +raindex_bindings = { workspace = true } +raindex_subgraph_client = { workspace = true } +raindex_app_settings = { workspace = true } +raindex_quote = { workspace = true } alloy = { workspace = true, features = ["dyn-abi", "rand"] } alloy-ethers-typecast = { workspace = true } url = { workspace = true } @@ -77,5 +77,5 @@ wasm-bindgen-futures = "0.4" [target.'cfg(not(target_family = "wasm"))'.dev-dependencies] httpmock = "0.7.0" -rain_orderbook_test_fixtures = { workspace = true } +raindex_test_fixtures = { workspace = true } tempfile = "3" diff --git a/crates/common/src/add_order.rs b/crates/common/src/add_order.rs index d366fdc260..bd364d333c 100644 --- a/crates/common/src/add_order.rs +++ b/crates/common/src/add_order.rs @@ -32,8 +32,8 @@ use rain_metadata::{ ContentLanguage, ContentType, Error as RainMetaError, KnownMagic, RainMetaDocumentV1Item, }; use rain_metadata_bindings::MetaBoard::emitMetaCall; -use rain_orderbook_app_settings::deployment::DeploymentCfg; -use rain_orderbook_bindings::IRaindexV6::{ +use raindex_app_settings::deployment::DeploymentCfg; +use raindex_bindings::IRaindexV6::{ addOrder4Call, EvaluableV4, OrderConfigV4, TaskV2, IOV2, }; use serde::{Deserialize, Serialize}; @@ -472,7 +472,7 @@ mod tests { use rain_metadata::{ types::dotrain::source_v1::DotrainSourceV1, Error as RainMetaError, KnownMagic, }; - use rain_orderbook_app_settings::{ + use raindex_app_settings::{ network::NetworkCfg, order::{OrderCfg, OrderIOCfg}, rainlang::RainlangCfg, @@ -481,7 +481,7 @@ mod tests { token::TokenCfg, yaml::{default_document, default_documents}, }; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_test_fixtures::LocalEvm; use std::{ collections::BTreeMap, str::FromStr, diff --git a/crates/common/src/deposit.rs b/crates/common/src/deposit.rs index f49e997cf5..4649f0ad4d 100644 --- a/crates/common/src/deposit.rs +++ b/crates/common/src/deposit.rs @@ -8,8 +8,8 @@ use alloy_ethers_typecast::{ use alloy_ethers_typecast::{WriteTransaction, WriteTransactionStatus}; use rain_math_float::{Float, FloatError}; #[cfg(not(target_family = "wasm"))] -use rain_orderbook_bindings::IERC20::approveCall; -use rain_orderbook_bindings::{IRaindexV6::deposit4Call, IERC20::allowanceCall}; +use raindex_bindings::IERC20::approveCall; +use raindex_bindings::{IRaindexV6::deposit4Call, IERC20::allowanceCall}; use serde::{Deserialize, Serialize}; use thiserror::Error; diff --git a/crates/common/src/dotrain_add_order_lsp.rs b/crates/common/src/dotrain_add_order_lsp.rs index 98fe16d42f..053f546290 100644 --- a/crates/common/src/dotrain_add_order_lsp.rs +++ b/crates/common/src/dotrain_add_order_lsp.rs @@ -123,8 +123,8 @@ impl DotrainAddOrderLsp { #[cfg(all(test, not(target_family = "wasm")))] mod tests { use super::*; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_test_fixtures::LocalEvm; use url::Url; fn get_text() -> String { diff --git a/crates/common/src/dotrain_order.rs b/crates/common/src/dotrain_order.rs index b1e3a0416c..99328aaab8 100644 --- a/crates/common/src/dotrain_order.rs +++ b/crates/common/src/dotrain_order.rs @@ -8,16 +8,16 @@ use dotrain::{error::ComposeError, types::patterns::FRONTMATTER_SEPARATOR, RainD use futures::future::join_all; use rain_interpreter_parser::{Parser2, ParserError, ParserV2}; pub use rain_metadata::types::authoring::v2::*; -use rain_orderbook_app_settings::yaml::{ +use raindex_app_settings::yaml::{ clone_section_entry, context::ContextProfile, dotrain::DotrainYaml, orderbook::OrderbookYaml, FieldErrorKind, YamlError, YamlParsable, }; -use rain_orderbook_app_settings::{ +use raindex_app_settings::{ remote_networks::ParseRemoteNetworksError, remote_tokens::ParseRemoteTokensError, yaml::{dotrain::DotrainYamlValidation, orderbook::OrderbookYamlValidation}, }; -use rain_orderbook_app_settings::{scenario::ScenarioCfg, spec_version::SpecVersion}; +use raindex_app_settings::{scenario::ScenarioCfg, spec_version::SpecVersion}; use serde::{Deserialize, Serialize}; use std::sync::{Arc, RwLock}; use strict_yaml_rust::{strict_yaml::Hash as StrictYamlHash, StrictYaml, StrictYamlLoader}; @@ -867,7 +867,7 @@ mod tests { use alloy::{hex::encode_prefixed, primitives::B256, sol, sol_types::SolValue}; use httpmock::MockServer; use rain_metadata::{KnownMagic, RainMetaDocumentV1Item}; - use rain_orderbook_app_settings::yaml::FieldErrorKind; + use raindex_app_settings::yaml::FieldErrorKind; use serde_bytes::ByteBuf; use serde_json::json; use strict_yaml_rust::{strict_yaml::Hash as StrictYamlHash, StrictYaml, StrictYamlLoader}; diff --git a/crates/common/src/erc20.rs b/crates/common/src/erc20.rs index 20c5ff36df..1444e85f97 100644 --- a/crates/common/src/erc20.rs +++ b/crates/common/src/erc20.rs @@ -3,9 +3,9 @@ use alloy::primitives::{Address, U256}; use alloy::providers::{MulticallError, Provider}; use alloy_ethers_typecast::ReadContractParametersBuilderError; use rain_error_decoding::{AbiDecodeFailedErrors, AbiDecodedErrorType}; -use rain_orderbook_app_settings::token::TokenCfg; -use rain_orderbook_bindings::provider::{mk_read_provider, ReadProvider, ReadProviderError}; -use rain_orderbook_bindings::IERC20Metadata::IERC20MetadataInstance; +use raindex_app_settings::token::TokenCfg; +use raindex_bindings::provider::{mk_read_provider, ReadProvider, ReadProviderError}; +use raindex_bindings::IERC20Metadata::IERC20MetadataInstance; use serde::{Deserialize, Serialize}; use serde_json::Value; use std::collections::HashMap; @@ -251,7 +251,7 @@ mod tests { use super::*; use alloy::{hex, sol_types::SolValue}; use httpmock::MockServer; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_test_fixtures::LocalEvm; use serde_json::json; #[tokio::test] diff --git a/crates/common/src/fuzz/impls.rs b/crates/common/src/fuzz/impls.rs index 2f5019ad91..ac5740c441 100644 --- a/crates/common/src/fuzz/impls.rs +++ b/crates/common/src/fuzz/impls.rs @@ -21,14 +21,14 @@ use rain_interpreter_eval::eval::ForkParseArgs; use rain_interpreter_eval::fork::{Forker, NewForkedEvm}; pub use rain_interpreter_eval::trace::{RainEvalResult, RainEvalResults, TraceSearchError}; use rain_interpreter_eval::{error::ForkCallError, eval::ForkEvalArgs}; -use rain_orderbook_app_settings::blocks::BlockError; -use rain_orderbook_app_settings::scenario::ScenarioCfg; -use rain_orderbook_app_settings::yaml::dotrain::DotrainYamlValidation; -use rain_orderbook_app_settings::{ +use raindex_app_settings::blocks::BlockError; +use raindex_app_settings::scenario::ScenarioCfg; +use raindex_app_settings::yaml::dotrain::DotrainYamlValidation; +use raindex_app_settings::{ order::OrderIOCfg, yaml::{dotrain::DotrainYaml, YamlError, YamlParsable}, }; -use rain_orderbook_bindings::IERC20Metadata; +use raindex_bindings::IERC20Metadata; use std::collections::HashMap; use std::sync::Arc; use thiserror::Error; @@ -731,8 +731,8 @@ impl FuzzRunner { mod tests { use super::*; use alloy::providers::{ext::AnvilApi, Provider}; - use rain_orderbook_app_settings::{spec_version::SpecVersion, yaml::FieldErrorKind}; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_app_settings::{spec_version::SpecVersion, yaml::FieldErrorKind}; + use raindex_test_fixtures::LocalEvm; #[tokio::test(flavor = "multi_thread", worker_threads = 10)] async fn test_fuzz_runner_missing_spec_version() { diff --git a/crates/common/src/fuzz/mod.rs b/crates/common/src/fuzz/mod.rs index bc7a0233e3..bf03ffabf9 100644 --- a/crates/common/src/fuzz/mod.rs +++ b/crates/common/src/fuzz/mod.rs @@ -1,5 +1,5 @@ pub use rain_interpreter_eval::trace::*; -use rain_orderbook_app_settings::chart::ChartCfg; +use raindex_app_settings::chart::ChartCfg; use serde::{Deserialize, Serialize}; use std::collections::HashMap; diff --git a/crates/common/src/local_db/address_collectors.rs b/crates/common/src/local_db/address_collectors.rs index 7ea765fbea..a6c42e0504 100644 --- a/crates/common/src/local_db/address_collectors.rs +++ b/crates/common/src/local_db/address_collectors.rs @@ -1,6 +1,6 @@ use super::decode::{DecodedEvent, DecodedEventData}; use alloy::primitives::Address; -use rain_orderbook_bindings::IRaindexV6::OrderV4; +use raindex_bindings::IRaindexV6::OrderV4; use std::collections::BTreeSet; pub fn collect_token_addresses( @@ -67,8 +67,8 @@ mod tests { use super::super::decode::InterpreterStoreSetEvent; use super::*; use alloy::primitives::{b256, Address, Bytes, FixedBytes, U256}; - use rain_orderbook_bindings::IInterpreterStoreV3::Set; - use rain_orderbook_bindings::IRaindexV6::{ + use raindex_bindings::IInterpreterStoreV3::Set; + use raindex_bindings::IRaindexV6::{ AddOrderV3, DepositV2, OrderV4, RemoveOrderV3, SignedContextV1, TakeOrderConfigV4, TakeOrderV3, WithdrawV2, IOV2, }; @@ -90,7 +90,7 @@ mod tests { OrderV4 { owner: Address::from([1u8; 20]), nonce: U256::from(1).into(), - evaluable: rain_orderbook_bindings::IRaindexV6::EvaluableV4 { + evaluable: raindex_bindings::IRaindexV6::EvaluableV4 { interpreter: Address::from([2u8; 20]), store: Address::from([3u8; 20]), bytecode: alloy::primitives::Bytes::from(vec![]), @@ -172,11 +172,11 @@ mod tests { vaultId: U256::from(0).into(), }); - let clear = rain_orderbook_bindings::IRaindexV6::ClearV3 { + let clear = raindex_bindings::IRaindexV6::ClearV3 { sender: Address::from([0u8; 20]), alice, bob, - clearConfig: rain_orderbook_bindings::IRaindexV6::ClearConfigV2 { + clearConfig: raindex_bindings::IRaindexV6::ClearConfigV2 { aliceInputIOIndex: U256::from(0), aliceOutputIOIndex: U256::from(0), bobInputIOIndex: U256::from(0), diff --git a/crates/common/src/local_db/decode.rs b/crates/common/src/local_db/decode.rs index 51e4581c93..7ac55e0584 100644 --- a/crates/common/src/local_db/decode.rs +++ b/crates/common/src/local_db/decode.rs @@ -5,7 +5,7 @@ use alloy::{ sol_types::{abi::token::WordToken, SolEvent}, }; use core::convert::TryFrom; -use rain_orderbook_bindings::{ +use raindex_bindings::{ IInterpreterStoreV3::Set, IRaindexV6::{ AddOrderV3, AfterClearV2, ClearV3, DepositV2, RemoveOrderV3, TakeOrderV3, WithdrawV2, @@ -209,7 +209,7 @@ mod test_helpers { use crate::rpc_client::LogEntryResponse; use alloy::hex; use alloy::primitives::{address, b256, Address, Bytes, FixedBytes, B256, U256}; - use rain_orderbook_bindings::{ + use raindex_bindings::{ IRaindexV6::{ AddOrderV3, AfterClearV2, ClearConfigV2, ClearStateChangeV2, ClearV3, DepositV2, RemoveOrderV3, SignedContextV1, TakeOrderConfigV4, TakeOrderV3, WithdrawV2, diff --git a/crates/common/src/local_db/fetch.rs b/crates/common/src/local_db/fetch.rs index cb35b7de70..22b968e7ea 100644 --- a/crates/common/src/local_db/fetch.rs +++ b/crates/common/src/local_db/fetch.rs @@ -6,7 +6,7 @@ use crate::{ use alloy::primitives::{Address, U256}; use alloy::rpc::types::Filter; use futures::{StreamExt, TryStreamExt}; -use rain_orderbook_bindings::topics::{ORDERBOOK_EVENT_TOPICS, STORE_SET_TOPICS}; +use raindex_bindings::topics::{ORDERBOOK_EVENT_TOPICS, STORE_SET_TOPICS}; use std::collections::{HashMap, HashSet}; use thiserror::Error; @@ -443,7 +443,7 @@ mod tests { use alloy::rpc::types::FilterBlockError; use alloy::sol_types::SolEvent; use httpmock::prelude::*; - use rain_orderbook_bindings::{IInterpreterStoreV3::Set, IRaindexV6::AddOrderV3}; + use raindex_bindings::{IInterpreterStoreV3::Set, IRaindexV6::AddOrderV3}; use serde_json::json; use std::str::FromStr; use std::sync::atomic::{AtomicUsize, Ordering}; diff --git a/crates/common/src/local_db/insert.rs b/crates/common/src/local_db/insert.rs index b2a62ca97d..221bc9f77a 100644 --- a/crates/common/src/local_db/insert.rs +++ b/crates/common/src/local_db/insert.rs @@ -10,11 +10,11 @@ use alloy::{ }; use itertools::Itertools; use rain_math_float::Float; -use rain_orderbook_bindings::IRaindexV6::{ +use raindex_bindings::IRaindexV6::{ AddOrderV3, AfterClearV2, ClearV3, DepositV2, OrderV4, RemoveOrderV3, TakeOrderV3, WithdrawV2, IOV2, }; -use rain_orderbook_bindings::OrderBook::MetaV1_2; +use raindex_bindings::OrderBook::MetaV1_2; use std::collections::HashMap; use std::convert::TryInto; use thiserror::Error; @@ -967,8 +967,8 @@ mod tests { use crate::rpc_client::LogEntryResponse; use alloy::hex; use alloy::primitives::{address, b256, Address, Bytes, FixedBytes, B256, U256}; - use rain_orderbook_bindings::IInterpreterStoreV3::Set; - use rain_orderbook_bindings::IRaindexV6::{ + use raindex_bindings::IInterpreterStoreV3::Set; + use raindex_bindings::IRaindexV6::{ ClearConfigV2, ClearStateChangeV2, EvaluableV4, SignedContextV1, TakeOrderConfigV4, }; use std::collections::HashMap; diff --git a/crates/common/src/local_db/mod.rs b/crates/common/src/local_db/mod.rs index 6ecc106a22..212528ced3 100644 --- a/crates/common/src/local_db/mod.rs +++ b/crates/common/src/local_db/mod.rs @@ -20,8 +20,8 @@ use decode::DecodeError; pub use fetch::{FetchConfig, FetchConfigError}; use insert::InsertError; use query::{LocalDbQueryError, SqlBuildError}; -use rain_orderbook_app_settings::remote::manifest::FetchManifestError; -use rain_orderbook_app_settings::yaml::YamlError; +use raindex_app_settings::remote::manifest::FetchManifestError; +use raindex_app_settings::yaml::YamlError; use serde::{Deserialize, Serialize}; use std::array::TryFromSliceError; use std::num::ParseIntError; diff --git a/crates/common/src/local_db/pipeline/adapters/apply.rs b/crates/common/src/local_db/pipeline/adapters/apply.rs index a62656011e..c3ca3cbc45 100644 --- a/crates/common/src/local_db/pipeline/adapters/apply.rs +++ b/crates/common/src/local_db/pipeline/adapters/apply.rs @@ -227,7 +227,7 @@ mod tests { fn deposit_event(addr: Address) -> DecodedEventData { use crate::local_db::decode::EventType; - use rain_orderbook_bindings::IRaindexV6::DepositV2; + use raindex_bindings::IRaindexV6::DepositV2; DecodedEventData { event_type: EventType::DepositV2, block_number: U256::from(1), @@ -247,7 +247,7 @@ mod tests { fn withdraw_event(addr: Address) -> DecodedEventData { use crate::local_db::decode::EventType; - use rain_orderbook_bindings::IRaindexV6::WithdrawV2; + use raindex_bindings::IRaindexV6::WithdrawV2; DecodedEventData { event_type: EventType::WithdrawV2, block_number: U256::from(0x10), diff --git a/crates/common/src/local_db/pipeline/adapters/bootstrap.rs b/crates/common/src/local_db/pipeline/adapters/bootstrap.rs index 74482ff0b9..e92d35f12f 100644 --- a/crates/common/src/local_db/pipeline/adapters/bootstrap.rs +++ b/crates/common/src/local_db/pipeline/adapters/bootstrap.rs @@ -13,7 +13,7 @@ use crate::local_db::query::{LocalDbQueryExecutor, SqlStatementBatch}; use crate::local_db::LocalDbError; use crate::local_db::OrderbookIdentifier; use async_trait::async_trait; -use rain_orderbook_app_settings::local_db_manifest::DB_SCHEMA_VERSION; +use raindex_app_settings::local_db_manifest::DB_SCHEMA_VERSION; use std::collections::HashSet; #[derive(Debug, Clone)] diff --git a/crates/common/src/local_db/pipeline/adapters/events.rs b/crates/common/src/local_db/pipeline/adapters/events.rs index ab0c71c1d8..a75ab5c8c5 100644 --- a/crates/common/src/local_db/pipeline/adapters/events.rs +++ b/crates/common/src/local_db/pipeline/adapters/events.rs @@ -93,7 +93,7 @@ mod tests { use alloy::primitives::{b256, Bytes, U256}; use alloy::sol_types::SolEvent; use httpmock::MockServer; - use rain_orderbook_bindings::OrderBook::MetaV1_2; + use raindex_bindings::OrderBook::MetaV1_2; use serde_json::json; use std::str::FromStr; diff --git a/crates/common/src/local_db/pipeline/adapters/tokens.rs b/crates/common/src/local_db/pipeline/adapters/tokens.rs index f83c4464ea..d6a54b2a38 100644 --- a/crates/common/src/local_db/pipeline/adapters/tokens.rs +++ b/crates/common/src/local_db/pipeline/adapters/tokens.rs @@ -298,7 +298,7 @@ mod tests { mod non_wasm_tests { use super::*; use alloy::primitives::Address; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_test_fixtures::LocalEvm; #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn fetch_missing_delegates_to_concurrent_fetcher() { diff --git a/crates/common/src/local_db/pipeline/engine.rs b/crates/common/src/local_db/pipeline/engine.rs index 804a8be53f..3e3bc681a9 100644 --- a/crates/common/src/local_db/pipeline/engine.rs +++ b/crates/common/src/local_db/pipeline/engine.rs @@ -366,7 +366,7 @@ mod tests { use crate::local_db::FetchConfig; use alloy::primitives::{b256, Address, Bytes, FixedBytes, B256, U256}; use async_trait::async_trait; - use rain_orderbook_bindings::IInterpreterStoreV3::Set; + use raindex_bindings::IInterpreterStoreV3::Set; use serde_json; use std::collections::VecDeque; use std::sync::{Arc, Mutex}; @@ -408,7 +408,7 @@ mod tests { token: Address, tx: u8, ) -> DecodedEventData { - use rain_orderbook_bindings::IRaindexV6::DepositV2; + use raindex_bindings::IRaindexV6::DepositV2; DecodedEventData { event_type: EventType::DepositV2, block_number: U256::from(block), @@ -432,7 +432,7 @@ mod tests { output_token: Address, tx: u8, ) -> DecodedEventData { - use rain_orderbook_bindings::IRaindexV6::{AddOrderV3, EvaluableV4, OrderV4, IOV2}; + use raindex_bindings::IRaindexV6::{AddOrderV3, EvaluableV4, OrderV4, IOV2}; DecodedEventData { event_type: EventType::AddOrderV3, block_number: U256::from(block), diff --git a/crates/common/src/local_db/pipeline/runner/environment.rs b/crates/common/src/local_db/pipeline/runner/environment.rs index 0fba849006..fd47385b86 100644 --- a/crates/common/src/local_db/pipeline/runner/environment.rs +++ b/crates/common/src/local_db/pipeline/runner/environment.rs @@ -5,8 +5,8 @@ use crate::local_db::pipeline::adapters::bootstrap::BootstrapPipeline; use crate::local_db::pipeline::engine::SyncEngine; use crate::local_db::pipeline::{EventsPipeline, StatusBus, TokensPipeline, WindowPipeline}; use crate::local_db::LocalDbError; -use rain_orderbook_app_settings::orderbook::OrderbookCfg; -use rain_orderbook_app_settings::remote::manifest::ManifestMap; +use raindex_app_settings::orderbook::OrderbookCfg; +use raindex_app_settings::remote::manifest::ManifestMap; use std::collections::HashMap; use std::future::Future; use std::pin::Pin; @@ -154,11 +154,11 @@ mod tests { use crate::rpc_client::LogEntryResponse; use alloy::primitives::{address, b256, Address, B256}; use async_trait::async_trait; - use rain_orderbook_app_settings::local_db_manifest::MANIFEST_VERSION; - use rain_orderbook_app_settings::local_db_remotes::LocalDbRemoteCfg; - use rain_orderbook_app_settings::orderbook::OrderbookCfg; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_app_settings::yaml::default_document; + use raindex_app_settings::local_db_manifest::MANIFEST_VERSION; + use raindex_app_settings::local_db_remotes::LocalDbRemoteCfg; + use raindex_app_settings::orderbook::OrderbookCfg; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_app_settings::yaml::default_document; use std::collections::HashMap; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; diff --git a/crates/common/src/local_db/pipeline/runner/remotes.rs b/crates/common/src/local_db/pipeline/runner/remotes.rs index de0e209908..fdcf02f1aa 100644 --- a/crates/common/src/local_db/pipeline/runner/remotes.rs +++ b/crates/common/src/local_db/pipeline/runner/remotes.rs @@ -2,9 +2,9 @@ use super::utils::RunnerTarget; use crate::local_db::LocalDbError; use flate2::read::GzDecoder; use itertools::Itertools; -use rain_orderbook_app_settings::local_db_manifest::ManifestOrderbook; -use rain_orderbook_app_settings::orderbook::OrderbookCfg; -use rain_orderbook_app_settings::remote::manifest::{fetch_multiple_manifests, ManifestMap}; +use raindex_app_settings::local_db_manifest::ManifestOrderbook; +use raindex_app_settings::orderbook::OrderbookCfg; +use raindex_app_settings::remote::manifest::{fetch_multiple_manifests, ManifestMap}; use std::collections::HashMap; use std::io::Read; use url::Url; @@ -80,14 +80,14 @@ mod tests { use alloy::primitives::{address, Bytes}; use flate2::write::GzEncoder; use httpmock::prelude::*; - use rain_orderbook_app_settings::local_db_manifest::{ + use raindex_app_settings::local_db_manifest::{ LocalDbManifest, ManifestNetwork, ManifestOrderbook, MANIFEST_VERSION, }; - use rain_orderbook_app_settings::local_db_remotes::LocalDbRemoteCfg; - use rain_orderbook_app_settings::orderbook::OrderbookCfg; - use rain_orderbook_app_settings::remote::manifest::{FetchManifestError, ManifestMap}; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_app_settings::yaml::default_document; + use raindex_app_settings::local_db_remotes::LocalDbRemoteCfg; + use raindex_app_settings::orderbook::OrderbookCfg; + use raindex_app_settings::remote::manifest::{FetchManifestError, ManifestMap}; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_app_settings::yaml::default_document; use std::collections::{HashMap, HashSet}; use std::io::Write; use std::sync::Arc; diff --git a/crates/common/src/local_db/pipeline/runner/utils.rs b/crates/common/src/local_db/pipeline/runner/utils.rs index f2cdcef940..b6c2696104 100644 --- a/crates/common/src/local_db/pipeline/runner/utils.rs +++ b/crates/common/src/local_db/pipeline/runner/utils.rs @@ -3,10 +3,10 @@ use crate::local_db::pipeline::engine::SyncInputs; use crate::local_db::pipeline::{FinalityConfig, SyncConfig, WindowOverrides}; use crate::local_db::{LocalDbError, OrderbookIdentifier}; use itertools::Itertools; -use rain_orderbook_app_settings::local_db_sync::LocalDbSyncCfg; -use rain_orderbook_app_settings::orderbook::OrderbookCfg; -use rain_orderbook_app_settings::yaml::orderbook::{OrderbookYaml, OrderbookYamlValidation}; -use rain_orderbook_app_settings::yaml::YamlParsable; +use raindex_app_settings::local_db_sync::LocalDbSyncCfg; +use raindex_app_settings::orderbook::OrderbookCfg; +use raindex_app_settings::yaml::orderbook::{OrderbookYaml, OrderbookYamlValidation}; +use raindex_app_settings::yaml::YamlParsable; use std::collections::HashMap; use url::Url; @@ -127,9 +127,9 @@ mod tests { use crate::local_db::fetch::FetchConfigError; use crate::local_db::LocalDbError; use alloy::primitives::address; - use rain_orderbook_app_settings::local_db_sync::LocalDbSyncCfg; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_app_settings::yaml::default_document; + use raindex_app_settings::local_db_sync::LocalDbSyncCfg; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_app_settings::yaml::default_document; use url::Url; fn sample_settings_yaml() -> String { @@ -261,7 +261,7 @@ orderbooks: let is_missing_networks = matches!( err, LocalDbError::SettingsYaml(ref yaml_err) - if matches!(yaml_err, rain_orderbook_app_settings::yaml::YamlError::Field { .. }) + if matches!(yaml_err, raindex_app_settings::yaml::YamlError::Field { .. }) ); assert!( is_yaml_scan || is_missing_networks, diff --git a/crates/common/src/local_db/query/clear_orderbook_data/mod.rs b/crates/common/src/local_db/query/clear_raindex_data/mod.rs similarity index 100% rename from crates/common/src/local_db/query/clear_orderbook_data/mod.rs rename to crates/common/src/local_db/query/clear_raindex_data/mod.rs diff --git a/crates/common/src/local_db/query/clear_orderbook_data/query.sql b/crates/common/src/local_db/query/clear_raindex_data/query.sql similarity index 100% rename from crates/common/src/local_db/query/clear_orderbook_data/query.sql rename to crates/common/src/local_db/query/clear_raindex_data/query.sql diff --git a/crates/common/src/local_db/token_fetch.rs b/crates/common/src/local_db/token_fetch.rs index 258c95da5f..e0191dde18 100644 --- a/crates/common/src/local_db/token_fetch.rs +++ b/crates/common/src/local_db/token_fetch.rs @@ -66,7 +66,7 @@ mod tests { use crate::local_db::{FetchConfig, LocalDbError}; use crate::rpc_client::RpcClient; use alloy::primitives::Address; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_test_fixtures::LocalEvm; use url::Url; #[tokio::test(flavor = "multi_thread", worker_threads = 2)] diff --git a/crates/common/src/meta.rs b/crates/common/src/meta.rs index fc20d5cdeb..1fcedbafd8 100644 --- a/crates/common/src/meta.rs +++ b/crates/common/src/meta.rs @@ -46,8 +46,8 @@ impl TryDecodeRainlangSource for String { #[cfg(test)] mod tests { - use rain_orderbook_subgraph_client::types::common::SgBytes; - use rain_orderbook_subgraph_client::types::common::SgRainMetaV1; + use raindex_subgraph_client::types::common::SgBytes; + use raindex_subgraph_client::types::common::SgRainMetaV1; use super::*; diff --git a/crates/common/src/oracle.rs b/crates/common/src/oracle.rs index 7dfbcf95a6..976796feec 100644 --- a/crates/common/src/oracle.rs +++ b/crates/common/src/oracle.rs @@ -1,3 +1,3 @@ // Re-export oracle types and functions from the quote crate. // This maintains backward compatibility for code in common that uses oracle functionality. -pub use rain_orderbook_quote::oracle::*; +pub use raindex_quote::oracle::*; diff --git a/crates/common/src/raindex_client/add_orders.rs b/crates/common/src/raindex_client/add_orders.rs index 11cecfe674..89c9c8f762 100644 --- a/crates/common/src/raindex_client/add_orders.rs +++ b/crates/common/src/raindex_client/add_orders.rs @@ -138,7 +138,7 @@ impl RaindexClient { { Ok(orders) => orders, Err(RaindexError::OrderbookSubgraphClientError( - rain_orderbook_subgraph_client::OrderbookSubgraphClientError::Empty, + raindex_subgraph_client::OrderbookSubgraphClientError::Empty, )) => return Err(PollError::Empty), Err(e) => return Err(PollError::Inner(e)), }; @@ -191,7 +191,7 @@ mod tests { use alloy::primitives::{b256, Address, Bytes, U256}; use async_trait::async_trait; use httpmock::MockServer; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; use serde_json::{json, Value}; use std::{ str::FromStr, diff --git a/crates/common/src/raindex_client/local_db/mod.rs b/crates/common/src/raindex_client/local_db/mod.rs index 4c9ec13c11..7bb24f0167 100644 --- a/crates/common/src/raindex_client/local_db/mod.rs +++ b/crates/common/src/raindex_client/local_db/mod.rs @@ -337,8 +337,8 @@ mod wasm_tests { use super::*; use crate::raindex_client::RaindexClient; use gloo_timers::future::TimeoutFuture; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_app_settings::yaml::{ + use raindex_app_settings::spec_version::SpecVersion; + use raindex_app_settings::yaml::{ orderbook::{OrderbookYaml, OrderbookYamlValidation}, YamlParsable, }; diff --git a/crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs b/crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs index 60b8766117..1cd2e0ed17 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs @@ -141,7 +141,7 @@ mod tests { }; use alloy::primitives::{Address, Bytes}; use async_trait::async_trait; - use rain_orderbook_app_settings::local_db_manifest::DB_SCHEMA_VERSION; + use raindex_app_settings::local_db_manifest::DB_SCHEMA_VERSION; use serde_json::json; use std::str::FromStr; diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/config.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/config.rs index 10893f7320..628612f0e7 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/config.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/config.rs @@ -2,8 +2,8 @@ use crate::local_db::pipeline::runner::utils::{ build_runner_targets, ParsedRunnerSettings, RunnerTarget, }; use crate::local_db::LocalDbError; -use rain_orderbook_app_settings::local_db_sync::LocalDbSyncCfg; -use rain_orderbook_app_settings::orderbook::OrderbookCfg; +use raindex_app_settings::local_db_sync::LocalDbSyncCfg; +use raindex_app_settings::orderbook::OrderbookCfg; use std::collections::HashMap; #[derive(Debug, Clone)] @@ -69,7 +69,7 @@ impl NetworkRunnerConfig { mod tests { use super::*; use crate::local_db::pipeline::runner::utils::parse_runner_settings; - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::spec_version::SpecVersion; fn sample_settings_yaml() -> String { format!( diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs index e64c3020dc..b900913a52 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs @@ -34,7 +34,7 @@ use config::NetworkRunnerConfig; use environment::default_environment; use futures::future::join_all; use leadership::{DefaultLeadership, Leadership, LeadershipGuard}; -use rain_orderbook_app_settings::remote::manifest::ManifestMap; +use raindex_app_settings::remote::manifest::ManifestMap; pub struct ClientRunner { network_key: Option, @@ -335,12 +335,12 @@ mod tests { use crate::rpc_client::LogEntryResponse; use alloy::primitives::{address, b256, Address, Bytes, B256}; use async_trait::async_trait; - use rain_orderbook_app_settings::local_db_manifest::{ + use raindex_app_settings::local_db_manifest::{ LocalDbManifest, ManifestNetwork, ManifestOrderbook, DB_SCHEMA_VERSION, MANIFEST_VERSION, }; - use rain_orderbook_app_settings::orderbook::OrderbookCfg; - use rain_orderbook_app_settings::remote::manifest::ManifestMap; - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::orderbook::OrderbookCfg; + use raindex_app_settings::remote::manifest::ManifestMap; + use raindex_app_settings::spec_version::SpecVersion; use serde::Serialize; use serde_json::{json, Value}; use std::collections::{HashMap, VecDeque}; diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/native.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/native.rs index f21541036b..004d6f458c 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/native.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/native.rs @@ -14,8 +14,8 @@ use crate::local_db::LocalDbError; use crate::raindex_client::local_db::pipeline::bootstrap::ClientBootstrapAdapter; use crate::raindex_client::local_db::pipeline::status::TracingStatusBus; use crate::raindex_client::local_db::{LocalDb, SyncReadiness}; -use rain_orderbook_app_settings::local_db_manifest::DB_SCHEMA_VERSION; -use rain_orderbook_app_settings::network::NetworkCfg; +use raindex_app_settings::local_db_manifest::DB_SCHEMA_VERSION; +use raindex_app_settings::network::NetworkCfg; use std::collections::HashMap; use std::future::Future; use std::path::PathBuf; diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/wasm.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/wasm.rs index a1f3f35535..6e6f333335 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/wasm.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/wasm.rs @@ -17,8 +17,8 @@ use crate::raindex_client::local_db::pipeline::status::{ use crate::raindex_client::local_db::{LocalDb, NetworkSyncStatus, SchedulerState, SyncReadiness}; use gloo_timers::future::TimeoutFuture; use js_sys::Function; -use rain_orderbook_app_settings::local_db_manifest::DB_SCHEMA_VERSION; -use rain_orderbook_app_settings::network::NetworkCfg; +use raindex_app_settings::local_db_manifest::DB_SCHEMA_VERSION; +use raindex_app_settings::network::NetworkCfg; use std::cell::Cell; use std::collections::HashMap; use std::future::Future; diff --git a/crates/common/src/raindex_client/local_db/state.rs b/crates/common/src/raindex_client/local_db/state.rs index 5f3a25e0fd..cef2fbe290 100644 --- a/crates/common/src/raindex_client/local_db/state.rs +++ b/crates/common/src/raindex_client/local_db/state.rs @@ -3,8 +3,8 @@ use super::LocalDb; use crate::raindex_client::local_db::pipeline::runner::scheduler::NativeSyncHandle; #[cfg(target_family = "wasm")] use crate::raindex_client::local_db::pipeline::runner::scheduler::SchedulerHandle; -use rain_orderbook_app_settings::network::NetworkCfg; -use rain_orderbook_app_settings::yaml::orderbook::OrderbookYaml; +use raindex_app_settings::network::NetworkCfg; +use raindex_app_settings::yaml::orderbook::OrderbookYaml; #[cfg(target_family = "wasm")] use std::cell::RefCell; use std::collections::HashSet; @@ -223,9 +223,9 @@ mod tests { use crate::local_db::query::{ FromDbJson, LocalDbQueryError, LocalDbQueryExecutor, SqlStatement, SqlStatementBatch, }; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_app_settings::yaml::orderbook::{OrderbookYaml, OrderbookYamlValidation}; - use rain_orderbook_app_settings::yaml::YamlParsable; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_app_settings::yaml::orderbook::{OrderbookYaml, OrderbookYamlValidation}; + use raindex_app_settings::yaml::YamlParsable; struct NoopExec; diff --git a/crates/common/src/raindex_client/mod.rs b/crates/common/src/raindex_client/mod.rs index 989c6d088a..002d99401c 100644 --- a/crates/common/src/raindex_client/mod.rs +++ b/crates/common/src/raindex_client/mod.rs @@ -14,7 +14,7 @@ use alloy::{ }; pub(crate) use local_db::{ClassifiedChains, LocalDbState, QuerySource}; use rain_math_float::FloatError; -use rain_orderbook_app_settings::{ +use raindex_app_settings::{ network::NetworkCfg, remote_networks::ParseRemoteNetworksError, remote_tokens::ParseRemoteTokensError, @@ -23,7 +23,7 @@ use rain_orderbook_app_settings::{ YamlError, YamlParsable, }, }; -use rain_orderbook_subgraph_client::{ +use raindex_subgraph_client::{ types::order_detail_traits::OrderDetailError, MultiSubgraphArgs, OrderbookSubgraphClient, OrderbookSubgraphClientError, }; @@ -416,7 +416,7 @@ pub enum RaindexError { #[error(transparent)] AddOrderArgsError(#[from] AddOrderArgsError), #[error(transparent)] - OrderbookQuoteError(#[from] rain_orderbook_quote::error::Error), + OrderbookQuoteError(#[from] raindex_quote::error::Error), #[error("Missing subgraph {0} for order {1}")] SubgraphNotFound(String, String), #[error("Invalid vault balance change type: {0}")] @@ -694,7 +694,7 @@ impl From for WasmEncodedError { #[cfg(test)] pub(crate) mod tests { use super::*; - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::spec_version::SpecVersion; #[cfg(not(target_family = "wasm"))] pub const CHAIN_ID_1_ORDERBOOK_ADDRESS: &str = "0x1234567890123456789012345678901234567890"; @@ -980,7 +980,7 @@ accounts: #[cfg(target_family = "wasm")] mod wasm_tests { use super::*; - use rain_orderbook_app_settings::yaml::YamlError; + use raindex_app_settings::yaml::YamlError; use url::Url; use wasm_bindgen_test::wasm_bindgen_test; diff --git a/crates/common/src/raindex_client/order_quotes.rs b/crates/common/src/raindex_client/order_quotes.rs index 2f4720bf1b..11b975dba9 100644 --- a/crates/common/src/raindex_client/order_quotes.rs +++ b/crates/common/src/raindex_client/order_quotes.rs @@ -2,9 +2,9 @@ use super::*; use crate::raindex_client::orders::RaindexOrder; use crate::raindex_client::orders_list::RaindexOrders; use rain_math_float::Float; -use rain_orderbook_bindings::IRaindexV6::OrderV4; -use rain_orderbook_quote::{get_order_quotes, BatchOrderQuotesResponse, OrderQuoteValue, Pair}; -use rain_orderbook_subgraph_client::utils::float::{F0, F1}; +use raindex_bindings::IRaindexV6::OrderV4; +use raindex_quote::{get_order_quotes, BatchOrderQuotesResponse, OrderQuoteValue, Pair}; +use raindex_subgraph_client::utils::float::{F0, F1}; use std::ops::{Div, Mul}; #[derive(Serialize, Deserialize, Debug, Clone, Tsify)] @@ -275,7 +275,7 @@ mod tests { use alloy::{sol, sol_types::SolValue}; use httpmock::MockServer; use rain_math_float::Float; - use rain_orderbook_subgraph_client::utils::float::{F0_5, F2}; + use raindex_subgraph_client::utils::float::{F0_5, F2}; use serde_json::{json, Value}; sol!( diff --git a/crates/common/src/raindex_client/orders.rs b/crates/common/src/raindex_client/orders.rs index c184c1f6c0..a352f0f261 100644 --- a/crates/common/src/raindex_client/orders.rs +++ b/crates/common/src/raindex_client/orders.rs @@ -33,7 +33,7 @@ use rain_metaboard_subgraph::metaboard_client::MetaboardSubgraphClient; use rain_metaboard_subgraph::types::metas::BigInt as MetaBigInt; use rain_metadata::types::dotrain::source_v1::DotrainSourceV1; use rain_metadata::{KnownMagic, RainMetaDocumentV1Item}; -use rain_orderbook_subgraph_client::{ +use raindex_subgraph_client::{ types::{ common::{ SgBigInt, SgBytes, SgOrder, SgOrderAsIO, SgOrderbook, SgOrdersListFilterArgs, @@ -1536,11 +1536,11 @@ mod tests { use rain_metadata::{ ContentEncoding, ContentLanguage, ContentType, KnownMagic, RainMetaDocumentV1Item, }; - use rain_orderbook_subgraph_client::types::common::{ + use raindex_subgraph_client::types::common::{ SgAddOrder, SgBigInt, SgBytes, SgErc20, SgOrderAsIO, SgOrderbook, SgTransaction, SgVault, }; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; use serde_bytes::ByteBuf; use serde_json::{json, Value}; use std::collections::BTreeMap; @@ -1958,7 +1958,7 @@ mod tests { #[test] fn get_orders_filters_to_sg_filter_args_maps_orderbook_addresses() { use alloy::primitives::address; - use rain_orderbook_subgraph_client::types::common::SgOrdersListFilterArgs; + use raindex_subgraph_client::types::common::SgOrdersListFilterArgs; let filters = GetOrdersFilters { owners: vec![], @@ -1986,7 +1986,7 @@ mod tests { #[test] fn get_orders_filters_to_sg_filter_args_empty_orderbook_addresses() { - use rain_orderbook_subgraph_client::types::common::SgOrdersListFilterArgs; + use raindex_subgraph_client::types::common::SgOrdersListFilterArgs; let filters = GetOrdersFilters { owners: vec![], @@ -2004,7 +2004,7 @@ mod tests { #[test] fn get_orders_filters_to_sg_filter_args_lowercases_mixed_case_addresses() { use alloy::primitives::address; - use rain_orderbook_subgraph_client::types::common::SgOrdersListFilterArgs; + use raindex_subgraph_client::types::common::SgOrdersListFilterArgs; let filters = GetOrdersFilters { owners: vec![], @@ -3347,7 +3347,7 @@ mod tests { use crate::take_orders::TakeOrdersMode; use alloy::primitives::{Address, Bytes}; use rain_math_float::Float; - use rain_orderbook_quote::Pair; + use raindex_quote::Pair; use std::ops::Mul; use wasm_bindgen_test::wasm_bindgen_test; use wasm_bindgen_utils::prelude::{from_js_value, to_js_value}; diff --git a/crates/common/src/raindex_client/orderbook_yaml.rs b/crates/common/src/raindex_client/raindex_yaml.rs similarity index 99% rename from crates/common/src/raindex_client/orderbook_yaml.rs rename to crates/common/src/raindex_client/raindex_yaml.rs index a83bdbf177..57d9430a90 100644 --- a/crates/common/src/raindex_client/orderbook_yaml.rs +++ b/crates/common/src/raindex_client/raindex_yaml.rs @@ -1,5 +1,5 @@ use super::*; -use rain_orderbook_app_settings::{ +use raindex_app_settings::{ accounts::AccountCfg, network::NetworkCfg, orderbook::OrderbookCfg, token::TokenCfg, }; use std::collections::{HashMap, HashSet}; diff --git a/crates/common/src/raindex_client/remove_orders.rs b/crates/common/src/raindex_client/remove_orders.rs index b97ac218ac..db6255c47c 100644 --- a/crates/common/src/raindex_client/remove_orders.rs +++ b/crates/common/src/raindex_client/remove_orders.rs @@ -7,8 +7,8 @@ use crate::raindex_client::QuerySource; use crate::retry::{retry_with_constant_interval, RetryError}; use alloy::primitives::{hex::decode, Bytes, B256}; use alloy::sol_types::{SolCall, SolValue}; -use rain_orderbook_bindings::IRaindexV6::{removeOrder3Call, OrderV4}; -use rain_orderbook_subgraph_client::types::order_detail_traits::OrderDetailError; +use raindex_bindings::IRaindexV6::{removeOrder3Call, OrderV4}; +use raindex_subgraph_client::types::order_detail_traits::OrderDetailError; const DEFAULT_REMOVE_ORDER_POLL_ATTEMPTS: usize = 10; const DEFAULT_REMOVE_ORDER_POLL_INTERVAL_MS: u64 = 1_000; @@ -141,7 +141,7 @@ impl RaindexClient { { Ok(orders) => orders, Err(RaindexError::OrderbookSubgraphClientError( - rain_orderbook_subgraph_client::OrderbookSubgraphClientError::Empty, + raindex_subgraph_client::OrderbookSubgraphClientError::Empty, )) => return Err(PollError::Empty), Err(e) => return Err(PollError::Inner(e)), }; @@ -236,7 +236,7 @@ mod tests { use alloy::primitives::{b256, Address, Bytes, U256}; use async_trait::async_trait; use httpmock::MockServer; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; use serde_json::{json, Value}; use std::{ str::FromStr, diff --git a/crates/common/src/raindex_client/take_orders/approval.rs b/crates/common/src/raindex_client/take_orders/approval.rs index 62a02ab8c9..a8f5805bbc 100644 --- a/crates/common/src/raindex_client/take_orders/approval.rs +++ b/crates/common/src/raindex_client/take_orders/approval.rs @@ -163,7 +163,7 @@ mod local_evm_tests { use super::*; use crate::take_orders::TakeOrdersMode; use alloy::primitives::U256; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_test_fixtures::LocalEvm; use url::Url; fn make_mode(mode: TakeOrdersMode, amount: &str) -> ParsedTakeOrdersMode { diff --git a/crates/common/src/raindex_client/take_orders/e2e_tests.rs b/crates/common/src/raindex_client/take_orders/e2e_tests.rs index 4ac72d826d..0d4aaebcd3 100644 --- a/crates/common/src/raindex_client/take_orders/e2e_tests.rs +++ b/crates/common/src/raindex_client/take_orders/e2e_tests.rs @@ -24,7 +24,7 @@ use alloy::serde::WithOtherFields; use alloy::sol_types::SolCall; use httpmock::MockServer; use rain_math_float::Float; -use rain_orderbook_bindings::IRaindexV6::{takeOrders4Call, TakeOrdersConfigV5}; +use raindex_bindings::IRaindexV6::{takeOrders4Call, TakeOrdersConfigV5}; use serde_json::json; use std::ops::{Mul, Sub}; diff --git a/crates/common/src/raindex_client/take_orders/mod.rs b/crates/common/src/raindex_client/take_orders/mod.rs index c0ee93b2ad..86411f1a54 100644 --- a/crates/common/src/raindex_client/take_orders/mod.rs +++ b/crates/common/src/raindex_client/take_orders/mod.rs @@ -20,7 +20,7 @@ use crate::take_orders::{ build_take_orders_config_from_simulation, find_failing_order_index, simulate_take_orders, }; use approval::{check_approval_needed, ApprovalCheckParams}; -use rain_orderbook_bindings::provider::mk_read_provider; +use raindex_bindings::provider::mk_read_provider; use wasm_bindgen_utils::prelude::*; use wasm_bindgen_utils::wasm_export; diff --git a/crates/common/src/raindex_client/take_orders/result.rs b/crates/common/src/raindex_client/take_orders/result.rs index c456d12555..3eebb090cc 100644 --- a/crates/common/src/raindex_client/take_orders/result.rs +++ b/crates/common/src/raindex_client/take_orders/result.rs @@ -3,7 +3,7 @@ use crate::take_orders::{build_approval_calldata, BuiltTakeOrdersConfig, ParsedT use alloy::primitives::{Address, Bytes}; use alloy::sol_types::SolCall; use rain_math_float::Float; -use rain_orderbook_bindings::IRaindexV6::takeOrders4Call; +use raindex_bindings::IRaindexV6::takeOrders4Call; use serde::{Deserialize, Serialize}; use std::ops::{Div, Mul}; use wasm_bindgen_utils::prelude::*; @@ -426,8 +426,8 @@ mod tests { use crate::take_orders::build_take_orders_config_from_simulation; use crate::test_helpers::candidates::make_candidate; use alloy::primitives::U256; - use rain_orderbook_bindings::IRaindexV6::takeOrders4Call; - use rain_orderbook_bindings::IERC20::approveCall; + use raindex_bindings::IRaindexV6::takeOrders4Call; + use raindex_bindings::IERC20::approveCall; fn high_price_cap() -> Float { Float::parse("1000000".to_string()).unwrap() diff --git a/crates/common/src/raindex_client/take_orders/single.rs b/crates/common/src/raindex_client/take_orders/single.rs index 1e6741d48b..d3c4df4df8 100644 --- a/crates/common/src/raindex_client/take_orders/single.rs +++ b/crates/common/src/raindex_client/take_orders/single.rs @@ -8,8 +8,8 @@ use crate::take_orders::{ }; use alloy::primitives::Address; use rain_math_float::Float; -use rain_orderbook_bindings::provider::mk_read_provider; -use rain_orderbook_bindings::IRaindexV6::OrderV4; +use raindex_bindings::provider::mk_read_provider; +use raindex_bindings::IRaindexV6::OrderV4; use std::ops::{Div, Mul}; #[cfg(target_family = "wasm")] use std::str::FromStr; @@ -265,7 +265,7 @@ mod tests { use super::*; use crate::raindex_client::order_quotes::{RaindexOrderQuote, RaindexOrderQuoteValue}; use rain_math_float::Float; - use rain_orderbook_quote::Pair; + use raindex_quote::Pair; use std::ops::Mul; fn make_quote_value(max_output: Float, ratio: Float) -> RaindexOrderQuoteValue { @@ -357,7 +357,7 @@ mod tests { rt.block_on(async { use alloy::primitives::b256; use httpmock::MockServer; - use rain_orderbook_subgraph_client::utils::float::F1; + use raindex_subgraph_client::utils::float::F1; use serde_json::json; let server = MockServer::start_async().await; @@ -458,7 +458,7 @@ mod tests { rt.block_on(async { use alloy::primitives::b256; use httpmock::MockServer; - use rain_orderbook_subgraph_client::utils::float::F1; + use raindex_subgraph_client::utils::float::F1; use serde_json::json; let server = MockServer::start_async().await; @@ -561,7 +561,7 @@ mod tests { rt.block_on(async { use alloy::primitives::b256; use httpmock::MockServer; - use rain_orderbook_subgraph_client::utils::float::F1; + use raindex_subgraph_client::utils::float::F1; use serde_json::json; let server = MockServer::start_async().await; diff --git a/crates/common/src/raindex_client/take_orders/single_tests.rs b/crates/common/src/raindex_client/take_orders/single_tests.rs index 5cae73b305..7724c92626 100644 --- a/crates/common/src/raindex_client/take_orders/single_tests.rs +++ b/crates/common/src/raindex_client/take_orders/single_tests.rs @@ -22,8 +22,8 @@ use alloy::serde::WithOtherFields; use alloy::sol_types::SolCall; use httpmock::MockServer; use rain_math_float::Float; -use rain_orderbook_bindings::IRaindexV6::takeOrders4Call; -use rain_orderbook_quote::Pair; +use raindex_bindings::IRaindexV6::takeOrders4Call; +use raindex_quote::Pair; use serde_json::json; use std::ops::{Div, Mul}; diff --git a/crates/common/src/raindex_client/trades.rs b/crates/common/src/raindex_client/trades.rs index 2f1d30ac85..5fae3b2de1 100644 --- a/crates/common/src/raindex_client/trades.rs +++ b/crates/common/src/raindex_client/trades.rs @@ -11,7 +11,7 @@ use crate::raindex_client::{ vaults::{LocalTradeBalanceInfo, LocalTradeTokenInfo, RaindexVaultBalanceChange}, }; use alloy::primitives::{Address, Bytes, B256, U256}; -use rain_orderbook_subgraph_client::types::{common::SgTrade, Id}; +use raindex_subgraph_client::types::{common::SgTrade, Id}; use std::str::FromStr; #[cfg(target_family = "wasm")] use wasm_bindgen_utils::prelude::js_sys::BigInt; @@ -368,7 +368,7 @@ mod test_helpers { }; use alloy::primitives::{address, b256, bytes, Address, Bytes, B256, U256}; use js_sys::Array; - use rain_orderbook_subgraph_client::utils::float::{F1, F2, F3, NEG2}; + use raindex_subgraph_client::utils::float::{F1, F2, F3, NEG2}; use serde_json::{self, json}; use std::collections::HashMap; use std::str::FromStr; @@ -769,7 +769,7 @@ mod test_helpers { use alloy::primitives::{b256, Bytes}; use httpmock::MockServer; use rain_math_float::Float; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; use serde_json::{json, Value}; fn get_order1_json() -> Value { diff --git a/crates/common/src/raindex_client/transactions.rs b/crates/common/src/raindex_client/transactions.rs index 309125c386..934fad3810 100644 --- a/crates/common/src/raindex_client/transactions.rs +++ b/crates/common/src/raindex_client/transactions.rs @@ -7,8 +7,8 @@ use crate::raindex_client::QuerySource; use alloy::primitives::{Address, B256, U256}; #[cfg(target_family = "wasm")] use gloo_timers::future::TimeoutFuture; -use rain_orderbook_subgraph_client::types::{common::SgTransaction, Id}; -use rain_orderbook_subgraph_client::OrderbookSubgraphClientError; +use raindex_subgraph_client::types::{common::SgTransaction, Id}; +use raindex_subgraph_client::OrderbookSubgraphClientError; use serde::{Deserialize, Serialize}; #[cfg(not(target_family = "wasm"))] use std::time::Duration; diff --git a/crates/common/src/raindex_client/vaults.rs b/crates/common/src/raindex_client/vaults.rs index f265750108..2bfc96db41 100644 --- a/crates/common/src/raindex_client/vaults.rs +++ b/crates/common/src/raindex_client/vaults.rs @@ -24,8 +24,8 @@ use alloy::{ }; use async_trait::async_trait; use rain_math_float::Float; -use rain_orderbook_bindings::{IRaindexV6::deposit4Call, IERC20::approveCall}; -use rain_orderbook_subgraph_client::{ +use raindex_bindings::{IRaindexV6::deposit4Call, IERC20::approveCall}; +use raindex_subgraph_client::{ performance::vol::{VaultVolume, VolumeDetails}, types::{ common::{ @@ -2154,12 +2154,12 @@ mod tests { use alloy::primitives::{address, b256}; use alloy::sol_types::SolCall; use httpmock::MockServer; - use rain_orderbook_bindings::IERC20Metadata::decimalsCall; - use rain_orderbook_bindings::{ + use raindex_bindings::IERC20Metadata::decimalsCall; + use raindex_bindings::{ IRaindexV6::{deposit4Call, withdraw4Call}, IERC20::approveCall, }; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; use serde_json::{json, Value}; use std::sync::Arc; use LocalDbVault; @@ -3501,7 +3501,7 @@ mod tests { #[test] fn get_vaults_filters_to_sg_filter_args_maps_orderbook_addresses() { - use rain_orderbook_subgraph_client::types::common::SgVaultsListFilterArgs; + use raindex_subgraph_client::types::common::SgVaultsListFilterArgs; let filters = GetVaultsFilters { owners: vec![], @@ -3529,7 +3529,7 @@ mod tests { #[test] fn get_vaults_filters_to_sg_filter_args_empty_orderbook_addresses() { - use rain_orderbook_subgraph_client::types::common::SgVaultsListFilterArgs; + use raindex_subgraph_client::types::common::SgVaultsListFilterArgs; let filters = GetVaultsFilters { owners: vec![], @@ -3546,7 +3546,7 @@ mod tests { #[test] fn get_vaults_filters_to_sg_filter_args_lowercases_mixed_case_addresses() { - use rain_orderbook_subgraph_client::types::common::SgVaultsListFilterArgs; + use raindex_subgraph_client::types::common::SgVaultsListFilterArgs; let filters = GetVaultsFilters { owners: vec![], diff --git a/crates/common/src/raindex_client/vaults_list.rs b/crates/common/src/raindex_client/vaults_list.rs index 0a05339da8..deabea0f41 100644 --- a/crates/common/src/raindex_client/vaults_list.rs +++ b/crates/common/src/raindex_client/vaults_list.rs @@ -1,6 +1,6 @@ use alloy::{primitives::Bytes, sol_types::SolCall}; use rain_math_float::Float; -use rain_orderbook_bindings::OrderBook::multicallCall; +use raindex_bindings::OrderBook::multicallCall; use serde::{Deserialize, Serialize}; use thiserror::Error; use wasm_bindgen_utils::prelude::*; diff --git a/crates/common/src/rainlang.rs b/crates/common/src/rainlang.rs index fec28b162c..75f236e62f 100644 --- a/crates/common/src/rainlang.rs +++ b/crates/common/src/rainlang.rs @@ -279,7 +279,7 @@ mod fork_parse { use super::*; use crate::add_order::ORDERBOOK_ORDER_ENTRYPOINTS; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_test_fixtures::LocalEvm; #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn test_parse_rainlang_on_fork_ok() { diff --git a/crates/common/src/remove_order.rs b/crates/common/src/remove_order.rs index 55b5e914fb..97d0222219 100644 --- a/crates/common/src/remove_order.rs +++ b/crates/common/src/remove_order.rs @@ -6,8 +6,8 @@ use alloy::sol_types::SolCall; use alloy_ethers_typecast::WritableClientError; #[cfg(not(target_family = "wasm"))] use alloy_ethers_typecast::{WriteTransaction, WriteTransactionStatus}; -use rain_orderbook_bindings::IRaindexV6::removeOrder3Call; -use rain_orderbook_subgraph_client::types::{ +use raindex_bindings::IRaindexV6::removeOrder3Call; +use raindex_subgraph_client::types::{ common::SgOrder, order_detail_traits::OrderDetailError, }; use serde::{Deserialize, Serialize}; @@ -79,11 +79,11 @@ impl RemoveOrderArgs { mod tests { use super::*; use alloy::primitives::Address; - use rain_orderbook_bindings::IRaindexV6::removeOrder3Call; - use rain_orderbook_subgraph_client::types::common::{ + use raindex_bindings::IRaindexV6::removeOrder3Call; + use raindex_subgraph_client::types::common::{ SgBigInt, SgBytes, SgErc20, SgOrderbook, SgVault, }; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; fn get_order() -> SgOrder { SgOrder { diff --git a/crates/common/src/replays.rs b/crates/common/src/replays.rs index 729399fee9..c9a9901f9f 100644 --- a/crates/common/src/replays.rs +++ b/crates/common/src/replays.rs @@ -57,8 +57,8 @@ mod tests { sol_types::SolCall, }; use rain_math_float::Float; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_test_fixtures::{LocalEvm, Orderbook}; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_test_fixtures::{LocalEvm, Orderbook}; use std::str::FromStr; #[tokio::test(flavor = "multi_thread", worker_threads = 10)] diff --git a/crates/common/src/rpc_client.rs b/crates/common/src/rpc_client.rs index 9f68886515..adb5e2e713 100644 --- a/crates/common/src/rpc_client.rs +++ b/crates/common/src/rpc_client.rs @@ -3,7 +3,7 @@ use alloy::providers::Provider; use alloy::rpc::json_rpc::{Id, RequestMeta}; use alloy::rpc::types::Filter; use alloy::transports::TransportError; -use rain_orderbook_bindings::provider::{mk_read_provider, ReadProvider, ReadProviderError}; +use raindex_bindings::provider::{mk_read_provider, ReadProvider, ReadProviderError}; use serde::{Deserialize, Serialize}; use serde_json::{Map, Value}; use std::sync::Arc; diff --git a/crates/common/src/subgraph.rs b/crates/common/src/subgraph.rs index 72f234d3b6..b295f95759 100644 --- a/crates/common/src/subgraph.rs +++ b/crates/common/src/subgraph.rs @@ -1,4 +1,4 @@ -use rain_orderbook_subgraph_client::OrderbookSubgraphClient; +use raindex_subgraph_client::OrderbookSubgraphClient; use serde::{Deserialize, Serialize}; use url::{ParseError, Url}; diff --git a/crates/common/src/take_orders/candidates.rs b/crates/common/src/take_orders/candidates.rs index 60d71b22b5..925bdae0b0 100644 --- a/crates/common/src/take_orders/candidates.rs +++ b/crates/common/src/take_orders/candidates.rs @@ -3,7 +3,7 @@ use crate::raindex_client::orders::RaindexOrder; use crate::raindex_client::RaindexError; use alloy::primitives::Address; use rain_math_float::Float; -use rain_orderbook_bindings::IRaindexV6::{OrderV4, SignedContextV1}; +use raindex_bindings::IRaindexV6::{OrderV4, SignedContextV1}; #[cfg(target_family = "wasm")] use std::str::FromStr; diff --git a/crates/common/src/take_orders/config.rs b/crates/common/src/take_orders/config.rs index 14c843cd85..c3667dbe66 100644 --- a/crates/common/src/take_orders/config.rs +++ b/crates/common/src/take_orders/config.rs @@ -2,7 +2,7 @@ use super::simulation::SimulationResult; use crate::raindex_client::RaindexError; use alloy::primitives::{Bytes, U256}; use rain_math_float::Float; -use rain_orderbook_bindings::IRaindexV6::{TakeOrderConfigV4, TakeOrdersConfigV5}; +use raindex_bindings::IRaindexV6::{TakeOrderConfigV4, TakeOrdersConfigV5}; use serde::{Deserialize, Serialize}; use wasm_bindgen_utils::{impl_wasm_traits, prelude::*}; diff --git a/crates/common/src/take_orders/preflight.rs b/crates/common/src/take_orders/preflight.rs index 68863eda22..00893a17bd 100644 --- a/crates/common/src/take_orders/preflight.rs +++ b/crates/common/src/take_orders/preflight.rs @@ -4,9 +4,9 @@ use alloy::providers::Provider; use alloy::rpc::types::TransactionRequest; use alloy::serde::WithOtherFields; use alloy::sol_types::SolCall; -use rain_orderbook_bindings::provider::ReadProvider; -use rain_orderbook_bindings::IRaindexV6::{takeOrders4Call, TakeOrdersConfigV5}; -use rain_orderbook_bindings::IERC20::approveCall; +use raindex_bindings::provider::ReadProvider; +use raindex_bindings::IRaindexV6::{takeOrders4Call, TakeOrdersConfigV5}; +use raindex_bindings::IERC20::approveCall; use thiserror::Error; use crate::erc20::ERC20; @@ -295,9 +295,9 @@ mod local_evm_tests { use super::*; use crate::erc20::ERC20; use alloy::primitives::B256; - use rain_orderbook_bindings::provider::mk_read_provider; - use rain_orderbook_bindings::IRaindexV6::TakeOrderConfigV4; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_bindings::provider::mk_read_provider; + use raindex_bindings::IRaindexV6::TakeOrderConfigV4; + use raindex_test_fixtures::LocalEvm; use url::Url; async fn setup_local_evm() -> (LocalEvm, Address, Address, Address) { @@ -474,9 +474,9 @@ mod local_evm_tests { let provider = mk_read_provider(&[rpc_url]).unwrap(); let fake_order = TakeOrderConfigV4 { - order: rain_orderbook_bindings::IRaindexV6::OrderV4 { + order: raindex_bindings::IRaindexV6::OrderV4 { owner: Address::ZERO, - evaluable: rain_orderbook_bindings::IRaindexV6::EvaluableV4 { + evaluable: raindex_bindings::IRaindexV6::EvaluableV4 { interpreter: Address::ZERO, store: Address::ZERO, bytecode: Bytes::new(), @@ -531,9 +531,9 @@ mod local_evm_tests { let provider = mk_read_provider(&[rpc_url]).unwrap(); let fake_order = TakeOrderConfigV4 { - order: rain_orderbook_bindings::IRaindexV6::OrderV4 { + order: raindex_bindings::IRaindexV6::OrderV4 { owner: Address::ZERO, - evaluable: rain_orderbook_bindings::IRaindexV6::EvaluableV4 { + evaluable: raindex_bindings::IRaindexV6::EvaluableV4 { interpreter: Address::ZERO, store: Address::ZERO, bytecode: Bytes::new(), diff --git a/crates/common/src/test_helpers.rs b/crates/common/src/test_helpers.rs index 603823b62d..712b5d4a69 100644 --- a/crates/common/src/test_helpers.rs +++ b/crates/common/src/test_helpers.rs @@ -1,4 +1,4 @@ -use rain_orderbook_app_settings::spec_version::SpecVersion; +use raindex_app_settings::spec_version::SpecVersion; pub fn test_dotrain() -> String { format!( @@ -178,10 +178,10 @@ _ _: 0 0; pub mod local_evm { use alloy::primitives::{Address, B256, U256}; use rain_math_float::Float; - use rain_orderbook_subgraph_client::types::common::{ + use raindex_subgraph_client::types::common::{ SgBigInt, SgBytes, SgErc20, SgOrderbook, SgVault, }; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_test_fixtures::LocalEvm; pub struct TestSetup { pub local_evm: LocalEvm, @@ -346,7 +346,7 @@ pub mod local_evm { } pub async fn setup_multi_orderbook_test() -> MultiOrderbookTestSetup { - use rain_orderbook_test_fixtures::Orderbook; + use raindex_test_fixtures::Orderbook; let mut local_evm = LocalEvm::new().await; let owner = local_evm.signer_wallets[0].default_signer().address(); @@ -395,7 +395,7 @@ pub mod local_evm { amount: U256, vault_id: B256, ) { - use rain_orderbook_test_fixtures::Orderbook; + use raindex_test_fixtures::Orderbook; let token_contract = setup .local_evm @@ -478,7 +478,7 @@ pub mod local_evm { pub mod orders { use alloy::primitives::{Address, U256}; - use rain_orderbook_bindings::IRaindexV6::{EvaluableV4, OrderV4, IOV2}; + use raindex_bindings::IRaindexV6::{EvaluableV4, OrderV4, IOV2}; pub fn make_basic_order(input_token: Address, output_token: Address) -> OrderV4 { OrderV4 { @@ -531,7 +531,7 @@ pub mod orders { } use super::super::local_evm::MultiOrderbookTestSetup; - use rain_orderbook_bindings::IRaindexV6::OrderV4; + use raindex_bindings::IRaindexV6::OrderV4; pub async fn deploy_order_to_orderbook( setup: &MultiOrderbookTestSetup, @@ -541,7 +541,7 @@ pub mod orders { use alloy::network::TransactionBuilder; use alloy::rpc::types::TransactionRequest; use alloy::serde::WithOtherFields; - use rain_orderbook_test_fixtures::Orderbook; + use raindex_test_fixtures::Orderbook; let dotrain_order = DotrainOrder::create(dotrain.clone(), None).await.unwrap(); let deployment = dotrain_order @@ -620,7 +620,7 @@ pub mod candidates { pub mod quotes { use crate::raindex_client::order_quotes::{RaindexOrderQuote, RaindexOrderQuoteValue}; use rain_math_float::Float; - use rain_orderbook_quote::Pair; + use raindex_quote::Pair; pub fn make_quote_value( max_output: Float, @@ -666,7 +666,7 @@ pub mod quotes { #[cfg(not(target_family = "wasm"))] pub mod dotrain { use alloy::primitives::Address; - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::spec_version::SpecVersion; use super::local_evm::{MultiOrderbookTestSetup, TestSetup}; @@ -908,8 +908,8 @@ amount price: {max_output} {ratio}; #[cfg(not(target_family = "wasm"))] pub mod subgraph { use alloy::primitives::{Address, B256}; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_subgraph_client::types::common::{ + use raindex_app_settings::spec_version::SpecVersion; + use raindex_subgraph_client::types::common::{ SgBigInt, SgBytes, SgOrder, SgOrderbook, SgVault, }; use serde_json::json; diff --git a/crates/common/src/transaction.rs b/crates/common/src/transaction.rs index 8a9f6ed265..7a2c6a3147 100644 --- a/crates/common/src/transaction.rs +++ b/crates/common/src/transaction.rs @@ -139,7 +139,7 @@ mod tests { use httpmock::MockServer; use super::*; - use rain_orderbook_bindings::IRaindexV6::vaultBalance2Call; + use raindex_bindings::IRaindexV6::vaultBalance2Call; #[test] fn test_try_into_write_contract_parameters_ok() { diff --git a/crates/common/src/types/order_detail_extended.rs b/crates/common/src/types/order_detail_extended.rs index 98fa2d5b3d..e9e221c185 100644 --- a/crates/common/src/types/order_detail_extended.rs +++ b/crates/common/src/types/order_detail_extended.rs @@ -1,5 +1,5 @@ use crate::meta::{TryDecodeRainlangSource, TryDecodeRainlangSourceError}; -use rain_orderbook_subgraph_client::types::common::SgOrder; +use raindex_subgraph_client::types::common::SgOrder; use serde::{Deserialize, Serialize}; #[cfg(target_family = "wasm")] use wasm_bindgen_utils::{impl_wasm_traits, prelude::*}; @@ -36,7 +36,7 @@ impl TryFrom for OrderDetailExtended { mod tests { use super::*; use crate::meta::TryDecodeRainlangSourceError; - use rain_orderbook_subgraph_client::types::common::{ + use raindex_subgraph_client::types::common::{ SgAddOrder, SgBigInt, SgBytes, SgErc20, SgOrderStructPartialTrade, SgOrderbook, SgRemoveOrder, SgTransaction, SgVault, }; diff --git a/crates/common/src/types/order_takes_list_flattened.rs b/crates/common/src/types/order_takes_list_flattened.rs index 411febea20..6eb0b3b0fa 100644 --- a/crates/common/src/types/order_takes_list_flattened.rs +++ b/crates/common/src/types/order_takes_list_flattened.rs @@ -1,6 +1,6 @@ use crate::{csv::TryIntoCsv, utils::timestamp::format_bigint_timestamp_display}; use rain_math_float::Float; -use rain_orderbook_subgraph_client::types::common::*; +use raindex_subgraph_client::types::common::*; use serde::{Deserialize, Serialize}; use super::FlattenError; @@ -59,11 +59,11 @@ impl TryIntoCsv for Vec {} mod tests { use super::*; use rain_math_float::FloatError; - use rain_orderbook_subgraph_client::types::common::{ + use raindex_subgraph_client::types::common::{ SgBigInt, SgBytes, SgErc20, SgOrderbook, SgTrade, SgTradeEvent, SgTradeStructPartialOrder, SgTradeVaultBalanceChange, SgTransaction, SgVaultBalanceChangeVault, }; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; // Helper to build a default, valid SgTrade instance fn mock_sg_trade_default() -> SgTrade { diff --git a/crates/common/src/types/orders_list_flattened.rs b/crates/common/src/types/orders_list_flattened.rs index af0e24237c..d9ece1541b 100644 --- a/crates/common/src/types/orders_list_flattened.rs +++ b/crates/common/src/types/orders_list_flattened.rs @@ -2,8 +2,8 @@ use crate::types::vault::NO_SYMBOL; use crate::{csv::TryIntoCsv, utils::timestamp::format_bigint_timestamp_display}; use alloy::dyn_abi::SolType; use alloy::primitives::hex::{decode, encode}; -use rain_orderbook_bindings::IRaindexV6::OrderV4; -use rain_orderbook_subgraph_client::types::common::*; +use raindex_bindings::IRaindexV6::OrderV4; +use raindex_subgraph_client::types::common::*; use serde::{Deserialize, Serialize}; use super::FlattenError; @@ -90,8 +90,8 @@ mod tests { primitives::{Address, Bytes, FixedBytes, B256, U256}, sol_types::SolValue, }; - use rain_orderbook_bindings::IRaindexV6::{EvaluableV4, OrderV4, IOV2}; - use rain_orderbook_subgraph_client::types::common::{ + use raindex_bindings::IRaindexV6::{EvaluableV4, OrderV4, IOV2}; + use raindex_subgraph_client::types::common::{ SgAddOrder, SgBigInt, SgBytes, SgErc20, SgOrderStructPartialTrade, SgOrderbook, SgTransaction, SgVault, }; diff --git a/crates/common/src/types/token_vault_flattened.rs b/crates/common/src/types/token_vault_flattened.rs index d6399fb36b..8abeaff988 100644 --- a/crates/common/src/types/token_vault_flattened.rs +++ b/crates/common/src/types/token_vault_flattened.rs @@ -1,6 +1,6 @@ use crate::csv::TryIntoCsv; use rain_math_float::Float; -use rain_orderbook_subgraph_client::types::common::*; +use raindex_subgraph_client::types::common::*; use serde::{Deserialize, Serialize}; use super::FlattenError; @@ -44,10 +44,10 @@ impl TryIntoCsv for Vec {} #[cfg(test)] mod tests { use super::*; - use rain_orderbook_subgraph_client::types::common::{ + use raindex_subgraph_client::types::common::{ SgBigInt, SgBytes, SgErc20, SgOrderAsIO, SgOrderbook, SgVault, SgVaultBalanceChangeType, }; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; #[allow(clippy::too_many_arguments)] fn create_sg_vault( diff --git a/crates/common/src/types/vault_balance_change_flattened.rs b/crates/common/src/types/vault_balance_change_flattened.rs index 87c4eda76e..622cb71227 100644 --- a/crates/common/src/types/vault_balance_change_flattened.rs +++ b/crates/common/src/types/vault_balance_change_flattened.rs @@ -1,6 +1,6 @@ use crate::{csv::TryIntoCsv, utils::timestamp::format_bigint_timestamp_display}; use rain_math_float::Float; -use rain_orderbook_subgraph_client::types::common::*; +use raindex_subgraph_client::types::common::*; use serde::{Deserialize, Serialize}; use super::FlattenError; @@ -77,11 +77,11 @@ mod tests { use super::*; use crate::utils::timestamp::format_bigint_timestamp_display; use rain_math_float::FloatError; - use rain_orderbook_subgraph_client::types::common::{ + use raindex_subgraph_client::types::common::{ SgBigInt, SgBytes, SgErc20, SgOrderbook, SgTransaction, SgVaultBalanceChangeUnwrapped, SgVaultBalanceChangeVault, }; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; fn mock_sg_vault_balance_change_unwrapped( timestamp_val: &str, diff --git a/crates/common/src/unit_tests.rs b/crates/common/src/unit_tests.rs index ef0aa9046b..066a5017b1 100644 --- a/crates/common/src/unit_tests.rs +++ b/crates/common/src/unit_tests.rs @@ -13,7 +13,7 @@ use rain_interpreter_eval::{ fork::{Forker, NewForkedEvm}, trace::{RainEvalResultFromRawCallResultError, RainEvalResults}, }; -use rain_orderbook_app_settings::{ +use raindex_app_settings::{ blocks::BlockError, rainlang::RainlangCfg, unit_test::TestConfig, @@ -437,8 +437,8 @@ impl TestRunner { #[cfg(test)] mod tests { use super::*; - use rain_orderbook_app_settings::{spec_version::SpecVersion, unit_test::UnitTestConfigSource}; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_app_settings::{spec_version::SpecVersion, unit_test::UnitTestConfigSource}; + use raindex_test_fixtures::LocalEvm; fn get_test_config(test_dotrain: &str) -> TestConfig { let frontmatter = RainDocument::get_front_matter(test_dotrain).unwrap(); diff --git a/crates/common/src/withdraw.rs b/crates/common/src/withdraw.rs index dbc1129eee..174e076c12 100644 --- a/crates/common/src/withdraw.rs +++ b/crates/common/src/withdraw.rs @@ -8,7 +8,7 @@ use alloy_ethers_typecast::{WriteTransaction, WriteTransactionStatus}; use serde::{Deserialize, Serialize}; use rain_math_float::Float; -use rain_orderbook_bindings::IRaindexV6::withdraw4Call; +use raindex_bindings::IRaindexV6::withdraw4Call; #[derive(Clone, Deserialize, Serialize, Debug)] pub struct WithdrawArgs { diff --git a/crates/integration_tests/Cargo.toml b/crates/integration_tests/Cargo.toml index 8babd28d72..7c48631957 100644 --- a/crates/integration_tests/Cargo.toml +++ b/crates/integration_tests/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "rain_orderbook_integration_tests" +name = "raindex_integration_tests" version.workspace = true edition.workspace = true license.workspace = true @@ -10,9 +10,9 @@ publish = false [dev-dependencies] tokio = { workspace = true } -rain_orderbook_app_settings = { workspace = true } -rain_orderbook_test_fixtures = { workspace = true } +raindex_app_settings = { workspace = true } +raindex_test_fixtures = { workspace = true } alloy = { workspace = true, features = ["full", "node-bindings"] } -rain_orderbook_common = { workspace = true } +raindex_common = { workspace = true } serde_json = { workspace = true } rain-math-float.workspace = true diff --git a/crates/integration_tests/src/lib.rs b/crates/integration_tests/src/lib.rs index f16a0ed43e..f809ebebeb 100644 --- a/crates/integration_tests/src/lib.rs +++ b/crates/integration_tests/src/lib.rs @@ -9,9 +9,9 @@ mod tests { rpc::types::TransactionRequest, }; use rain_math_float::Float; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_common::{add_order::AddOrderArgs, dotrain_order::DotrainOrder}; - use rain_orderbook_test_fixtures::{LocalEvm, Orderbook::QuoteV2}; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_common::{add_order::AddOrderArgs, dotrain_order::DotrainOrder}; + use raindex_test_fixtures::{LocalEvm, Orderbook::QuoteV2}; #[tokio::test] async fn test_post_task_set() { diff --git a/crates/js_api/ARCHITECTURE.md b/crates/js_api/ARCHITECTURE.md index 9ff1ed82d6..327838391a 100644 --- a/crates/js_api/ARCHITECTURE.md +++ b/crates/js_api/ARCHITECTURE.md @@ -1,5 +1,5 @@ **Overview** -- Purpose: `rain_orderbook_js_api` exposes a single, browser-friendly WebAssembly surface for the Rain Orderbook application. It bridges YAML-based ā€œdotrainā€ order configuration, on-chain ERC‑20/token metadata, and contract call generation into a typed JavaScript/TypeScript API. +- Purpose: `raindex_js_api` exposes a single, browser-friendly WebAssembly surface for the Rain Orderbook application. It bridges YAML-based ā€œdotrainā€ order configuration, on-chain ERC‑20/token metadata, and contract call generation into a typed JavaScript/TypeScript API. - Target: Compiles as a `cdylib` for wasm and is designed to be consumed from JS environments (webapps). All public APIs are exported via `wasm_bindgen_utils` macros and return ergonomic results with rich, user‑readable errors. - Scope: Includes high-level GUI helpers for interactive order building, a fetchable registry of orders, and low-level helpers for hashing and ABI calldata generation. It re-exports certain sibling crates so their wasm bindings are reachable from a single import. @@ -11,7 +11,7 @@ **Top-Level Layout** - `src/lib.rs` - Exposes modules only when targeting wasm: `bindings`, `gui`, `registry`, `yaml`. - - Re-exports crates so their wasm bindings are available from this single module: `rain_orderbook_app_settings`, `rain_orderbook_common`, `rain_orderbook_subgraph_client`. + - Re-exports crates so their wasm bindings are available from this single module: `raindex_app_settings`, `raindex_common`, `raindex_subgraph_client`. - Appends a small TS section defining `Address` and `Hex` template literal types for better typing on the JS side. **FFI & Error Conventions** @@ -143,9 +143,9 @@ - Errors: `OrderbookYamlError` with readable messaging, converted to JS. **External Crates & Interactions** -- `rain_orderbook_app_settings`: typed config model + YAML parsing helpers for GUI sections, deployments, networks, orders, select-tokens, and validation rules. -- `rain_orderbook_common`: higher-level order manipulation (compose Rainlang, add order args), ERC‑20 RPC client, transaction helpers, and formatting utilities. -- `rain_orderbook_bindings`: generated Solidity bindings for `IOrderBookV5` (e.g., `deposit3`, `multicall`, `takeOrders3`). +- `raindex_app_settings`: typed config model + YAML parsing helpers for GUI sections, deployments, networks, orders, select-tokens, and validation rules. +- `raindex_common`: higher-level order manipulation (compose Rainlang, add order args), ERC‑20 RPC client, transaction helpers, and formatting utilities. +- `raindex_bindings`: generated Solidity bindings for `IOrderBookV5` (e.g., `deposit3`, `multicall`, `takeOrders3`). - `alloy`: ABI encoding/decoding, primitives (`Address`, `Bytes`, `U256`, keccak256), and Solidity type utilities. - `wasm-bindgen-utils`: export macro, JS bridging, `WasmEncodedError` packaging. @@ -191,4 +191,4 @@ - `const registry = await DotrainRegistry.new(registryUrl)` → inspect orders/deployments → `await registry.getGui(orderKey, deploymentKey, serializedState?, onStateChanged?)`. **Summary** -- `rain_orderbook_js_api` is the JS/WASM gateway for building, validating, and deploying Rain Orderbook orders from YAML+Rainlang definitions. It centralizes: YAML parsing and validation, user input state, token selection and metadata, field and deposit validation, vault ID management, transaction calldata generation (approvals, deposits, add order, multicall), registry-driven content fetching, and robust error handling—exposed as a typed, ergonomic TypeScript surface. +- `raindex_js_api` is the JS/WASM gateway for building, validating, and deploying Rain Orderbook orders from YAML+Rainlang definitions. It centralizes: YAML parsing and validation, user input state, token selection and metadata, field and deposit validation, vault ID management, transaction calldata generation (approvals, deposits, add order, multicall), registry-driven content fetching, and robust error handling—exposed as a typed, ergonomic TypeScript surface. diff --git a/crates/js_api/Cargo.toml b/crates/js_api/Cargo.toml index 9d7d0f2004..eee4356a65 100644 --- a/crates/js_api/Cargo.toml +++ b/crates/js_api/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "rain_orderbook_js_api" +name = "raindex_js_api" description = "Javascript bindings for common functions accross the app." version.workspace = true edition.workspace = true @@ -16,11 +16,11 @@ cynic = { workspace = true } reqwest = { workspace = true } thiserror = { workspace = true } futures = { workspace = true } -rain_orderbook_common = { workspace = true } -rain_orderbook_app_settings = { workspace = true } -rain_orderbook_subgraph_client = { workspace = true } -rain_orderbook_bindings = { workspace = true } -rain_orderbook_quote = { workspace = true } +raindex_common = { workspace = true } +raindex_app_settings = { workspace = true } +raindex_subgraph_client = { workspace = true } +raindex_bindings = { workspace = true } +raindex_quote = { workspace = true } alloy-ethers-typecast = { workspace = true } wasm-bindgen-utils = { workspace = true } tokio = { workspace = true, features = [ diff --git a/crates/js_api/src/bindings/mod.rs b/crates/js_api/src/bindings/mod.rs index ca116f6bf4..30012fc0f9 100644 --- a/crates/js_api/src/bindings/mod.rs +++ b/crates/js_api/src/bindings/mod.rs @@ -8,7 +8,7 @@ use alloy::{ }, sol_types::SolCall, }; -use rain_orderbook_bindings::IRaindexV6::{takeOrders4Call, OrderV4, TakeOrdersConfigV5}; +use raindex_bindings::IRaindexV6::{takeOrders4Call, OrderV4, TakeOrdersConfigV5}; use serde::{Deserialize, Serialize}; use wasm_bindgen_utils::{impl_wasm_traits, prelude::*}; diff --git a/crates/js_api/src/gui/deposits.rs b/crates/js_api/src/gui/deposits.rs index e44fcd60a7..0789b4efce 100644 --- a/crates/js_api/src/gui/deposits.rs +++ b/crates/js_api/src/gui/deposits.rs @@ -1,5 +1,5 @@ use super::*; -use rain_orderbook_app_settings::gui::GuiDepositCfg; +use raindex_app_settings::gui::GuiDepositCfg; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Tsify)] pub struct TokenDeposit { diff --git a/crates/js_api/src/gui/mod.rs b/crates/js_api/src/gui/mod.rs index 24a1531e69..2ec1a3f303 100644 --- a/crates/js_api/src/gui/mod.rs +++ b/crates/js_api/src/gui/mod.rs @@ -4,7 +4,7 @@ use base64::{engine::general_purpose::URL_SAFE, Engine}; use flate2::{read::GzDecoder, write::GzEncoder, Compression}; use rain_math_float::FloatError; use rain_metaboard_subgraph::metaboard_client::MetaboardSubgraphClientError; -use rain_orderbook_app_settings::{ +use raindex_app_settings::{ deployment::DeploymentCfg, gui::{ GuiCfg, GuiDeploymentCfg, GuiFieldDefinitionCfg, GuiPresetCfg, NameAndDescriptionCfg, @@ -17,8 +17,8 @@ use rain_orderbook_app_settings::{ emitter, YamlError, YamlParsable, }, }; -pub use rain_orderbook_common::erc20::ExtendedTokenInfo; -use rain_orderbook_common::{ +pub use raindex_common::erc20::ExtendedTokenInfo; +use raindex_common::{ dotrain::{types::patterns::FRONTMATTER_SEPARATOR, RainDocument}, dotrain_order::{DotrainOrder, DotrainOrderError}, erc20::ERC20, @@ -668,7 +668,7 @@ pub enum GuiError { #[error(transparent)] ReadableClientError(#[from] ReadableClientError), #[error(transparent)] - DepositError(#[from] rain_orderbook_common::deposit::DepositError), + DepositError(#[from] raindex_common::deposit::DepositError), #[error(transparent)] ParseError(#[from] alloy::primitives::ruint::ParseError), #[error(transparent)] @@ -679,12 +679,12 @@ pub enum GuiError { UnitsError(#[from] alloy::primitives::utils::UnitsError), #[error(transparent)] WritableTransactionExecuteError( - #[from] rain_orderbook_common::transaction::WritableTransactionExecuteError, + #[from] raindex_common::transaction::WritableTransactionExecuteError, ), #[error(transparent)] - AddOrderArgsError(#[from] rain_orderbook_common::add_order::AddOrderArgsError), + AddOrderArgsError(#[from] raindex_common::add_order::AddOrderArgsError), #[error(transparent)] - ERC20Error(#[from] rain_orderbook_common::erc20::Error), + ERC20Error(#[from] raindex_common::erc20::Error), #[error(transparent)] SolTypesError(#[from] alloy::sol_types::Error), #[error(transparent)] @@ -820,8 +820,8 @@ impl From for WasmEncodedError { #[cfg(test)] mod tests { use super::*; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_app_settings::yaml::FieldErrorKind; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_app_settings::yaml::FieldErrorKind; use wasm_bindgen_test::wasm_bindgen_test; pub fn get_yaml() -> String { diff --git a/crates/js_api/src/gui/order_operations.rs b/crates/js_api/src/gui/order_operations.rs index 147b327965..8c648695d3 100644 --- a/crates/js_api/src/gui/order_operations.rs +++ b/crates/js_api/src/gui/order_operations.rs @@ -9,14 +9,14 @@ use rain_metaboard_subgraph::metaboard_client::{ }; use rain_metaboard_subgraph::types::metas::BigInt as MetaBigInt; use rain_metadata::RainMetaDocumentV1Item; -use rain_orderbook_app_settings::{ +use raindex_app_settings::{ order::{OrderIOCfg, VaultType}, orderbook::OrderbookCfg, }; -use rain_orderbook_bindings::{ +use raindex_bindings::{ IRaindexV6::deposit4Call, OrderBook::multicallCall, IERC20::approveCall, }; -use rain_orderbook_common::{ +use raindex_common::{ add_order::AddOrderArgs, deposit::DepositArgs, erc20::ERC20, transaction::TransactionArgs, }; use std::{collections::HashMap, str::FromStr, sync::Arc}; @@ -487,7 +487,7 @@ impl DotrainOrderGui { decimals, }; let calldata = deposit4Call::try_from(deposit_args) - .map_err(rain_orderbook_common::deposit::DepositError::from)? + .map_err(raindex_common::deposit::DepositError::from)? .abi_encode(); calldatas.push(Bytes::copy_from_slice(&calldata)); } diff --git a/crates/js_api/src/gui/select_tokens.rs b/crates/js_api/src/gui/select_tokens.rs index 705be8e644..2d12eff68c 100644 --- a/crates/js_api/src/gui/select_tokens.rs +++ b/crates/js_api/src/gui/select_tokens.rs @@ -1,11 +1,11 @@ use super::*; use futures::StreamExt; use rain_math_float::Float; -use rain_orderbook_app_settings::{ +use raindex_app_settings::{ deployment::DeploymentCfg, gui::GuiSelectTokensCfg, network::NetworkCfg, order::OrderCfg, token::TokenCfg, yaml::YamlParsableHash, }; -use rain_orderbook_common::raindex_client::vaults::AccountBalance; +use raindex_common::raindex_client::vaults::AccountBalance; use std::str::FromStr; const MAX_CONCURRENT_FETCHES: usize = 5; @@ -799,7 +799,7 @@ mod tests { use crate::gui::{DotrainOrderGui, GuiError}; use alloy::primitives::Address; use httpmock::MockServer; - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::spec_version::SpecVersion; use serde_json::json; use std::str::FromStr; diff --git a/crates/js_api/src/gui/state_management.rs b/crates/js_api/src/gui/state_management.rs index 6a57c32100..ca041cb890 100644 --- a/crates/js_api/src/gui/state_management.rs +++ b/crates/js_api/src/gui/state_management.rs @@ -3,7 +3,7 @@ use rain_metadata::types::dotrain::{ gui_state_v1::{DotrainGuiStateV1, ShortenedTokenCfg, ValueCfg}, source_v1::DotrainSourceV1, }; -use rain_orderbook_app_settings::{ +use raindex_app_settings::{ gui::GuiDepositCfg, order::{OrderIOCfg, VaultType}, token::TokenCfg, @@ -547,11 +547,11 @@ mod tests { }; use alloy::primitives::{Address, U256}; use js_sys::{eval, Reflect}; - use rain_orderbook_app_settings::{ + use raindex_app_settings::{ network::NetworkCfg, order::VaultType, yaml::YamlParsableHash, }; - use rain_orderbook_common::dotrain::RainDocument; - use rain_orderbook_common::dotrain_order::DotrainOrder; + use raindex_common::dotrain::RainDocument; + use raindex_common::dotrain_order::DotrainOrder; use std::str::FromStr; use wasm_bindgen_test::wasm_bindgen_test; diff --git a/crates/js_api/src/gui/validation.rs b/crates/js_api/src/gui/validation.rs index e02c4f4a25..ed3c43a0de 100644 --- a/crates/js_api/src/gui/validation.rs +++ b/crates/js_api/src/gui/validation.rs @@ -1,5 +1,5 @@ use rain_math_float::{Float, FloatError}; -use rain_orderbook_app_settings::gui::{DepositValidationCfg, FieldValueValidationCfg}; +use raindex_app_settings::gui::{DepositValidationCfg, FieldValueValidationCfg}; use thiserror::Error; #[derive(Error, Debug)] @@ -222,7 +222,7 @@ fn validate_boolean(name: &str, value: &str) -> Result<(), GuiValidationError> { #[cfg(test)] mod tests { use super::*; - use rain_orderbook_app_settings::gui::FieldValueValidationCfg; + use raindex_app_settings::gui::FieldValueValidationCfg; use wasm_bindgen_test::wasm_bindgen_test; #[wasm_bindgen_test] diff --git a/crates/js_api/src/lib.rs b/crates/js_api/src/lib.rs index 2877031e6f..63babaab76 100644 --- a/crates/js_api/src/lib.rs +++ b/crates/js_api/src/lib.rs @@ -6,11 +6,11 @@ pub mod yaml; // re-export other crates to include their wasm bindings as single export point #[cfg(target_family = "wasm")] -pub use rain_orderbook_app_settings; +pub use raindex_app_settings; #[cfg(target_family = "wasm")] -pub use rain_orderbook_common; +pub use raindex_common; #[cfg(target_family = "wasm")] -pub use rain_orderbook_subgraph_client; +pub use raindex_subgraph_client; use wasm_bindgen_utils::prelude::wasm_bindgen; diff --git a/crates/js_api/src/rainlang.rs b/crates/js_api/src/rainlang.rs index 7f0c52fcd3..66bd8d94e2 100644 --- a/crates/js_api/src/rainlang.rs +++ b/crates/js_api/src/rainlang.rs @@ -1,7 +1,7 @@ use crate::gui::{DotrainOrderGui, GuiError}; use crate::yaml::{OrderbookYaml, OrderbookYamlError}; -use rain_orderbook_app_settings::gui::NameAndDescriptionCfg; -use rain_orderbook_common::raindex_client::{RaindexClient, RaindexError as RaindexClientError}; +use raindex_app_settings::gui::NameAndDescriptionCfg; +use raindex_common::raindex_client::{RaindexClient, RaindexError as RaindexClientError}; use reqwest; use serde::{Deserialize, Serialize}; use std::collections::{BTreeMap, HashMap}; @@ -732,7 +732,7 @@ impl DotrainRainlang { #[cfg(test)] mod tests { use super::*; - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::spec_version::SpecVersion; use std::collections::HashMap; const MOCK_REGISTRY_CONTENT: &str = r#"https://example.com/settings.yaml diff --git a/crates/js_api/src/yaml/mod.rs b/crates/js_api/src/yaml/mod.rs index 0533a6f60a..42583f7725 100644 --- a/crates/js_api/src/yaml/mod.rs +++ b/crates/js_api/src/yaml/mod.rs @@ -1,7 +1,7 @@ use std::str::FromStr; use alloy::{hex::FromHexError, primitives::Address}; -use rain_orderbook_app_settings::{ +use raindex_app_settings::{ orderbook::OrderbookCfg, remote_tokens::{ParseRemoteTokensError, RemoteTokensCfg}, spec_version::CURRENT_SPEC_VERSION, @@ -10,7 +10,7 @@ use rain_orderbook_app_settings::{ YamlError, YamlParsable, }, }; -use rain_orderbook_common::erc20::ExtendedTokenInfo; +use raindex_common::erc20::ExtendedTokenInfo; use serde::{Deserialize, Serialize}; use thiserror::Error; use wasm_bindgen_utils::prelude::*; @@ -175,7 +175,7 @@ pub enum OrderbookYamlError { #[error(transparent)] ParseRemoteTokensError(#[from] ParseRemoteTokensError), #[error(transparent)] - ERC20Error(#[from] rain_orderbook_common::erc20::Error), + ERC20Error(#[from] raindex_common::erc20::Error), } impl OrderbookYamlError { @@ -212,7 +212,7 @@ impl From for WasmEncodedError { #[cfg(test)] pub(crate) mod tests { use super::*; - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::spec_version::SpecVersion; use wasm_bindgen_test::wasm_bindgen_test; pub fn get_yaml() -> String { @@ -464,7 +464,7 @@ pub(crate) mod tests { mod non_wasm_tests { use super::*; use httpmock::MockServer; - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::spec_version::SpecVersion; use serde_json::json; #[tokio::test] diff --git a/crates/math/ARCHITECTURE.md b/crates/math/ARCHITECTURE.md index 551e9047a2..2e7ad7d080 100644 --- a/crates/math/ARCHITECTURE.md +++ b/crates/math/ARCHITECTURE.md @@ -1,4 +1,4 @@ -# rain_orderbook_math — Architecture & Design Notes +# raindex_math — Architecture & Design Notes This crate provides small, focused, and overflow‑safe helpers for 256‑bit integer math used across the Rain Orderbook codebase. It standardizes two things: @@ -161,7 +161,7 @@ Assume `amount` is a token balance in its native decimals. - Normalize to 18 decimals: ```rust use alloy::primitives::U256; - use rain_orderbook_math::BigUintMath; + use raindex_math::BigUintMath; let usdc_amount = U256::from(1_500_000u64); // 1.5 USDC with 6 decimals let wad = usdc_amount.scale_18(6)?; // 1.5 * 1e18 as U256 @@ -190,8 +190,8 @@ Assume `amount` is a token balance in its native decimals. ## File Map - `src/lib.rs` — All implementations and tests. -- `Cargo.toml` — Declares crate as `rain_orderbook_math`; depends on `alloy`, `thiserror` (and `once_cell` via workspace, unused here). +- `Cargo.toml` — Declares crate as `raindex_math`; depends on `alloy`, `thiserror` (and `once_cell` via workspace, unused here). ## Summary -`rain_orderbook_math` supplies the minimal, safe building blocks needed for consistent 18‑dec fixed‑point math on `U256`, with careful overflow handling and 512‑bit intermediates for the common mul‑then‑div pattern. Other Rain Orderbook crates rely on these helpers to normalize magnitudes and compute rates without duplicating math or risking undefined overflow behavior. +`raindex_math` supplies the minimal, safe building blocks needed for consistent 18‑dec fixed‑point math on `U256`, with careful overflow handling and 512‑bit intermediates for the common mul‑then‑div pattern. Other Rain Orderbook crates rely on these helpers to normalize magnitudes and compute rates without duplicating math or risking undefined overflow behavior. diff --git a/crates/math/Cargo.toml b/crates/math/Cargo.toml index 3308b9c814..334b7ed9fc 100644 --- a/crates/math/Cargo.toml +++ b/crates/math/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "rain_orderbook_math" -description = "Math toolings for Rain Orderbooks crates" +name = "raindex_math" +description = "Math toolings for Raindexs crates" version.workspace = true edition.workspace = true license.workspace = true diff --git a/crates/quote/ARCHITECTURE.md b/crates/quote/ARCHITECTURE.md index 93d2068615..0e137228a7 100644 --- a/crates/quote/ARCHITECTURE.md +++ b/crates/quote/ARCHITECTURE.md @@ -1,4 +1,4 @@ -# rain_orderbook_quote — Architecture & Design +# raindex_quote — Architecture & Design This crate provides all functionality to quote Rain Orderbook orders from Rust, expose the API to WASM/TypeScript, and ship a small CLI for ad‑hoc quoting and debugging. It stitches together three external systems: @@ -11,7 +11,7 @@ It also includes a debugger that can fork an EVM and trace a `quote2` call for s ## Targets and Build Modes -- Library: `rain_orderbook_quote` (default). Always built. +- Library: `raindex_quote` (default). Always built. - Binary: uses `src/main.rs` which calls the crate CLI entry `cli::main()`. - WASM: many types derive `Tsify` and use `wasm-bindgen-utils` helpers. The `cli` and `quote_debug` modules are disabled for wasm via `#[cfg(not(target_family = "wasm"))]`. @@ -86,7 +86,7 @@ Key gating: Purpose: execute `quote2` for many `QuoteTarget`s in one multicall. Flow: -1. Parse RPC URLs into `Url` and build a `ReadProvider` via `mk_read_provider(&rpcs)` from `rain_orderbook_bindings`. +1. Parse RPC URLs into `Url` and build a `ReadProvider` via `mk_read_provider(&rpcs)` from `raindex_bindings`. 2. Create a dynamic `multicall` builder; override its address if `multicall_address` is provided. 3. Optionally pin to `block_number` via `BlockId::Number(block)`. 4. For each target, push `IOrderBookV5::quote2(QuoteV2)` into the multicall. @@ -130,7 +130,7 @@ Result: a flat `Vec` that UIs can render per pair. ## CLI: `cli` module and `src/main.rs` Entrypoint: -- `src/main.rs` calls `rain_orderbook_quote::cli::main()` which initializes tracing, parses args, and delegates to `Quoter::run()`. +- `src/main.rs` calls `raindex_quote::cli::main()` which initializes tracing, parses args, and delegates to `Quoter::run()`. Arguments (selected): - `--rpc ` (required): JSON‑RPC endpoint. @@ -190,8 +190,8 @@ Purpose: Help users debug a `quote2` call by forking a chain, executing the call ## External Dependencies of Note - `alloy` primitives and `sol_types`: ABI encode/decode, EVM types, and contract call modeling. -- `rain_orderbook_bindings`: contract bindings (`IOrderBookV5`, provider helpers like `mk_read_provider`). -- `rain_orderbook_subgraph_client`: GraphQL client and types; provides `order_detail` and `batch_order_detail`. +- `raindex_bindings`: contract bindings (`IOrderBookV5`, provider helpers like `mk_read_provider`). +- `raindex_subgraph_client`: GraphQL client and types; provides `order_detail` and `batch_order_detail`. - `rain-error-decoding`: decodes revert selectors (known/unknown) into structured errors. - `alloy-ethers-typecast::ReadableClient`: convenience for fetching block number across multiple HTTP RPCs. - `rain_math_float::Float`: canonical numeric type used in quotes; serializes to hex strings and provides safe equality/formatting. @@ -209,7 +209,7 @@ The crate has extensive unit tests across modules, including: Tests use: - `httpmock` for simulating JSON‑RPC and subgraph HTTP responses. -- `rain_orderbook_test_fixtures::LocalEvm` to spawn a local chain with tokens and an orderbook. +- `raindex_test_fixtures::LocalEvm` to spawn a local chain with tokens and an orderbook. ## Invariants and Edge Cases @@ -231,7 +231,7 @@ Tests use: - Or build `QuoteSpec`s and call `BatchQuoteSpec::do_quote(subgraph_url, rpcs, block, None, None)`. - CLI: - - Direct targets: `cargo run -p rain_orderbook_quote -- --rpc --target ` + - Direct targets: `cargo run -p raindex_quote -- --rpc --target ` - Specs via subgraph: `--spec --sg ` - Packed bytes: `-i --sg ` where `` is repeated 54‑byte chunks. diff --git a/crates/quote/Cargo.toml b/crates/quote/Cargo.toml index 0ebe4fa4dd..cf52b8d65f 100644 --- a/crates/quote/Cargo.toml +++ b/crates/quote/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "rain_orderbook_quote" -description = "Quote Rain Orderbook Orders" +name = "raindex_quote" +description = "Quote Raindex Orders" version.workspace = true edition.workspace = true license.workspace = true @@ -14,8 +14,8 @@ crate-type = ["rlib"] [dependencies] rain-math-float.workspace = true rain-metadata = { workspace = true } -rain_orderbook_bindings = { workspace = true } -rain_orderbook_subgraph_client = { workspace = true } +raindex_bindings = { workspace = true } +raindex_subgraph_client = { workspace = true } futures = { workspace = true } rain-error-decoding = { workspace = true } alloy = { workspace = true, features = ["sol-types"] } @@ -50,9 +50,9 @@ getrandom = { workspace = true } httpmock = "0.7.0" [dev-dependencies] -rain_orderbook_test_fixtures = { workspace = true } -rain_orderbook_common = { workspace = true } +raindex_test_fixtures = { workspace = true } +raindex_common = { workspace = true } wasm-bindgen-test = "0.3" -rain_orderbook_app_settings = { workspace = true } +raindex_app_settings = { workspace = true } tempfile.workspace = true async-trait = "0.1" diff --git a/crates/quote/src/cli/input.rs b/crates/quote/src/cli/input.rs index 6fad13752c..d05d5c54fb 100644 --- a/crates/quote/src/cli/input.rs +++ b/crates/quote/src/cli/input.rs @@ -5,7 +5,7 @@ use alloy::primitives::{ }; use alloy::sol_types::SolType; use clap::Args; -use rain_orderbook_bindings::IRaindexV6::{OrderV4, QuoteV2}; +use raindex_bindings::IRaindexV6::{OrderV4, QuoteV2}; use std::str::FromStr; /// Group of valid input formats @@ -202,7 +202,7 @@ mod tests { use super::*; use alloy::primitives::hex::encode_prefixed; use alloy::sol_types::SolValue; - use rain_orderbook_bindings::IRaindexV6::{EvaluableV4, OrderV4}; + use raindex_bindings::IRaindexV6::{EvaluableV4, OrderV4}; #[test] fn test_parse_input() { diff --git a/crates/quote/src/cli/mod.rs b/crates/quote/src/cli/mod.rs index 0083583a3d..9daafe4cba 100644 --- a/crates/quote/src/cli/mod.rs +++ b/crates/quote/src/cli/mod.rs @@ -153,7 +153,7 @@ mod tests { use clap::CommandFactory; use httpmock::{Method::POST, MockServer}; use rain_math_float::Float; - use rain_orderbook_bindings::IRaindexV6::{quote2Call, quote2Return, OrderV4, IOV2}; + use raindex_bindings::IRaindexV6::{quote2Call, quote2Return, OrderV4, IOV2}; use serde_json::json; use std::{fs::read_to_string, str::FromStr}; use tempfile::NamedTempFile; diff --git a/crates/quote/src/error.rs b/crates/quote/src/error.rs index 70b17ef295..9264fe6d49 100644 --- a/crates/quote/src/error.rs +++ b/crates/quote/src/error.rs @@ -4,8 +4,8 @@ use alloy::{ }; use alloy_ethers_typecast::ReadableClientError; use rain_error_decoding::{AbiDecodeFailedErrors, AbiDecodedErrorType}; -use rain_orderbook_bindings::provider::ReadProviderError; -use rain_orderbook_subgraph_client::{ +use raindex_bindings::provider::ReadProviderError; +use raindex_subgraph_client::{ types::order_detail_traits::OrderDetailError, OrderbookSubgraphClientError, }; use thiserror::Error; diff --git a/crates/quote/src/main.rs b/crates/quote/src/main.rs index 44c8ec3294..7877aa69ac 100644 --- a/crates/quote/src/main.rs +++ b/crates/quote/src/main.rs @@ -1,5 +1,5 @@ #[cfg(not(target_family = "wasm"))] #[tokio::main] async fn main() -> anyhow::Result<()> { - rain_orderbook_quote::cli::main().await + raindex_quote::cli::main().await } diff --git a/crates/quote/src/oracle.rs b/crates/quote/src/oracle.rs index 41eeda574b..8c6137ca04 100644 --- a/crates/quote/src/oracle.rs +++ b/crates/quote/src/oracle.rs @@ -1,7 +1,7 @@ use alloy::primitives::{Address, Bytes, FixedBytes, U256}; use alloy::sol_types::SolValue; -use rain_orderbook_bindings::IRaindexV6::{OrderV4, SignedContextV1}; -use rain_orderbook_subgraph_client::types::common::SgOrder; +use raindex_bindings::IRaindexV6::{OrderV4, SignedContextV1}; +use raindex_subgraph_client::types::common::SgOrder; use reqwest::Client; use serde::{Deserialize, Serialize}; use url::Url; @@ -187,7 +187,7 @@ pub fn extract_oracle_url(order: &SgOrder) -> Option { mod tests { use super::*; use alloy::primitives::{address, FixedBytes}; - use rain_orderbook_bindings::IRaindexV6::{EvaluableV4, OrderV4, IOV2}; + use raindex_bindings::IRaindexV6::{EvaluableV4, OrderV4, IOV2}; #[test] fn test_oracle_response_to_signed_context() { diff --git a/crates/quote/src/order_quotes.rs b/crates/quote/src/order_quotes.rs index 9a0b5f350c..50edbabacd 100644 --- a/crates/quote/src/order_quotes.rs +++ b/crates/quote/src/order_quotes.rs @@ -5,8 +5,8 @@ use crate::{ }; use alloy::primitives::{Address, U256}; use alloy_ethers_typecast::ReadableClient; -use rain_orderbook_bindings::IRaindexV6::{OrderV4, QuoteV2}; -use rain_orderbook_subgraph_client::types::common::SgOrder; +use raindex_bindings::IRaindexV6::{OrderV4, QuoteV2}; +use raindex_subgraph_client::types::common::SgOrder; use serde::{Deserialize, Serialize}; use std::str::FromStr; #[cfg(target_family = "wasm")] @@ -209,14 +209,14 @@ mod tests { }; use alloy_ethers_typecast::ReadableClientError; use rain_math_float::Float; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_common::{add_order::AddOrderArgs, dotrain_order::DotrainOrder}; - use rain_orderbook_subgraph_client::types::{ + use raindex_app_settings::spec_version::SpecVersion; + use raindex_common::{add_order::AddOrderArgs, dotrain_order::DotrainOrder}; + use raindex_subgraph_client::types::{ common::{SgBigInt, SgBytes, SgErc20, SgOrderbook, SgVault}, order_detail_traits::OrderDetailError, }; - use rain_orderbook_subgraph_client::utils::float::*; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_subgraph_client::utils::float::*; + use raindex_test_fixtures::LocalEvm; struct TestSetup { local_evm: LocalEvm, diff --git a/crates/quote/src/quote.rs b/crates/quote/src/quote.rs index ea3d97769d..e0031e772d 100644 --- a/crates/quote/src/quote.rs +++ b/crates/quote/src/quote.rs @@ -13,8 +13,8 @@ use url::Url; use wasm_bindgen_utils::{add_ts_content, impl_wasm_traits, prelude::*}; use rain_math_float::Float; -use rain_orderbook_bindings::IRaindexV6::{quote2Return, OrderV4, QuoteV2, SignedContextV1}; -use rain_orderbook_subgraph_client::{ +use raindex_bindings::IRaindexV6::{quote2Return, OrderV4, QuoteV2, SignedContextV1}; +use raindex_subgraph_client::{ types::{common::SgBytes, Id}, utils::make_order_id, OrderbookSubgraphClient, @@ -327,8 +327,8 @@ mod tests { use alloy::transports::TransportError; use httpmock::{Method::POST, MockServer}; use rain_error_decoding::AbiDecodedErrorType; - use rain_orderbook_bindings::IRaindexV6::{quote2Call, QuoteV2, IOV2}; - use rain_orderbook_subgraph_client::OrderbookSubgraphClientError; + use raindex_bindings::IRaindexV6::{quote2Call, QuoteV2, IOV2}; + use raindex_subgraph_client::OrderbookSubgraphClientError; use serde_json::{json, Value}; // helper fn to build some test data diff --git a/crates/quote/src/quote_debug.rs b/crates/quote/src/quote_debug.rs index 665e676e5b..55363ead57 100644 --- a/crates/quote/src/quote_debug.rs +++ b/crates/quote/src/quote_debug.rs @@ -7,7 +7,7 @@ use rain_interpreter_eval::{ fork::{Forker, NewForkedEvm}, trace::{RainEvalResult, RainEvalResultFromRawCallResultError}, }; -use rain_orderbook_bindings::IRaindexV6::quote2Call; +use raindex_bindings::IRaindexV6::quote2Call; use url::Url; pub struct NewQuoteDebugger { @@ -88,11 +88,11 @@ mod tests { use alloy::primitives::{fixed_bytes, U256}; use alloy::sol_types::{SolCall, SolValue}; use httpmock::MockServer; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_bindings::IRaindexV6::{OrderV4, QuoteV2}; - use rain_orderbook_common::add_order::AddOrderArgs; - use rain_orderbook_common::dotrain_order::DotrainOrder; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_bindings::IRaindexV6::{OrderV4, QuoteV2}; + use raindex_common::add_order::AddOrderArgs; + use raindex_common::dotrain_order::DotrainOrder; + use raindex_test_fixtures::LocalEvm; use std::str::FromStr; #[tokio::test(flavor = "multi_thread", worker_threads = 10)] diff --git a/crates/quote/src/rpc.rs b/crates/quote/src/rpc.rs index ad565ce49d..8138d37a1f 100644 --- a/crates/quote/src/rpc.rs +++ b/crates/quote/src/rpc.rs @@ -8,8 +8,8 @@ use alloy::{ primitives::Address, }; use rain_error_decoding::{AbiDecodedErrorType, ErrorRegistry}; -use rain_orderbook_bindings::provider::{mk_read_provider, ReadProvider}; -use rain_orderbook_bindings::IRaindexV6::{quote2Call, quote2Return, IRaindexV6Instance}; +use raindex_bindings::provider::{mk_read_provider, ReadProvider}; +use raindex_bindings::IRaindexV6::{quote2Call, quote2Return, IRaindexV6Instance}; use url::Url; const DEFAULT_QUOTE_CHUNK_SIZE: usize = 16; @@ -251,7 +251,7 @@ mod tests { use httpmock::{Method::POST, MockServer}; use rain_error_decoding::ErrorRegistry; use rain_math_float::Float; - use rain_orderbook_bindings::IRaindexV6::{quote2Call, quote2Return}; + use raindex_bindings::IRaindexV6::{quote2Call, quote2Return}; use serde_json::json; #[test] diff --git a/crates/rest_api/Cargo.toml b/crates/rest_api/Cargo.toml index bb95ea3614..a2d72a553b 100644 --- a/crates/rest_api/Cargo.toml +++ b/crates/rest_api/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "rain_orderbook_rest_api" -description = "REST API server for rain orderbook" +name = "raindex_rest_api" +description = "REST API server for raindex" version.workspace = true edition.workspace = true license.workspace = true @@ -8,11 +8,11 @@ homepage.workspace = true publish = false [[bin]] -name = "rain-orderbook-api" +name = "raindex-api" path = "src/main.rs" [dependencies] -rain_orderbook_common = { workspace = true } +raindex_common = { workspace = true } rocket = { version = "0.5.1", features = ["json"] } rocket_cors = "0.6" serde = { workspace = true, features = ["derive"] } diff --git a/crates/rest_api/src/error.rs b/crates/rest_api/src/error.rs index 71981ba305..920795a7aa 100644 --- a/crates/rest_api/src/error.rs +++ b/crates/rest_api/src/error.rs @@ -1,4 +1,4 @@ -use rain_orderbook_common::raindex_client::RaindexError; +use raindex_common::raindex_client::RaindexError; use rocket::http::Status; use rocket::response::{self, Responder}; use rocket::serde::json::Json; diff --git a/crates/rest_api/src/routes/take_orders.rs b/crates/rest_api/src/routes/take_orders.rs index a1549ee949..ac7ec3c837 100644 --- a/crates/rest_api/src/routes/take_orders.rs +++ b/crates/rest_api/src/routes/take_orders.rs @@ -1,7 +1,7 @@ use crate::error::{ApiError, ApiErrorResponse}; -use rain_orderbook_common::raindex_client::take_orders::TakeOrdersRequest; -use rain_orderbook_common::raindex_client::RaindexClient; -use rain_orderbook_common::take_orders::TakeOrdersMode; +use raindex_common::raindex_client::take_orders::TakeOrdersRequest; +use raindex_common::raindex_client::RaindexClient; +use raindex_common::take_orders::TakeOrdersMode; use rocket::serde::json::Json; use rocket::{post, Route}; use serde::{Deserialize, Serialize}; @@ -148,7 +148,7 @@ async fn execute_take_orders( if let Some(approval_info) = result.approval_info() { let amount = approval_info.amount().format().map_err(|e| { - ApiError::Raindex(rain_orderbook_common::raindex_client::RaindexError::Float( + ApiError::Raindex(raindex_common::raindex_client::RaindexError::Float( e, )) })?; @@ -162,7 +162,7 @@ async fn execute_take_orders( })) } else if let Some(take_orders_info) = result.take_orders_info() { let effective_price = take_orders_info.effective_price().format().map_err(|e| { - ApiError::Raindex(rain_orderbook_common::raindex_client::RaindexError::Float( + ApiError::Raindex(raindex_common::raindex_client::RaindexError::Float( e, )) })?; @@ -172,7 +172,7 @@ async fn execute_take_orders( .iter() .map(|p| { p.format().map_err(|e| { - ApiError::Raindex(rain_orderbook_common::raindex_client::RaindexError::Float( + ApiError::Raindex(raindex_common::raindex_client::RaindexError::Float( e, )) }) @@ -180,13 +180,13 @@ async fn execute_take_orders( .collect(); let expected_sell = take_orders_info.expected_sell().format().map_err(|e| { - ApiError::Raindex(rain_orderbook_common::raindex_client::RaindexError::Float( + ApiError::Raindex(raindex_common::raindex_client::RaindexError::Float( e, )) })?; let max_sell_cap = take_orders_info.max_sell_cap().format().map_err(|e| { - ApiError::Raindex(rain_orderbook_common::raindex_client::RaindexError::Float( + ApiError::Raindex(raindex_common::raindex_client::RaindexError::Float( e, )) })?; diff --git a/crates/settings/Cargo.toml b/crates/settings/Cargo.toml index a6e95db656..78730c4c1e 100644 --- a/crates/settings/Cargo.toml +++ b/crates/settings/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "rain_orderbook_app_settings" -description = "Rain Orderbook app settings parsing & validation" +name = "raindex_app_settings" +description = "Raindex app settings parsing & validation" version.workspace = true edition.workspace = true license.workspace = true @@ -18,7 +18,7 @@ serde_json = { workspace = true } strict-yaml-rust = { workspace = true } alloy = { workspace = true, features = ["serde", "rand"] } reqwest = { workspace = true } -rain_orderbook_bindings = { workspace = true } +raindex_bindings = { workspace = true } futures = { workspace = true } wasm-bindgen-utils = { workspace = true } diff --git a/crates/settings/src/gui.rs b/crates/settings/src/gui.rs index b5c2b83c42..4b47eaede6 100644 --- a/crates/settings/src/gui.rs +++ b/crates/settings/src/gui.rs @@ -1195,7 +1195,7 @@ mod tests { outputs: vec![], network: mock_network(), rainlang: None, - orderbook: None, + raindex: None, oracle_url: None, }; let deployment = DeploymentCfg { diff --git a/crates/settings/src/lib.rs b/crates/settings/src/lib.rs index 053c8d05ae..5370fbc896 100644 --- a/crates/settings/src/lib.rs +++ b/crates/settings/src/lib.rs @@ -9,7 +9,7 @@ pub mod local_db_sync; pub mod metaboard; pub mod network; pub mod order; -pub mod orderbook; +pub mod raindex; pub mod plot_source; pub mod rainlang; pub mod remote; @@ -30,7 +30,7 @@ pub(crate) use gui::*; pub(crate) use local_db_sync::*; pub(crate) use network::*; pub(crate) use order::*; -pub(crate) use orderbook::*; +pub(crate) use raindex::*; pub(crate) use plot_source::*; pub(crate) use rainlang::*; pub(crate) use remote_networks::*; diff --git a/crates/settings/src/order.rs b/crates/settings/src/order.rs index 2debcdc43d..98b3006734 100644 --- a/crates/settings/src/order.rs +++ b/crates/settings/src/order.rs @@ -9,7 +9,7 @@ use std::{ use strict_yaml_rust::{strict_yaml::Hash, StrictYaml}; use thiserror::Error; -const ALLOWED_ORDER_KEYS: [&str; 5] = ["inputs", "oracle-url", "orderbook", "outputs", "rainlang"]; +const ALLOWED_ORDER_KEYS: [&str; 5] = ["inputs", "oracle-url", "raindex", "outputs", "rainlang"]; const ALLOWED_ORDER_IO_KEYS: [&str; 2] = ["token", "vault-id"]; use wasm_bindgen_utils::{impl_wasm_traits, prelude::*}; use yaml::{ @@ -55,7 +55,7 @@ pub struct OrderCfg { #[cfg_attr(target_family = "wasm", tsify(optional))] pub rainlang: Option>, #[cfg_attr(target_family = "wasm", tsify(optional))] - pub orderbook: Option>, + pub raindex: Option>, #[cfg_attr(target_family = "wasm", tsify(optional))] #[serde(rename = "oracle-url")] pub oracle_url: Option, @@ -349,9 +349,9 @@ impl OrderCfg { } } - if let Some(orderbook_key) = optional_string(order_yaml, "orderbook") { + if let Some(raindex_key) = optional_string(order_yaml, "raindex") { let key = - OrderbookCfg::parse_network_key(documents.clone(), &orderbook_key)?; + RaindexCfg::parse_network_key(documents.clone(), &raindex_key)?; if let Some(ref existing_key) = network_key { if *existing_key != key { @@ -532,7 +532,7 @@ impl YamlParsableHash for OrderCfg { let mut orders = HashMap::new(); let rainlangs = RainlangCfg::parse_all_from_yaml(documents.clone(), context); - let orderbooks = OrderbookCfg::parse_all_from_yaml(documents.clone(), context); + let raindexes = RaindexCfg::parse_all_from_yaml(documents.clone(), context); let tokens = TokenCfg::parse_all_from_yaml(documents.clone(), context); let tokens = if let Some(context) = context { @@ -609,17 +609,17 @@ impl YamlParsableHash for OrderCfg { None => None, }; - let orderbook = match optional_string(order_yaml, "orderbook") { + let orderbook = match optional_string(order_yaml, "raindex") { Some(orderbook_name) => { - let orderbooks = orderbooks.as_ref().map_err(|e| YamlError::Field { + let raindexes = raindexes.as_ref().map_err(|e| YamlError::Field { kind: FieldErrorKind::InvalidValue { - field: "orderbooks".to_string(), + field: "raindexes".to_string(), reason: e.to_string(), }, location: "root".to_string(), })?; let orderbook = Arc::new( - orderbooks + raindexes .get(&orderbook_name) .ok_or_else(|| { YamlError::KeyNotFound(orderbook_name.to_string()) @@ -934,7 +934,7 @@ impl Default for OrderCfg { outputs: vec![], network: Arc::new(NetworkCfg::default()), rainlang: None, - orderbook: None, + raindex: None, oracle_url: None, } } @@ -947,7 +947,7 @@ impl PartialEq for OrderCfg { && self.outputs == other.outputs && self.network == other.network && self.rainlang == other.rainlang - && self.orderbook == other.orderbook + && self.raindex == other.raindex && self.oracle_url == other.oracle_url } } @@ -957,7 +957,7 @@ pub enum ParseOrderConfigSourceError { #[error("Failed to parse rainlang")] RainlangParseError(ParseRainlangConfigSourceError), #[error("Failed to parse orderbook")] - OrderbookParseError(ParseOrderbookConfigSourceError), + OrderbookParseError(ParseRaindexConfigSourceError), #[error("Failed to parse token")] TokenParseError(ParseTokenConfigSourceError), #[error("Network not found for Order: {0}")] @@ -998,9 +998,9 @@ impl ParseOrderConfigSourceError { ParseOrderConfigSourceError::TokenParseError(err) => err.to_readable_msg(), ParseOrderConfigSourceError::NetworkNotFoundError(_) => - "No network could be determined for this order. Please specify a network or ensure that tokens, rainlangs, or orderbooks have valid networks.".to_string(), + "No network could be determined for this order. Please specify a network or ensure that tokens, rainlangs, or raindexes have valid networks.".to_string(), ParseOrderConfigSourceError::NetworkNotMatch => - "The networks specified in your order configuration do not match. All components (tokens, rainlangs, orderbooks) must use the same network.".to_string(), + "The networks specified in your order configuration do not match. All components (tokens, rainlangs, raindexes) must use the same network.".to_string(), ParseOrderConfigSourceError::RainlangNetworkDoesNotMatch { expected, found } => format!("Network mismatch in your YAML configuration: The rainlang is using network '{}' but the order is using network '{}'. Please ensure all components use the same network.", found, expected), ParseOrderConfigSourceError::OrderbookNetworkDoesNotMatch { expected, found } => @@ -1242,7 +1242,7 @@ orders: test ); assert_eq!( error.to_readable_msg(), - "Order configuration error in your YAML: No network could be determined for this order. Please specify a network or ensure that tokens, rainlangs, or orderbooks have valid networks." + "Order configuration error in your YAML: No network could be determined for this order. Please specify a network or ensure that tokens, rainlangs, or raindexes have valid networks." ); let yaml = r#" @@ -1258,7 +1258,7 @@ orders: ); assert_eq!( error.to_readable_msg(), - "Order configuration error in your YAML: No network could be determined for this order. Please specify a network or ensure that tokens, rainlangs, or orderbooks have valid networks." + "Order configuration error in your YAML: No network could be determined for this order. Please specify a network or ensure that tokens, rainlangs, or raindexes have valid networks." ); let yaml = r#" @@ -1274,7 +1274,7 @@ orders: ); assert_eq!( error.to_readable_msg(), - "Order configuration error in your YAML: No network could be determined for this order. Please specify a network or ensure that tokens, rainlangs, or orderbooks have valid networks." + "Order configuration error in your YAML: No network could be determined for this order. Please specify a network or ensure that tokens, rainlangs, or raindexes have valid networks." ); } @@ -1288,7 +1288,7 @@ orders: outputs: - token: usdc rainlang: mainnet - orderbook: mainnet + raindex: mainnet unknown-key: should-be-dropped another-unknown: also-dropped "#; @@ -1312,7 +1312,7 @@ orders: assert!(order_hash.contains_key(&StrictYaml::String("inputs".to_string()))); assert!(order_hash.contains_key(&StrictYaml::String("outputs".to_string()))); assert!(order_hash.contains_key(&StrictYaml::String("rainlang".to_string()))); - assert!(order_hash.contains_key(&StrictYaml::String("orderbook".to_string()))); + assert!(order_hash.contains_key(&StrictYaml::String("raindex".to_string()))); assert!(!order_hash.contains_key(&StrictYaml::String("unknown-key".to_string()))); assert!(!order_hash.contains_key(&StrictYaml::String("another-unknown".to_string()))); } diff --git a/crates/settings/src/orderbook.rs b/crates/settings/src/raindex.rs similarity index 66% rename from crates/settings/src/orderbook.rs rename to crates/settings/src/raindex.rs index ed5105a403..3d9f874936 100644 --- a/crates/settings/src/orderbook.rs +++ b/crates/settings/src/raindex.rs @@ -19,7 +19,7 @@ use yaml::{ default_document, optional_string, require_hash, require_string, YamlError, YamlParsableHash, }; -const ALLOWED_ORDERBOOK_KEYS: [&str; 6] = [ +const ALLOWED_RAINDEX_KEYS: [&str; 6] = [ "address", "deployment-block", "label", @@ -31,7 +31,7 @@ const ALLOWED_ORDERBOOK_KEYS: [&str; 6] = [ #[derive(Debug, Serialize, Deserialize, Clone)] #[cfg_attr(target_family = "wasm", derive(Tsify))] #[serde(rename_all = "camelCase")] -pub struct OrderbookCfg { +pub struct RaindexCfg { #[serde(skip, default = "default_document")] pub document: Arc>, pub key: String, @@ -46,48 +46,48 @@ pub struct OrderbookCfg { pub deployment_block: u64, } #[cfg(target_family = "wasm")] -impl_wasm_traits!(OrderbookCfg); +impl_wasm_traits!(RaindexCfg); -impl OrderbookCfg { - pub fn validate_address(address: &str) -> Result { - Address::from_str(address).map_err(ParseOrderbookConfigSourceError::AddressParseError) +impl RaindexCfg { + pub fn validate_address(address: &str) -> Result { + Address::from_str(address).map_err(ParseRaindexConfigSourceError::AddressParseError) } - pub fn validate_deployment_block(value: &str) -> Result { + pub fn validate_deployment_block(value: &str) -> Result { value .parse::() - .map_err(ParseOrderbookConfigSourceError::DeploymentBlockParseError) + .map_err(ParseRaindexConfigSourceError::DeploymentBlockParseError) } pub fn parse_network_key( documents: Vec>>, - orderbook_key: &str, + raindex_key: &str, ) -> Result { for document in &documents { let document_read = document.read().map_err(|_| YamlError::ReadLockError)?; - if let Ok(orderbooks_hash) = require_hash(&document_read, Some("orderbooks"), None) { - if let Some(orderbook_yaml) = - orderbooks_hash.get(&StrictYaml::String(orderbook_key.to_string())) + if let Ok(raindex_hash) = require_hash(&document_read, Some("raindexes"), None) { + if let Some(raindex_yaml) = + raindex_hash.get(&StrictYaml::String(raindex_key.to_string())) { - return require_string(orderbook_yaml, Some("network"), None) - .or_else(|_| Ok(orderbook_key.to_string())); + return require_string(raindex_yaml, Some("network"), None) + .or_else(|_| Ok(raindex_key.to_string())); } } } Err(YamlError::Field { - kind: FieldErrorKind::Missing(format!("network for orderbook '{}'", orderbook_key)), + kind: FieldErrorKind::Missing(format!("network for raindex '{}'", raindex_key)), location: "root".to_string(), }) } } -impl YamlParsableHash for OrderbookCfg { +impl YamlParsableHash for RaindexCfg { fn parse_all_from_yaml( documents: Vec>>, context: Option<&Context>, ) -> Result, YamlError> { - let mut orderbooks = HashMap::new(); + let mut raindexes = HashMap::new(); let networks = NetworkCfg::parse_all_from_yaml(documents.clone(), context)?; let subgraphs = SubgraphCfg::parse_all_from_yaml(documents.clone(), context)?; @@ -96,14 +96,14 @@ impl YamlParsableHash for OrderbookCfg { for document in &documents { let document_read = document.read().map_err(|_| YamlError::ReadLockError)?; - if let Ok(orderbooks_hash) = require_hash(&document_read, Some("orderbooks"), None) { - for (key_yaml, orderbook_yaml) in orderbooks_hash { - let orderbook_key = key_yaml.as_str().unwrap_or_default().to_string(); - let location = format!("orderbook '{}'", orderbook_key); + if let Ok(raindex_hash) = require_hash(&document_read, Some("raindexes"), None) { + for (key_yaml, raindex_yaml) in raindex_hash { + let raindex_key = key_yaml.as_str().unwrap_or_default().to_string(); + let location = format!("raindex '{}'", raindex_key); let address_str = - require_string(orderbook_yaml, Some("address"), Some(location.clone()))?; - let address = OrderbookCfg::validate_address(&address_str).map_err(|e| { + require_string(raindex_yaml, Some("address"), Some(location.clone()))?; + let address = RaindexCfg::validate_address(&address_str).map_err(|e| { YamlError::Field { kind: FieldErrorKind::InvalidValue { field: "address".to_string(), @@ -113,9 +113,9 @@ impl YamlParsableHash for OrderbookCfg { } })?; - let network_name = match optional_string(orderbook_yaml, "network") { + let network_name = match optional_string(raindex_yaml, "network") { Some(network_name) => network_name, - None => orderbook_key.clone(), + None => raindex_key.clone(), }; let network = networks .get(&network_name) @@ -127,9 +127,9 @@ impl YamlParsableHash for OrderbookCfg { location: location.clone(), })?; - let subgraph_name = match optional_string(orderbook_yaml, "subgraph") { + let subgraph_name = match optional_string(raindex_yaml, "subgraph") { Some(subgraph_name) => subgraph_name, - None => orderbook_key.clone(), + None => raindex_key.clone(), }; let subgraph = subgraphs @@ -142,22 +142,22 @@ impl YamlParsableHash for OrderbookCfg { location: location.clone(), })?; - let label = optional_string(orderbook_yaml, "label"); + let label = optional_string(raindex_yaml, "label"); - let local_db_remote_name = optional_string(orderbook_yaml, "local-db-remote"); + let local_db_remote_name = optional_string(raindex_yaml, "local-db-remote"); let local_db_remote = if let Some(name) = local_db_remote_name { local_db_remotes.get(&name).cloned() } else { - local_db_remotes.get(&orderbook_key).cloned() + local_db_remotes.get(&raindex_key).cloned() } .map(Arc::new); let deployment_block_str = require_string( - orderbook_yaml, + raindex_yaml, Some("deployment-block"), Some(location.clone()), )?; - let deployment_block = OrderbookCfg::validate_deployment_block( + let deployment_block = RaindexCfg::validate_deployment_block( &deployment_block_str, ) .map_err(|e| YamlError::Field { @@ -168,9 +168,9 @@ impl YamlParsableHash for OrderbookCfg { location: location.clone(), })?; - let orderbook = OrderbookCfg { + let raindex_entry = RaindexCfg { document: document.clone(), - key: orderbook_key.clone(), + key: raindex_key.clone(), address, network: Arc::new(network.clone()), subgraph: Arc::new(subgraph.clone()), @@ -179,25 +179,25 @@ impl YamlParsableHash for OrderbookCfg { deployment_block, }; - if orderbooks.contains_key(&orderbook_key) { + if raindexes.contains_key(&raindex_key) { return Err(YamlError::KeyShadowing( - orderbook_key, - "orderbooks".to_string(), + raindex_key, + "raindexes".to_string(), )); } - orderbooks.insert(orderbook_key, orderbook); + raindexes.insert(raindex_key, raindex_entry); } } } - if orderbooks.is_empty() { + if raindexes.is_empty() { return Err(YamlError::Field { - kind: FieldErrorKind::Missing("orderbooks".to_string()), + kind: FieldErrorKind::Missing("raindexes".to_string()), location: "root".to_string(), }); } - Ok(orderbooks) + Ok(raindexes) } fn sanitize_documents(documents: &[Arc>]) -> Result<(), YamlError> { @@ -207,55 +207,55 @@ impl YamlParsableHash for OrderbookCfg { continue; }; - let orderbooks_key = StrictYaml::String("orderbooks".to_string()); - let Some(orderbooks_value) = root_hash.get(&orderbooks_key) else { + let raindex_section_key = StrictYaml::String("raindexes".to_string()); + let Some(raindex_value) = root_hash.get(&raindex_section_key) else { continue; }; - let StrictYaml::Hash(ref orderbooks_hash) = *orderbooks_value else { + let StrictYaml::Hash(ref raindex_hash) = *raindex_value else { continue; }; - let mut sanitized_orderbooks: Vec<(String, StrictYaml)> = Vec::new(); + let mut sanitized_raindex_entries: Vec<(String, StrictYaml)> = Vec::new(); - for (orderbook_key, orderbook_value) in orderbooks_hash { - let Some(orderbook_key_str) = orderbook_key.as_str() else { + for (raindex_key, orderbook_value) in raindex_hash { + let Some(raindex_key_str) = raindex_key.as_str() else { continue; }; - let StrictYaml::Hash(ref orderbook_hash) = *orderbook_value else { + let StrictYaml::Hash(ref raindex_entry_hash) = *orderbook_value else { continue; }; - let mut sanitized_orderbook = Hash::new(); + let mut sanitized_raindex = Hash::new(); - for allowed_key in ALLOWED_ORDERBOOK_KEYS.iter() { + for allowed_key in ALLOWED_RAINDEX_KEYS.iter() { let key_yaml = StrictYaml::String(allowed_key.to_string()); - if let Some(v) = orderbook_hash.get(&key_yaml) { - sanitized_orderbook.insert(key_yaml, v.clone()); + if let Some(v) = raindex_entry_hash.get(&key_yaml) { + sanitized_raindex.insert(key_yaml, v.clone()); } } - sanitized_orderbooks.push(( - orderbook_key_str.to_string(), - StrictYaml::Hash(sanitized_orderbook), + sanitized_raindex_entries.push(( + raindex_key_str.to_string(), + StrictYaml::Hash(sanitized_raindex), )); } - sanitized_orderbooks.sort_by(|(a, _), (b, _)| a.cmp(b)); + sanitized_raindex_entries.sort_by(|(a, _), (b, _)| a.cmp(b)); - let mut new_orderbooks_hash = Hash::new(); - for (key, value) in sanitized_orderbooks { - new_orderbooks_hash.insert(StrictYaml::String(key), value); + let mut new_raindex_hash = Hash::new(); + for (key, value) in sanitized_raindex_entries { + new_raindex_hash.insert(StrictYaml::String(key), value); } - root_hash.insert(orderbooks_key, StrictYaml::Hash(new_orderbooks_hash)); + root_hash.insert(raindex_section_key, StrictYaml::Hash(new_raindex_hash)); } Ok(()) } } -impl Default for OrderbookCfg { +impl Default for RaindexCfg { fn default() -> Self { Self { document: Arc::new(RwLock::new(StrictYaml::String("".to_string()))), @@ -269,7 +269,7 @@ impl Default for OrderbookCfg { } } } -impl PartialEq for OrderbookCfg { +impl PartialEq for RaindexCfg { fn eq(&self, other: &Self) -> bool { self.key == other.key && self.address == other.address @@ -282,10 +282,10 @@ impl PartialEq for OrderbookCfg { } #[derive(Error, Debug, PartialEq)] -pub enum ParseOrderbookConfigSourceError { +pub enum ParseRaindexConfigSourceError { #[error("Failed to parse address")] AddressParseError(FromHexError), - #[error("Network not found for Orderbook: {0}")] + #[error("Network not found for Raindex: {0}")] NetworkNotFoundError(String), #[error("Subgraph not found: {0}")] SubgraphNotFoundError(String), @@ -293,17 +293,17 @@ pub enum ParseOrderbookConfigSourceError { DeploymentBlockParseError(ParseIntError), } -impl ParseOrderbookConfigSourceError { +impl ParseRaindexConfigSourceError { pub fn to_readable_msg(&self) -> String { match self { - ParseOrderbookConfigSourceError::AddressParseError(err) => - format!("The orderbook address in your YAML configuration is invalid. Please provide a valid EVM address: {}", err), - ParseOrderbookConfigSourceError::NetworkNotFoundError(network) => - format!("The network '{}' specified for this orderbook was not found in your YAML configuration. Please define this network or use an existing one.", network), - ParseOrderbookConfigSourceError::SubgraphNotFoundError(subgraph) => - format!("The subgraph '{}' specified for this orderbook was not found in your YAML configuration. Please define this subgraph or use an existing one.", subgraph), - ParseOrderbookConfigSourceError::DeploymentBlockParseError(err) => - format!("The deployment block in your orderbook configuration must be a valid number: {}", err), + ParseRaindexConfigSourceError::AddressParseError(err) => + format!("The raindex address in your YAML configuration is invalid. Please provide a valid EVM address: {}", err), + ParseRaindexConfigSourceError::NetworkNotFoundError(network) => + format!("The network '{}' specified for this raindex was not found in your YAML configuration. Please define this network or use an existing one.", network), + ParseRaindexConfigSourceError::SubgraphNotFoundError(subgraph) => + format!("The subgraph '{}' specified for this raindex was not found in your YAML configuration. Please define this subgraph or use an existing one.", subgraph), + ParseRaindexConfigSourceError::DeploymentBlockParseError(err) => + format!("The deployment block in your raindex configuration must be a valid number: {}", err), } } } @@ -314,11 +314,11 @@ mod tests { use crate::yaml::tests::get_document; #[test] - fn test_parse_orderbooks_from_yaml() { + fn test_parse_raindexes_from_yaml() { let yaml = r#" test: test "#; - let error = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); assert_eq!( error, YamlError::Field { @@ -339,7 +339,7 @@ networks: chain-id: 1 test: test "#; - let error = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); assert_eq!( error, YamlError::Field { @@ -362,17 +362,17 @@ subgraphs: SomeSubgraph: https://subgraph.com test: test "#; - let error = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); assert_eq!( error, YamlError::Field { - kind: FieldErrorKind::Missing("orderbooks".to_string()), + kind: FieldErrorKind::Missing("raindexes".to_string()), location: "root".to_string(), } ); assert_eq!( error.to_readable_msg(), - "Missing required field 'orderbooks' in root" + "Missing required field 'raindexes' in root" ); let yaml = r#" @@ -383,20 +383,20 @@ networks: chain-id: 1 subgraphs: SomeSubgraph: https://subgraph.com -orderbooks: - TestOrderbook: +raindexes: + TestRaindex: "#; - let error = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); assert_eq!( error, YamlError::Field { kind: FieldErrorKind::Missing("address".to_string()), - location: "orderbook 'TestOrderbook'".to_string(), + location: "raindex 'TestRaindex'".to_string(), } ); assert_eq!( error.to_readable_msg(), - "Missing required field 'address' in orderbook 'TestOrderbook'" + "Missing required field 'address' in orderbook 'TestRaindex'" ); let yaml = r#" @@ -407,12 +407,12 @@ networks: chain-id: 1 subgraphs: SomeSubgraph: https://subgraph.com -orderbooks: - TestOrderbook: +raindexes: + TestRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork "#; - let error = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); assert_eq!( error, YamlError::Field { @@ -420,10 +420,10 @@ orderbooks: field: "network".to_string(), reason: "Network 'TestNetwork' not found".to_string(), }, - location: "orderbook 'TestOrderbook'".to_string(), + location: "raindex 'TestRaindex'".to_string(), } ); - assert_eq!(error.to_readable_msg(), "Invalid value for field 'network' in orderbook 'TestOrderbook': Network 'TestNetwork' not found"); + assert_eq!(error.to_readable_msg(), "Invalid value for field 'network' in orderbook 'TestRaindex': Network 'TestNetwork' not found"); let yaml = r#" networks: @@ -433,15 +433,15 @@ networks: chain-id: 1 subgraphs: SomeSubgraph: https://subgraph.com -orderbooks: - TestOrderbook: +raindexes: + TestRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph local-db-remote: mainnet deployment-block: 12345 "#; - let error = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); assert_eq!( error, YamlError::Field { @@ -449,14 +449,14 @@ orderbooks: field: "subgraph".to_string(), reason: "Subgraph 'TestSubgraph' not found".to_string(), }, - location: "orderbook 'TestOrderbook'".to_string(), + location: "raindex 'TestRaindex'".to_string(), } ); - assert_eq!(error.to_readable_msg(), "Invalid value for field 'subgraph' in orderbook 'TestOrderbook': Subgraph 'TestSubgraph' not found"); + assert_eq!(error.to_readable_msg(), "Invalid value for field 'subgraph' in orderbook 'TestRaindex': Subgraph 'TestSubgraph' not found"); } #[test] - fn test_parse_orderbooks_from_yaml_multiple_files() { + fn test_parse_raindexes_from_yaml_multiple_files() { let yaml_one = r#" networks: TestNetwork: @@ -465,8 +465,8 @@ networks: chain-id: 1 subgraphs: TestSubgraph: https://subgraph.com -orderbooks: - OrderbookOne: +raindexes: + RaindexOne: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph @@ -474,8 +474,8 @@ orderbooks: deployment-block: 12345 "#; let yaml_two = r#" -orderbooks: - OrderbookTwo: +raindexes: + RaindexTwo: address: 0x0987654321098765432109876543210987654321 network: TestNetwork subgraph: TestSubgraph @@ -484,24 +484,24 @@ orderbooks: "#; let documents = vec![get_document(yaml_one), get_document(yaml_two)]; - let orderbooks = OrderbookCfg::parse_all_from_yaml(documents, None).unwrap(); + let raindexes = RaindexCfg::parse_all_from_yaml(documents, None).unwrap(); - assert_eq!(orderbooks.len(), 2); - assert!(orderbooks.contains_key("OrderbookOne")); - assert!(orderbooks.contains_key("OrderbookTwo")); + assert_eq!(raindexes.len(), 2); + assert!(raindexes.contains_key("RaindexOne")); + assert!(raindexes.contains_key("RaindexTwo")); assert_eq!( - orderbooks.get("OrderbookOne").unwrap().address.to_string(), + raindexes.get("RaindexOne").unwrap().address.to_string(), "0x1234567890123456789012345678901234567890" ); assert_eq!( - orderbooks.get("OrderbookTwo").unwrap().address.to_string(), + raindexes.get("RaindexTwo").unwrap().address.to_string(), "0x0987654321098765432109876543210987654321" ); } #[test] - fn test_parse_orderbooks_from_yaml_duplicate_key() { + fn test_parse_raindexes_from_yaml_duplicate_key() { let yaml_one = r#" networks: TestNetwork: @@ -510,8 +510,8 @@ networks: chain-id: 1 subgraphs: TestSubgraph: https://subgraph.com -orderbooks: - DuplicateOrderbook: +raindexes: + DuplicateRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph @@ -519,8 +519,8 @@ orderbooks: deployment-block: 12345 "#; let yaml_two = r#" -orderbooks: - DuplicateOrderbook: +raindexes: + DuplicateRaindex: address: 0x0987654321098765432109876543210987654321 network: TestNetwork subgraph: TestSubgraph @@ -529,17 +529,17 @@ orderbooks: "#; let documents = vec![get_document(yaml_one), get_document(yaml_two)]; - let error = OrderbookCfg::parse_all_from_yaml(documents, None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(documents, None).unwrap_err(); assert_eq!( error, - YamlError::KeyShadowing("DuplicateOrderbook".to_string(), "orderbooks".to_string()) + YamlError::KeyShadowing("DuplicateRaindex".to_string(), "raindexes".to_string()) ); - assert_eq!(error.to_readable_msg(), "The key 'DuplicateOrderbook' is defined multiple times in your YAML configuration at orderbooks"); + assert_eq!(error.to_readable_msg(), "The key 'DuplicateRaindex' is defined multiple times in your YAML configuration at raindexes"); } #[test] - fn test_parse_orderbook_from_yaml_network_key() { + fn test_parse_raindex_from_yaml_network_key() { let yaml = r#" networks: mainnet: @@ -548,7 +548,7 @@ networks: chain-id: 1 subgraphs: mainnet: https://subgraph.com -orderbooks: +raindexes: mainnet: address: 0x1234567890123456789012345678901234567890 network: mainnet @@ -557,7 +557,7 @@ orderbooks: "#; let documents = vec![get_document(yaml)]; - let network_key = OrderbookCfg::parse_network_key(documents, "mainnet").unwrap(); + let network_key = RaindexCfg::parse_network_key(documents, "mainnet").unwrap(); assert_eq!(network_key, "mainnet"); let yaml = r#" @@ -568,70 +568,70 @@ networks: chain-id: 1 subgraphs: mainnet: https://subgraph.com -orderbooks: +raindexes: mainnet: address: 0x1234567890123456789012345678901234567890 deployment-block: 12345 local-db-remote: mainnet "#; let documents = vec![get_document(yaml)]; - let network_key = OrderbookCfg::parse_network_key(documents, "mainnet").unwrap(); + let network_key = RaindexCfg::parse_network_key(documents, "mainnet").unwrap(); assert_eq!(network_key, "mainnet"); } #[test] fn test_parse_network_key() { let yaml = r#" -orderbooks: test +raindexes: test "#; let error = - OrderbookCfg::parse_network_key(vec![get_document(yaml)], "order1").unwrap_err(); + RaindexCfg::parse_network_key(vec![get_document(yaml)], "order1").unwrap_err(); assert_eq!( error, YamlError::Field { - kind: FieldErrorKind::Missing("network for orderbook 'order1'".to_string()), + kind: FieldErrorKind::Missing("network for raindex 'order1'".to_string()), location: "root".to_string(), } ); assert_eq!( error.to_readable_msg(), - "Missing required field 'network for orderbook 'order1'' in root" + "Missing required field 'network for raindex 'order1'' in root" ); let yaml = r#" -orderbooks: +raindexes: - test "#; let error = - OrderbookCfg::parse_network_key(vec![get_document(yaml)], "order1").unwrap_err(); + RaindexCfg::parse_network_key(vec![get_document(yaml)], "order1").unwrap_err(); assert_eq!( error, YamlError::Field { - kind: FieldErrorKind::Missing("network for orderbook 'order1'".to_string()), + kind: FieldErrorKind::Missing("network for raindex 'order1'".to_string()), location: "root".to_string(), } ); assert_eq!( error.to_readable_msg(), - "Missing required field 'network for orderbook 'order1'' in root" + "Missing required field 'network for raindex 'order1'' in root" ); let yaml = r#" -orderbooks: +raindexes: - test: test "#; let error = - OrderbookCfg::parse_network_key(vec![get_document(yaml)], "order1").unwrap_err(); + RaindexCfg::parse_network_key(vec![get_document(yaml)], "order1").unwrap_err(); assert_eq!( error, YamlError::Field { - kind: FieldErrorKind::Missing("network for orderbook 'order1'".to_string()), + kind: FieldErrorKind::Missing("network for raindex 'order1'".to_string()), location: "root".to_string(), } ); assert_eq!( error.to_readable_msg(), - "Missing required field 'network for orderbook 'order1'' in root" + "Missing required field 'network for raindex 'order1'' in root" ); } @@ -645,24 +645,24 @@ networks: chain-id: 1 subgraphs: TestSubgraph: https://subgraph.com -orderbooks: - TestOrderbook: +raindexes: + TestRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph local-db-remote: mainnet "#; - let error = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); assert_eq!( error, YamlError::Field { kind: FieldErrorKind::Missing("deployment-block".to_string()), - location: "orderbook 'TestOrderbook'".to_string(), + location: "raindex 'TestRaindex'".to_string(), } ); assert_eq!( error.to_readable_msg(), - "Missing required field 'deployment-block' in orderbook 'TestOrderbook'" + "Missing required field 'deployment-block' in orderbook 'TestRaindex'" ); } @@ -676,38 +676,38 @@ networks: chain-id: 1 subgraphs: TestSubgraph: https://subgraph.com -orderbooks: - TestOrderbook1: +raindexes: + TestRaindex1: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph local-db-remote: mainnet deployment-block: 0 - TestOrderbook2: + TestRaindex2: address: 0x0987654321098765432109876543210987654321 network: TestNetwork subgraph: TestSubgraph local-db-remote: mainnet deployment-block: 18446744073709551615 - TestOrderbook3: + TestRaindex3: address: 0x1111111111111111111111111111111111111111 network: TestNetwork subgraph: TestSubgraph local-db-remote: mainnet deployment-block: 12345678 "#; - let orderbooks = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); - assert_eq!(orderbooks.len(), 3); + let raindexes = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); + assert_eq!(raindexes.len(), 3); assert_eq!( - orderbooks.get("TestOrderbook1").unwrap().deployment_block, + raindexes.get("TestRaindex1").unwrap().deployment_block, 0 ); assert_eq!( - orderbooks.get("TestOrderbook2").unwrap().deployment_block, + raindexes.get("TestRaindex2").unwrap().deployment_block, 18446744073709551615 ); assert_eq!( - orderbooks.get("TestOrderbook3").unwrap().deployment_block, + raindexes.get("TestRaindex3").unwrap().deployment_block, 12345678 ); } @@ -722,15 +722,15 @@ networks: chain-id: 1 subgraphs: TestSubgraph: https://subgraph.com -orderbooks: - TestOrderbook: +raindexes: + TestRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph local-db-remote: mainnet deployment-block: -1 "#; - let error = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); assert_eq!( error, YamlError::Field { @@ -739,7 +739,7 @@ orderbooks: reason: "Failed to parse deployment block: invalid digit found in string" .to_string(), }, - location: "orderbook 'TestOrderbook'".to_string(), + location: "raindex 'TestRaindex'".to_string(), } ); } @@ -754,15 +754,15 @@ networks: chain-id: 1 subgraphs: TestSubgraph: https://subgraph.com -orderbooks: - TestOrderbook: +raindexes: + TestRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph local-db-remote: mainnet deployment-block: 18446744073709551616 "#; - let error = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); assert_eq!( error, YamlError::Field { @@ -772,7 +772,7 @@ orderbooks: "Failed to parse deployment block: number too large to fit in target type" .to_string(), }, - location: "orderbook 'TestOrderbook'".to_string(), + location: "raindex 'TestRaindex'".to_string(), } ); } @@ -787,15 +787,15 @@ networks: chain-id: 1 subgraphs: TestSubgraph: https://subgraph.com -orderbooks: - TestOrderbook: +raindexes: + TestRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph local-db-remote: mainnet deployment-block: abc123 "#; - let error = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); assert_eq!( error, YamlError::Field { @@ -804,7 +804,7 @@ orderbooks: reason: "Failed to parse deployment block: invalid digit found in string" .to_string(), }, - location: "orderbook 'TestOrderbook'".to_string(), + location: "raindex 'TestRaindex'".to_string(), } ); } @@ -819,15 +819,15 @@ networks: chain-id: 1 subgraphs: TestSubgraph: https://subgraph.com -orderbooks: - TestOrderbook: +raindexes: + TestRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph local-db-remote: mainnet deployment-block: 123.45 "#; - let error = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); assert_eq!( error, YamlError::Field { @@ -836,13 +836,13 @@ orderbooks: reason: "Failed to parse deployment block: invalid digit found in string" .to_string(), }, - location: "orderbook 'TestOrderbook'".to_string(), + location: "raindex 'TestRaindex'".to_string(), } ); } #[test] - fn test_orderbook_local_db_remote_absent_defaults_to_orderbook_key() { + fn test_raindex_local_db_remote_absent_defaults_to_raindex_key() { let yaml = r#" networks: TestNetwork: @@ -852,26 +852,26 @@ networks: subgraphs: TestSubgraph: https://subgraph.com local-db-remotes: - TestOrderbook: https://example.com/localdb/TestOrderbook -orderbooks: - TestOrderbook: + TestRaindex: https://example.com/localdb/TestRaindex +raindexes: + TestRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph deployment-block: 123 "#; - let orderbooks = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); - let ob = orderbooks.get("TestOrderbook").unwrap(); + let raindexes = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); + let ob = raindexes.get("TestRaindex").unwrap(); let remote = ob.local_db_remote.as_ref().expect("expected remote"); - assert_eq!(remote.key, "TestOrderbook"); + assert_eq!(remote.key, "TestRaindex"); assert_eq!( remote.url.to_string(), - "https://example.com/localdb/TestOrderbook" + "https://example.com/localdb/TestRaindex" ); } #[test] - fn test_orderbook_local_db_remote_resolves() { + fn test_raindex_local_db_remote_resolves() { let yaml = r#" networks: TestNetwork: @@ -882,16 +882,16 @@ subgraphs: TestSubgraph: https://subgraph.com local-db-remotes: mainnet: https://example.com/localdb/mainnet -orderbooks: - TestOrderbook: +raindexes: + TestRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph local-db-remote: mainnet deployment-block: 123 "#; - let orderbooks = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); - let ob = orderbooks.get("TestOrderbook").unwrap(); + let raindexes = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); + let ob = raindexes.get("TestRaindex").unwrap(); let remote = ob.local_db_remote.as_ref().expect("expected remote"); assert_eq!(remote.key, "mainnet"); assert_eq!( @@ -901,7 +901,7 @@ orderbooks: } #[test] - fn test_orderbook_local_db_remote_not_found() { + fn test_raindex_local_db_remote_not_found() { let yaml = r#" networks: TestNetwork: @@ -910,16 +910,16 @@ networks: chain-id: 1 subgraphs: TestSubgraph: https://subgraph.com -orderbooks: - TestOrderbook: +raindexes: + TestRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph local-db-remote: missing deployment-block: 123 "#; - let orderbooks = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); - let ob = orderbooks.get("TestOrderbook").unwrap(); + let raindexes = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); + let ob = raindexes.get("TestRaindex").unwrap(); assert!(ob.local_db_remote.is_none()); let yaml = r#" @@ -930,23 +930,23 @@ networks: chain-id: 1 subgraphs: TestSubgraph: https://subgraph.com -orderbooks: - TestOrderbook: +raindexes: + TestRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph local-db-remote: missing deployment-block: 123 "#; - let orderbooks = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); - let ob = orderbooks.get("TestOrderbook").unwrap(); + let raindexes = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); + let ob = raindexes.get("TestRaindex").unwrap(); assert!(ob.local_db_remote.is_none()); } #[test] fn test_sanitize_drops_unknown_keys() { let yaml = r#" -orderbooks: +raindexes: mainnet: address: 0x1234567890123456789012345678901234567890 network: mainnet @@ -956,16 +956,16 @@ orderbooks: another-unknown: also-removed "#; let doc = get_document(yaml); - OrderbookCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); + RaindexCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); let doc_read = doc.read().unwrap(); let root = doc_read.as_hash().unwrap(); - let orderbooks = root - .get(&StrictYaml::String("orderbooks".to_string())) + let raindexes = root + .get(&StrictYaml::String("raindexes".to_string())) .unwrap() .as_hash() .unwrap(); - let mainnet = orderbooks + let mainnet = raindexes .get(&StrictYaml::String("mainnet".to_string())) .unwrap() .as_hash() @@ -982,26 +982,26 @@ orderbooks: #[test] fn test_sanitize_preserves_all_allowed_keys() { let yaml = r#" -orderbooks: +raindexes: mainnet: address: 0x1234567890123456789012345678901234567890 network: mainnet subgraph: mainnet local-db-remote: mainnet - label: Mainnet Orderbook + label: Mainnet Raindex deployment-block: 12345 "#; let doc = get_document(yaml); - OrderbookCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); + RaindexCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); let doc_read = doc.read().unwrap(); let root = doc_read.as_hash().unwrap(); - let orderbooks = root - .get(&StrictYaml::String("orderbooks".to_string())) + let raindexes = root + .get(&StrictYaml::String("raindexes".to_string())) .unwrap() .as_hash() .unwrap(); - let mainnet = orderbooks + let mainnet = raindexes .get(&StrictYaml::String("mainnet".to_string())) .unwrap() .as_hash() @@ -1027,7 +1027,7 @@ orderbooks: ); assert_eq!( mainnet.get(&StrictYaml::String("label".to_string())), - Some(&StrictYaml::String("Mainnet Orderbook".to_string())) + Some(&StrictYaml::String("Mainnet Raindex".to_string())) ); assert_eq!( mainnet.get(&StrictYaml::String("deployment-block".to_string())), @@ -1036,33 +1036,33 @@ orderbooks: } #[test] - fn test_sanitize_drops_non_hash_orderbook_entries() { + fn test_sanitize_drops_non_hash_raindex_entries() { let yaml = r#" -orderbooks: +raindexes: mainnet: address: 0x1234567890123456789012345678901234567890 deployment-block: 12345 invalid-string: just-a-string "#; let doc = get_document(yaml); - OrderbookCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); + RaindexCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); let doc_read = doc.read().unwrap(); let root = doc_read.as_hash().unwrap(); - let orderbooks = root - .get(&StrictYaml::String("orderbooks".to_string())) + let raindexes = root + .get(&StrictYaml::String("raindexes".to_string())) .unwrap() .as_hash() .unwrap(); - assert!(orderbooks.contains_key(&StrictYaml::String("mainnet".to_string()))); - assert!(!orderbooks.contains_key(&StrictYaml::String("invalid-string".to_string()))); + assert!(raindexes.contains_key(&StrictYaml::String("mainnet".to_string()))); + assert!(!raindexes.contains_key(&StrictYaml::String("invalid-string".to_string()))); } #[test] - fn test_sanitize_sorts_orderbooks_lexicographically() { + fn test_sanitize_sorts_raindexes_lexicographically() { let yaml = r#" -orderbooks: +raindexes: zebra: address: 0x1111111111111111111111111111111111111111 deployment-block: 1 @@ -1074,22 +1074,22 @@ orderbooks: deployment-block: 3 "#; let doc = get_document(yaml); - OrderbookCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); + RaindexCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); let doc_read = doc.read().unwrap(); let root = doc_read.as_hash().unwrap(); - let orderbooks = root - .get(&StrictYaml::String("orderbooks".to_string())) + let raindexes = root + .get(&StrictYaml::String("raindexes".to_string())) .unwrap() .as_hash() .unwrap(); - let keys: Vec<_> = orderbooks.keys().map(|k| k.as_str().unwrap()).collect(); + let keys: Vec<_> = raindexes.keys().map(|k| k.as_str().unwrap()).collect(); assert_eq!(keys, vec!["alpha", "mainnet", "zebra"]); } #[test] - fn test_sanitize_handles_missing_orderbooks_section() { + fn test_sanitize_handles_missing_raindexes_section() { let yaml = r#" networks: mainnet: @@ -1098,50 +1098,50 @@ networks: chain-id: 1 "#; let doc = get_document(yaml); - OrderbookCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); + RaindexCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); let doc_read = doc.read().unwrap(); let root = doc_read.as_hash().unwrap(); - assert!(!root.contains_key(&StrictYaml::String("orderbooks".to_string()))); + assert!(!root.contains_key(&StrictYaml::String("raindexes".to_string()))); } #[test] fn test_sanitize_handles_non_hash_root() { let yaml = r#"just-a-string"#; let doc = get_document(yaml); - OrderbookCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); + RaindexCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); let doc_read = doc.read().unwrap(); assert!(doc_read.as_str().is_some()); } #[test] - fn test_sanitize_skips_non_hash_orderbooks_section() { + fn test_sanitize_skips_non_hash_raindexes_section() { let yaml = r#" -orderbooks: not-a-hash +raindexes: not-a-hash "#; let doc = get_document(yaml); - OrderbookCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); + RaindexCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); let doc_read = doc.read().unwrap(); let root = doc_read.as_hash().unwrap(); - let orderbooks = root - .get(&StrictYaml::String("orderbooks".to_string())) + let raindexes = root + .get(&StrictYaml::String("raindexes".to_string())) .unwrap(); - assert_eq!(orderbooks.as_str(), Some("not-a-hash")); + assert_eq!(raindexes.as_str(), Some("not-a-hash")); } #[test] fn test_sanitize_per_document_isolation() { let yaml1 = r#" -orderbooks: +raindexes: from-doc1: address: 0x1111111111111111111111111111111111111111 deployment-block: 1 extra-key: removed "#; let yaml2 = r#" -orderbooks: +raindexes: from-doc2: address: 0x2222222222222222222222222222222222222222 deployment-block: 2 @@ -1150,36 +1150,36 @@ orderbooks: let doc1 = get_document(yaml1); let doc2 = get_document(yaml2); - OrderbookCfg::sanitize_documents(&[doc1.clone(), doc2.clone()]).unwrap(); + RaindexCfg::sanitize_documents(&[doc1.clone(), doc2.clone()]).unwrap(); let doc1_read = doc1.read().unwrap(); let root1 = doc1_read.as_hash().unwrap(); - let orderbooks1 = root1 - .get(&StrictYaml::String("orderbooks".to_string())) + let raindexes1 = root1 + .get(&StrictYaml::String("raindexes".to_string())) .unwrap() .as_hash() .unwrap(); - let from_doc1 = orderbooks1 + let from_doc1 = raindexes1 .get(&StrictYaml::String("from-doc1".to_string())) .unwrap() .as_hash() .unwrap(); assert!(!from_doc1.contains_key(&StrictYaml::String("extra-key".to_string()))); - assert!(!orderbooks1.contains_key(&StrictYaml::String("from-doc2".to_string()))); + assert!(!raindexes1.contains_key(&StrictYaml::String("from-doc2".to_string()))); let doc2_read = doc2.read().unwrap(); let root2 = doc2_read.as_hash().unwrap(); - let orderbooks2 = root2 - .get(&StrictYaml::String("orderbooks".to_string())) + let raindexes2 = root2 + .get(&StrictYaml::String("raindexes".to_string())) .unwrap() .as_hash() .unwrap(); - let from_doc2 = orderbooks2 + let from_doc2 = raindexes2 .get(&StrictYaml::String("from-doc2".to_string())) .unwrap() .as_hash() .unwrap(); assert!(!from_doc2.contains_key(&StrictYaml::String("another-extra".to_string()))); - assert!(!orderbooks2.contains_key(&StrictYaml::String("from-doc1".to_string()))); + assert!(!raindexes2.contains_key(&StrictYaml::String("from-doc1".to_string()))); } } diff --git a/crates/settings/src/test.rs b/crates/settings/src/test.rs index 75517d5b7a..559e317600 100644 --- a/crates/settings/src/test.rs +++ b/crates/settings/src/test.rs @@ -28,12 +28,12 @@ pub fn mock_rainlang() -> Arc { }) } -// Helper function to create a mock orderbook -pub fn mock_orderbook() -> Arc { - Arc::new(OrderbookCfg { +// Helper function to create a mock raindex +pub fn mock_raindex() -> Arc { + Arc::new(RaindexCfg { document: Arc::new(RwLock::new(StrictYaml::String("".to_string()))), key: "".to_string(), - label: Some("Orderbook1".into()), + label: Some("Raindex1".into()), address: Address::repeat_byte(0x04), subgraph: Arc::new(SubgraphCfg { document: Arc::new(RwLock::new(StrictYaml::String("".to_string()))), diff --git a/crates/settings/src/yaml/context.rs b/crates/settings/src/yaml/context.rs index 3460a30f01..7906540d26 100644 --- a/crates/settings/src/yaml/context.rs +++ b/crates/settings/src/yaml/context.rs @@ -434,7 +434,7 @@ mod tests { }], network: mock_network(), rainlang: None, - orderbook: None, + raindex: None, oracle_url: None, }) } @@ -451,7 +451,7 @@ mod tests { outputs: vec![], network: mock_network(), rainlang: None, - orderbook: None, + raindex: None, oracle_url: None, }) } @@ -586,7 +586,7 @@ mod tests { }], network: mock_network(), rainlang: Some(mock_rainlang()), - orderbook: Some(mock_orderbook()), + raindex: Some(mock_raindex()), oracle_url: None, }; context.add_order(Arc::new(order)); @@ -602,7 +602,7 @@ mod tests { assert_eq!(context_order.outputs[0].vault_id, None); assert_eq!(context_order.network, mock_network()); assert_eq!(context_order.rainlang, Some(mock_rainlang())); - assert_eq!(context_order.orderbook, Some(mock_orderbook())); + assert_eq!(context_order.raindex, Some(mock_raindex())); } #[test] diff --git a/crates/settings/src/yaml/dotrain.rs b/crates/settings/src/yaml/dotrain.rs index 4c1456e795..aee2dd7d36 100644 --- a/crates/settings/src/yaml/dotrain.rs +++ b/crates/settings/src/yaml/dotrain.rs @@ -1,4 +1,4 @@ -use super::{cache::Cache, orderbook::OrderbookYaml, sanitize_all_documents, ValidationConfig, *}; +use super::{cache::Cache, raindex::RaindexYaml, sanitize_all_documents, ValidationConfig, *}; use crate::{spec_version::SpecVersion, ChartCfg, DeploymentCfg, GuiCfg, OrderCfg, ScenarioCfg}; use serde::{ de::{self, IgnoredAny, MapAccess, SeqAccess, Visitor}, @@ -61,7 +61,7 @@ impl ValidationConfig for DotrainYamlValidation { fn should_validate_local_db_sync(&self) -> bool { false } - fn should_validate_orderbooks(&self) -> bool { + fn should_validate_raindexes(&self) -> bool { false } fn should_validate_metaboards(&self) -> bool { @@ -134,10 +134,10 @@ impl YamlParsable for DotrainYaml { } } - fn from_orderbook_yaml(orderbook_yaml: OrderbookYaml) -> Self { + fn from_raindex_yaml(raindex_yaml: RaindexYaml) -> Self { DotrainYaml { - documents: orderbook_yaml.documents, - cache: orderbook_yaml.cache, + documents: raindex_yaml.documents, + cache: raindex_yaml.cache, profile: ContextProfile::Strict, } } @@ -376,14 +376,14 @@ mod tests { test::*, yaml::{ context::{ContextProfile, YamlCacheTrait}, - orderbook::OrderbookYamlValidation, + raindex::RaindexYamlValidation, }, BinXOptionsCfg, BinXTransformCfg, DotOptionsCfg, GuiSelectTokensCfg, HexBinOptionsCfg, HexBinTransformCfg, LineOptionsCfg, MarkCfg, RectYOptionsCfg, TransformCfg, TransformOutputsCfg, VaultType, }; use alloy::primitives::U256; - use orderbook::OrderbookYaml; + use raindex::RaindexYaml; use super::*; @@ -605,7 +605,7 @@ mod tests { #[test] fn test_full_yaml() { let ob_yaml = - OrderbookYaml::new(vec![full_yaml()], OrderbookYamlValidation::default()).unwrap(); + RaindexYaml::new(vec![full_yaml()], RaindexYamlValidation::default()).unwrap(); let dotrain_yaml = DotrainYaml::new(vec![full_yaml()], DotrainYamlValidation::default()).unwrap(); diff --git a/crates/settings/src/yaml/emitter.rs b/crates/settings/src/yaml/emitter.rs index 98218aa89f..059559749f 100644 --- a/crates/settings/src/yaml/emitter.rs +++ b/crates/settings/src/yaml/emitter.rs @@ -6,7 +6,7 @@ use crate::{ accounts::AccountCfg, local_db_remotes::LocalDbRemoteCfg, local_db_sync::LocalDbSyncCfg, metaboard::MetaboardCfg, remote_networks::RemoteNetworksCfg, remote_tokens::RemoteTokensCfg, sentry::Sentry, spec_version::SpecVersion, subgraph::SubgraphCfg, ChartCfg, DeploymentCfg, - GuiCfg, NetworkCfg, OrderCfg, OrderbookCfg, RainlangCfg, ScenarioCfg, TokenCfg, + GuiCfg, NetworkCfg, OrderCfg, RaindexCfg, RainlangCfg, ScenarioCfg, TokenCfg, }; use std::sync::{Arc, RwLock}; use strict_yaml_rust::{strict_yaml::Hash, StrictYaml, StrictYamlEmitter}; @@ -19,7 +19,7 @@ const CANONICAL_ROOT_KEYS: &[&str] = &[ "metaboards", "tokens", "rainlangs", - "orderbooks", + "raindexes", "orders", "scenarios", "deployments", @@ -43,7 +43,7 @@ pub fn validate_and_emit_documents( validate_hash_section::(documents, context)?; validate_hash_section::(documents, context)?; validate_hash_section::(documents, context)?; - validate_hash_section::(documents, context)?; + validate_hash_section::(documents, context)?; validate_hash_section::(documents, context)?; ChartCfg::parse_all_from_yaml(documents.to_vec(), context)?; diff --git a/crates/settings/src/yaml/mod.rs b/crates/settings/src/yaml/mod.rs index 16bf52d3a2..a53fdd2d24 100644 --- a/crates/settings/src/yaml/mod.rs +++ b/crates/settings/src/yaml/mod.rs @@ -2,18 +2,18 @@ pub mod cache; pub mod context; pub mod dotrain; pub mod emitter; -pub mod orderbook; +pub mod raindex; use crate::{ remote_networks::ParseRemoteNetworksError, remote_tokens::ParseRemoteTokensError, NetworkCfg, ParseDeploymentConfigSourceError, ParseNetworkConfigSourceError, ParseOrderConfigSourceError, - ParseOrderbookConfigSourceError, ParseRainlangConfigSourceError, + ParseRaindexConfigSourceError, ParseRainlangConfigSourceError, ParseScenarioConfigSourceError, ParseTokenConfigSourceError, TokenCfg, }; use alloy::primitives::ruint::ParseError as RuintParseError; use context::{Context, ContextError, ContextProfile}; use dotrain::DotrainYaml; -use orderbook::OrderbookYaml; +use raindex::RaindexYaml; use std::collections::HashMap; use std::sync::{Arc, RwLock}; use strict_yaml_rust::StrictYamlEmitter; @@ -32,7 +32,7 @@ pub trait ValidationConfig { fn should_validate_subgraphs(&self) -> bool; fn should_validate_local_db_remotes(&self) -> bool; fn should_validate_local_db_sync(&self) -> bool; - fn should_validate_orderbooks(&self) -> bool; + fn should_validate_raindexes(&self) -> bool; fn should_validate_metaboards(&self) -> bool; fn should_validate_rainlangs(&self) -> bool; fn should_validate_orders(&self) -> bool; @@ -45,7 +45,7 @@ pub trait YamlParsable: Sized { fn new(sources: Vec, validate: Self::ValidationConfig) -> Result; fn from_documents(documents: Vec>>) -> Self; - fn from_orderbook_yaml(orderbook_yaml: OrderbookYaml) -> Self; + fn from_raindex_yaml(raindex_yaml: RaindexYaml) -> Self; fn from_dotrain_yaml(dotrain_yaml: DotrainYaml) -> Self; fn get_yaml_string(document: Arc>) -> Result { @@ -199,7 +199,7 @@ pub enum YamlError { #[error(transparent)] ParseTokenConfigSourceError(#[from] ParseTokenConfigSourceError), #[error(transparent)] - ParseOrderbookConfigSourceError(#[from] ParseOrderbookConfigSourceError), + ParseRaindexConfigSourceError(#[from] ParseRaindexConfigSourceError), #[error(transparent)] ParseRainlangConfigSourceError(#[from] ParseRainlangConfigSourceError), #[error(transparent)] @@ -251,8 +251,8 @@ impl PartialEq for YamlError { e1 == e2 } ( - Self::ParseOrderbookConfigSourceError(e1), - Self::ParseOrderbookConfigSourceError(e2), + Self::ParseRaindexConfigSourceError(e1), + Self::ParseRaindexConfigSourceError(e2), ) => e1 == e2, ( Self::ParseRainlangConfigSourceError(e1), @@ -344,7 +344,7 @@ impl YamlError { "Token configuration error in your YAML: {}", err.to_readable_msg() ), - YamlError::ParseOrderbookConfigSourceError(err) => format!( + YamlError::ParseRaindexConfigSourceError(err) => format!( "Orderbook configuration error in your YAML: {}", err.to_readable_msg() ), diff --git a/crates/settings/src/yaml/orderbook.rs b/crates/settings/src/yaml/raindex.rs similarity index 84% rename from crates/settings/src/yaml/orderbook.rs rename to crates/settings/src/yaml/raindex.rs index fb5360a848..1f5ede74bf 100644 --- a/crates/settings/src/yaml/orderbook.rs +++ b/crates/settings/src/yaml/raindex.rs @@ -2,7 +2,7 @@ use super::{cache::Cache, sanitize_all_documents, ValidationConfig, *}; use crate::{ accounts::AccountCfg, local_db_remotes::LocalDbRemoteCfg, local_db_sync::LocalDbSyncCfg, metaboard::MetaboardCfg, remote_networks::RemoteNetworksCfg, remote_tokens::RemoteTokensCfg, - sentry::Sentry, spec_version::SpecVersion, subgraph::SubgraphCfg, NetworkCfg, OrderbookCfg, + sentry::Sentry, spec_version::SpecVersion, subgraph::SubgraphCfg, NetworkCfg, RaindexCfg, RainlangCfg, TokenCfg, }; use alloy::primitives::Address; @@ -21,17 +21,17 @@ use wasm_bindgen_utils::{impl_wasm_traits, prelude::*}; #[derive(Debug, Clone, Default)] #[cfg_attr(target_family = "wasm", derive(Tsify))] -pub struct OrderbookYaml { +pub struct RaindexYaml { #[cfg_attr(target_family = "wasm", tsify(type = "string[]"))] pub documents: Vec>>, pub cache: Cache, pub profile: ContextProfile, } #[cfg(target_family = "wasm")] -impl_wasm_traits!(OrderbookYaml); +impl_wasm_traits!(RaindexYaml); #[derive(Debug, Clone, Default)] -pub struct OrderbookYamlValidation { +pub struct RaindexYamlValidation { pub networks: bool, pub remote_networks: bool, pub tokens: bool, @@ -39,13 +39,13 @@ pub struct OrderbookYamlValidation { pub subgraphs: bool, pub local_db_remotes: bool, pub local_db_sync: bool, - pub orderbooks: bool, + pub raindexes: bool, pub metaboards: bool, pub rainlangs: bool, } -impl OrderbookYamlValidation { +impl RaindexYamlValidation { pub fn full() -> Self { - OrderbookYamlValidation { + RaindexYamlValidation { networks: true, remote_networks: true, tokens: true, @@ -53,13 +53,13 @@ impl OrderbookYamlValidation { subgraphs: true, local_db_remotes: true, local_db_sync: true, - orderbooks: true, + raindexes: true, metaboards: true, rainlangs: true, } } } -impl ValidationConfig for OrderbookYamlValidation { +impl ValidationConfig for RaindexYamlValidation { fn should_validate_networks(&self) -> bool { self.networks } @@ -81,8 +81,8 @@ impl ValidationConfig for OrderbookYamlValidation { fn should_validate_local_db_sync(&self) -> bool { self.local_db_sync } - fn should_validate_orderbooks(&self) -> bool { - self.orderbooks + fn should_validate_raindexes(&self) -> bool { + self.raindexes } fn should_validate_metaboards(&self) -> bool { self.metaboards @@ -107,10 +107,10 @@ pub struct FetchedRemoteData { pub remote_tokens: HashMap, } -impl YamlParsable for OrderbookYaml { - type ValidationConfig = OrderbookYamlValidation; +impl YamlParsable for RaindexYaml { + type ValidationConfig = RaindexYamlValidation; - fn new(sources: Vec, validate: OrderbookYamlValidation) -> Result { + fn new(sources: Vec, validate: RaindexYamlValidation) -> Result { let mut documents = Vec::new(); for source in sources { @@ -148,8 +148,8 @@ impl YamlParsable for OrderbookYaml { if validate.should_validate_local_db_sync() { LocalDbSyncCfg::parse_all_from_yaml(documents.clone(), None)?; } - if validate.should_validate_orderbooks() { - OrderbookCfg::parse_all_from_yaml(documents.clone(), None)?; + if validate.should_validate_raindexes() { + RaindexCfg::parse_all_from_yaml(documents.clone(), None)?; } if validate.should_validate_metaboards() { MetaboardCfg::parse_all_from_yaml(documents.clone(), None)?; @@ -158,7 +158,7 @@ impl YamlParsable for OrderbookYaml { RainlangCfg::parse_all_from_yaml(documents.clone(), None)?; } - Ok(OrderbookYaml { + Ok(RaindexYaml { documents, cache: Cache::default(), profile: ContextProfile::Strict, @@ -166,23 +166,23 @@ impl YamlParsable for OrderbookYaml { } fn from_documents(documents: Vec>>) -> Self { - OrderbookYaml { + RaindexYaml { documents, cache: Cache::default(), profile: ContextProfile::Strict, } } - fn from_orderbook_yaml(orderbook_yaml: OrderbookYaml) -> Self { - OrderbookYaml { - documents: orderbook_yaml.documents, - cache: orderbook_yaml.cache, - profile: orderbook_yaml.profile, + fn from_raindex_yaml(raindex_yaml: RaindexYaml) -> Self { + RaindexYaml { + documents: raindex_yaml.documents, + cache: raindex_yaml.cache, + profile: raindex_yaml.profile, } } fn from_dotrain_yaml(dotrain_yaml: DotrainYaml) -> Self { - OrderbookYaml { + RaindexYaml { documents: dotrain_yaml.documents, cache: dotrain_yaml.cache, profile: dotrain_yaml.profile, @@ -190,7 +190,7 @@ impl YamlParsable for OrderbookYaml { } } -impl ContextProvider for OrderbookYaml { +impl ContextProvider for RaindexYaml { fn get_remote_networks_from_cache(&self) -> HashMap { self.cache.get_remote_networks() } @@ -200,10 +200,10 @@ impl ContextProvider for OrderbookYaml { } } -impl OrderbookYaml { +impl RaindexYaml { pub fn new_with_profile( sources: Vec, - validate: OrderbookYamlValidation, + validate: RaindexYamlValidation, profile: ContextProfile, ) -> Result { let mut instance = Self::new(sources, validate)?; @@ -326,20 +326,20 @@ impl OrderbookYaml { } pub fn get_orderbook_keys(&self) -> Result, YamlError> { - Ok(self.get_orderbooks()?.keys().cloned().collect()) + Ok(self.get_raindexes()?.keys().cloned().collect()) } - pub fn get_orderbooks(&self) -> Result, YamlError> { + pub fn get_raindexes(&self) -> Result, YamlError> { let context = self.build_context(); - OrderbookCfg::parse_all_from_yaml(self.documents.clone(), Some(&context)) + RaindexCfg::parse_all_from_yaml(self.documents.clone(), Some(&context)) } - pub fn get_orderbook(&self, key: &str) -> Result { + pub fn get_orderbook(&self, key: &str) -> Result { let context = self.build_context(); - OrderbookCfg::parse_from_yaml(self.documents.clone(), key, Some(&context)) + RaindexCfg::parse_from_yaml(self.documents.clone(), key, Some(&context)) } - pub fn get_orderbook_by_address(&self, address: Address) -> Result { + pub fn get_orderbook_by_address(&self, address: Address) -> Result { let context = self.build_context(); - let orderbooks = OrderbookCfg::parse_all_from_yaml(self.documents.clone(), Some(&context))?; - for (_, orderbook) in orderbooks { + let raindexes = RaindexCfg::parse_all_from_yaml(self.documents.clone(), Some(&context))?; + for (_, orderbook) in raindexes { if orderbook.address == address { return Ok(orderbook); } @@ -349,47 +349,47 @@ impl OrderbookYaml { address ))) } - pub fn get_orderbooks_by_network_key( + pub fn get_raindexes_by_network_key( &self, network_key: &str, - ) -> Result, YamlError> { - let mut orderbooks: Vec<_> = self - .get_orderbooks()? + ) -> Result, YamlError> { + let mut raindexes: Vec<_> = self + .get_raindexes()? .into_iter() .filter(|(_, ob)| ob.network.key == network_key) .map(|(_, ob)| ob) .collect(); - orderbooks.sort_by(|a, b| a.key.cmp(&b.key)); + raindexes.sort_by(|a, b| a.key.cmp(&b.key)); - if orderbooks.is_empty() { + if raindexes.is_empty() { return Err(YamlError::NotFound(format!( "orderbook with network key: {}", network_key ))); } - Ok(orderbooks) + Ok(raindexes) } - pub fn get_orderbooks_by_chain_id( + pub fn get_raindexes_by_chain_id( &self, chain_id: u32, - ) -> Result, YamlError> { + ) -> Result, YamlError> { let network = self.get_network_by_chain_id(chain_id)?; - let mut orderbooks: Vec<_> = self - .get_orderbooks()? + let mut raindexes: Vec<_> = self + .get_raindexes()? .into_iter() .filter(|(_, ob)| ob.network.key == network.key) .map(|(_, ob)| ob) .collect(); - orderbooks.sort_by(|a, b| a.key.cmp(&b.key)); + raindexes.sort_by(|a, b| a.key.cmp(&b.key)); - if orderbooks.is_empty() { + if raindexes.is_empty() { return Err(YamlError::NotFound(format!( "orderbook with chain-id: {}", chain_id ))); } - Ok(orderbooks) + Ok(raindexes) } pub fn get_metaboard_keys(&self) -> Result, YamlError> { @@ -457,7 +457,7 @@ impl OrderbookYaml { } } -impl Serialize for OrderbookYaml { +impl Serialize for RaindexYaml { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -468,22 +468,22 @@ impl Serialize for OrderbookYaml { documents.push(yaml_str); } - let mut state = serializer.serialize_struct("OrderbookYaml", 2)?; + let mut state = serializer.serialize_struct("RaindexYaml", 2)?; state.serialize_field("documents", &documents)?; state.serialize_field("profile", &self.profile)?; state.end() } } -impl<'de> Deserialize<'de> for OrderbookYaml { +impl<'de> Deserialize<'de> for RaindexYaml { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { - struct OrderbookYamlVisitor; + struct RaindexYamlVisitor; - impl<'de> Visitor<'de> for OrderbookYamlVisitor { - type Value = OrderbookYaml; + impl<'de> Visitor<'de> for RaindexYamlVisitor { + type Value = RaindexYaml; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a sequence of YAML documents as strings") @@ -526,7 +526,7 @@ impl<'de> Deserialize<'de> for OrderbookYaml { }) .collect::, M::Error>>()?; - Ok(OrderbookYaml { + Ok(RaindexYaml { documents, cache: Cache::default(), profile, @@ -549,7 +549,7 @@ impl<'de> Deserialize<'de> for OrderbookYaml { documents.push(Arc::new(RwLock::new(doc))); } - Ok(OrderbookYaml { + Ok(RaindexYaml { documents, cache: Cache::default(), profile: ContextProfile::Strict, @@ -557,7 +557,7 @@ impl<'de> Deserialize<'de> for OrderbookYaml { } } - deserializer.deserialize_any(OrderbookYamlVisitor) + deserializer.deserialize_any(RaindexYamlVisitor) } } @@ -571,11 +571,11 @@ mod tests { use url::Url; #[test] - fn test_orderbook_yaml_profile_helpers() { + fn test_raindex_yaml_profile_helpers() { let sources = vec![full_yaml()]; - let ob = OrderbookYaml::new_with_profile( + let ob = RaindexYaml::new_with_profile( sources.clone(), - OrderbookYamlValidation::default(), + RaindexYamlValidation::default(), ContextProfile::Gui { current_deployment: "deployment1".to_string(), }, @@ -583,7 +583,7 @@ mod tests { .unwrap(); assert!(matches!(ob.profile, ContextProfile::Gui { .. })); - let ob_default = OrderbookYaml::new(sources, OrderbookYamlValidation::default()).unwrap(); + let ob_default = RaindexYaml::new(sources, RaindexYamlValidation::default()).unwrap(); assert!(matches!(ob_default.profile, ContextProfile::Strict)); let ob_strict = ob.with_profile(ContextProfile::Strict); @@ -591,10 +591,10 @@ mod tests { } #[test] - fn test_orderbook_yaml_serialization_preserves_profile() { - let ob = OrderbookYaml::new_with_profile( + fn test_raindex_yaml_serialization_preserves_profile() { + let ob = RaindexYaml::new_with_profile( vec![full_yaml()], - OrderbookYamlValidation::default(), + RaindexYamlValidation::default(), ContextProfile::Gui { current_deployment: "deployment1".to_string(), }, @@ -602,7 +602,7 @@ mod tests { .unwrap(); let serialized = serde_json::to_string(&ob).unwrap(); - let round_tripped: OrderbookYaml = serde_json::from_str(&serialized).unwrap(); + let round_tripped: RaindexYaml = serde_json::from_str(&serialized).unwrap(); match round_tripped.profile { ContextProfile::Gui { current_deployment } => { assert_eq!(current_deployment, "deployment1"); @@ -612,9 +612,9 @@ mod tests { } #[test] - fn test_orderbook_yaml_legacy_sequence_deserialization_defaults_profile() { + fn test_raindex_yaml_legacy_sequence_deserialization_defaults_profile() { let legacy_serialized = serde_json::to_string(&vec![full_yaml()]).unwrap(); - let deserialized: OrderbookYaml = serde_json::from_str(&legacy_serialized).unwrap(); + let deserialized: RaindexYaml = serde_json::from_str(&legacy_serialized).unwrap(); assert!(matches!(deserialized.profile, ContextProfile::Strict)); assert_eq!(deserialized.documents.len(), 1); @@ -646,7 +646,7 @@ mod tests { metaboards: board1: https://meta.example.com/board1 board2: https://meta.example.com/board2 - orderbooks: + raindexes: orderbook1: address: 0x0000000000000000000000000000000000000002 network: mainnet @@ -684,7 +684,7 @@ mod tests { mainnet: https://api.thegraph.com/subgraphs/name/xyz metaboards: board1: https://meta.example.com/board1 - orderbooks: + raindexes: orderbook1: address: 0x1234567890abcdef deployment-block: 12345 @@ -700,7 +700,7 @@ mod tests { #[test] fn test_full_yaml() { let ob_yaml = - OrderbookYaml::new(vec![full_yaml()], OrderbookYamlValidation::default()).unwrap(); + RaindexYaml::new(vec![full_yaml()], RaindexYamlValidation::default()).unwrap(); assert_eq!(ob_yaml.get_network_keys().unwrap().len(), 1); let network = ob_yaml.get_network("mainnet").unwrap(); @@ -764,7 +764,7 @@ mod tests { assert_eq!(orderbook.subgraph, subgraph.into()); assert_eq!(orderbook.label, Some("Primary Orderbook".to_string())); assert_eq!( - OrderbookCfg::parse_network_key(ob_yaml.documents.clone(), "orderbook1").unwrap(), + RaindexCfg::parse_network_key(ob_yaml.documents.clone(), "orderbook1").unwrap(), "mainnet" ); let orderbook_by_address = ob_yaml @@ -814,7 +814,7 @@ mod tests { #[test] fn test_update_network_rpc() { let ob_yaml = - OrderbookYaml::new(vec![full_yaml()], OrderbookYamlValidation::default()).unwrap(); + RaindexYaml::new(vec![full_yaml()], RaindexYamlValidation::default()).unwrap(); let mut network = ob_yaml.get_network("mainnet").unwrap(); assert_eq!( @@ -853,7 +853,7 @@ mod tests { #[test] fn test_update_token_address() { let ob_yaml = - OrderbookYaml::new(vec![full_yaml()], OrderbookYamlValidation::default()).unwrap(); + RaindexYaml::new(vec![full_yaml()], RaindexYamlValidation::default()).unwrap(); let mut token = ob_yaml.get_token("token1").unwrap(); assert_eq!( @@ -889,7 +889,7 @@ networks: "#, version = SpecVersion::current() ); - let ob_yaml = OrderbookYaml::new(vec![yaml], OrderbookYamlValidation::default()).unwrap(); + let ob_yaml = RaindexYaml::new(vec![yaml], RaindexYamlValidation::default()).unwrap(); TokenCfg::add_record_to_yaml( ob_yaml.documents.clone(), @@ -917,7 +917,7 @@ networks: #[test] fn test_remove_token_from_yaml() { let ob_yaml = - OrderbookYaml::new(vec![full_yaml()], OrderbookYamlValidation::default()).unwrap(); + RaindexYaml::new(vec![full_yaml()], RaindexYamlValidation::default()).unwrap(); assert!(ob_yaml.get_token("token1").is_ok()); TokenCfg::remove_record_from_yaml(ob_yaml.documents.clone(), "token1").unwrap(); @@ -933,7 +933,7 @@ test: test "#, version = SpecVersion::current() ); - let ob_yaml = OrderbookYaml::new(vec![yaml], OrderbookYamlValidation::default()).unwrap(); + let ob_yaml = RaindexYaml::new(vec![yaml], RaindexYamlValidation::default()).unwrap(); ob_yaml .add_metaboard("test-metaboard", "https://test-metaboard.com") @@ -952,7 +952,7 @@ test: test #[test] fn test_get_network_by_chain_id() { let ob_yaml = - OrderbookYaml::new(vec![full_yaml()], OrderbookYamlValidation::default()).unwrap(); + RaindexYaml::new(vec![full_yaml()], RaindexYamlValidation::default()).unwrap(); // Test successful lookup let network = ob_yaml.get_network_by_chain_id(1).unwrap(); @@ -982,21 +982,21 @@ test: test #[test] fn test_get_orderbook_by_network_key() { let ob_yaml = - OrderbookYaml::new(vec![full_yaml()], OrderbookYamlValidation::default()).unwrap(); + RaindexYaml::new(vec![full_yaml()], RaindexYamlValidation::default()).unwrap(); // Test successful lookup - let orderbooks = ob_yaml.get_orderbooks_by_network_key("mainnet").unwrap(); - assert_eq!(orderbooks.len(), 1); - assert_eq!(orderbooks[0].key, "orderbook1"); - assert_eq!(orderbooks[0].network.key, "mainnet"); + let raindexes = ob_yaml.get_raindexes_by_network_key("mainnet").unwrap(); + assert_eq!(raindexes.len(), 1); + assert_eq!(raindexes[0].key, "orderbook1"); + assert_eq!(raindexes[0].network.key, "mainnet"); assert_eq!( - orderbooks[0].address, + raindexes[0].address, Address::from_str("0x0000000000000000000000000000000000000002").unwrap() ); // Test error case - network key not found let error = ob_yaml - .get_orderbooks_by_network_key("nonexistent") + .get_raindexes_by_network_key("nonexistent") .unwrap_err(); assert_eq!( error, @@ -1037,7 +1037,7 @@ test: test currency: ETH subgraphs: mainnet: https://api.thegraph.com/subgraphs/name/xyz - orderbooks: + raindexes: mainnet-orderbook: address: 0x1234567890123456789012345678901234567890 network: mainnet @@ -1060,7 +1060,7 @@ test: test spec_version = SpecVersion::current() ); - let ob_yaml = OrderbookYaml::new(vec![yaml], OrderbookYamlValidation::default()).unwrap(); + let ob_yaml = RaindexYaml::new(vec![yaml], RaindexYamlValidation::default()).unwrap(); // Test each network let mainnet = ob_yaml.get_network_by_chain_id(1).unwrap(); @@ -1076,21 +1076,21 @@ test: test assert_eq!(arbitrum.chain_id, 42161); // Test orderbook lookup by network key - let orderbooks = ob_yaml.get_orderbooks_by_network_key("mainnet").unwrap(); - assert_eq!(orderbooks.len(), 2); - assert_eq!(orderbooks[0].key, "mainnet-orderbook"); - assert_eq!(orderbooks[0].network.key, "mainnet"); - assert_eq!(orderbooks[1].key, "other-orderbook"); - assert_eq!(orderbooks[1].network.key, "mainnet"); - - let orderbooks = ob_yaml.get_orderbooks_by_network_key("polygon").unwrap(); - assert_eq!(orderbooks.len(), 1); - assert_eq!(orderbooks[0].key, "polygon-orderbook"); - assert_eq!(orderbooks[0].network.key, "polygon"); + let raindexes = ob_yaml.get_raindexes_by_network_key("mainnet").unwrap(); + assert_eq!(raindexes.len(), 2); + assert_eq!(raindexes[0].key, "mainnet-orderbook"); + assert_eq!(raindexes[0].network.key, "mainnet"); + assert_eq!(raindexes[1].key, "other-orderbook"); + assert_eq!(raindexes[1].network.key, "mainnet"); + + let raindexes = ob_yaml.get_raindexes_by_network_key("polygon").unwrap(); + assert_eq!(raindexes.len(), 1); + assert_eq!(raindexes[0].key, "polygon-orderbook"); + assert_eq!(raindexes[0].network.key, "polygon"); // Test error for network without orderbook let error = ob_yaml - .get_orderbooks_by_network_key("arbitrum") + .get_raindexes_by_network_key("arbitrum") .unwrap_err(); assert_eq!( error, @@ -1099,20 +1099,20 @@ test: test } #[test] - fn test_get_orderbooks_by_chain_id_single_network() { + fn test_get_raindexes_by_chain_id_single_network() { let ob_yaml = - OrderbookYaml::new(vec![full_yaml()], OrderbookYamlValidation::default()).unwrap(); + RaindexYaml::new(vec![full_yaml()], RaindexYamlValidation::default()).unwrap(); - let orderbooks = ob_yaml.get_orderbooks_by_chain_id(1).unwrap(); - assert_eq!(orderbooks.len(), 1); - assert_eq!(orderbooks[0].key, "orderbook1"); - assert_eq!(orderbooks[0].network.key, "mainnet"); + let raindexes = ob_yaml.get_raindexes_by_chain_id(1).unwrap(); + assert_eq!(raindexes.len(), 1); + assert_eq!(raindexes[0].key, "orderbook1"); + assert_eq!(raindexes[0].network.key, "mainnet"); assert_eq!( - orderbooks[0].address, + raindexes[0].address, Address::from_str("0x0000000000000000000000000000000000000002").unwrap() ); - let err = ob_yaml.get_orderbooks_by_chain_id(999).unwrap_err(); + let err = ob_yaml.get_raindexes_by_chain_id(999).unwrap_err(); assert_eq!( err, YamlError::NotFound("network with chain-id: 999".to_string()) @@ -1124,7 +1124,7 @@ test: test } #[test] - fn test_get_orderbooks_by_chain_id_multiple_networks() { + fn test_get_raindexes_by_chain_id_multiple_networks() { let yaml = format!( r#" version: {spec_version} @@ -1143,7 +1143,7 @@ test: test chain-id: 42161 subgraphs: mainnet: https://api.thegraph.com/subgraphs/name/xyz - orderbooks: + raindexes: mainnet-orderbook: address: 0x1234567890123456789012345678901234567890 network: mainnet @@ -1166,21 +1166,21 @@ test: test spec_version = SpecVersion::current() ); - let ob_yaml = OrderbookYaml::new(vec![yaml], OrderbookYamlValidation::default()).unwrap(); + let ob_yaml = RaindexYaml::new(vec![yaml], RaindexYamlValidation::default()).unwrap(); // mainnet chain id - let orderbooks = ob_yaml.get_orderbooks_by_chain_id(1).unwrap(); - assert_eq!(orderbooks.len(), 2); - assert_eq!(orderbooks[0].network.key, "mainnet"); - assert_eq!(orderbooks[1].network.key, "mainnet"); + let raindexes = ob_yaml.get_raindexes_by_chain_id(1).unwrap(); + assert_eq!(raindexes.len(), 2); + assert_eq!(raindexes[0].network.key, "mainnet"); + assert_eq!(raindexes[1].network.key, "mainnet"); // polygon chain id - let orderbooks = ob_yaml.get_orderbooks_by_chain_id(137).unwrap(); - assert_eq!(orderbooks.len(), 1); - assert_eq!(orderbooks[0].network.key, "polygon"); + let raindexes = ob_yaml.get_raindexes_by_chain_id(137).unwrap(); + assert_eq!(raindexes.len(), 1); + assert_eq!(raindexes[0].network.key, "polygon"); - // arbitrum chain id has no orderbooks - let err = ob_yaml.get_orderbooks_by_chain_id(42161).unwrap_err(); + // arbitrum chain id has no raindexes + let err = ob_yaml.get_raindexes_by_chain_id(42161).unwrap_err(); assert_eq!( err, YamlError::NotFound("orderbook with chain-id: 42161".to_string()) @@ -1190,7 +1190,7 @@ test: test #[test] fn test_get_local_db_remote_keys() { let ob_yaml = - OrderbookYaml::new(vec![full_yaml()], OrderbookYamlValidation::default()).unwrap(); + RaindexYaml::new(vec![full_yaml()], RaindexYamlValidation::default()).unwrap(); let keys = ob_yaml.get_local_db_remote_keys().unwrap(); assert_eq!(keys, vec!["mainnet".to_string()]); @@ -1199,7 +1199,7 @@ test: test #[test] fn test_get_local_db_remotes_and_single_remote() { let ob_yaml = - OrderbookYaml::new(vec![full_yaml()], OrderbookYamlValidation::default()).unwrap(); + RaindexYaml::new(vec![full_yaml()], RaindexYamlValidation::default()).unwrap(); let remotes = ob_yaml.get_local_db_remotes().unwrap(); assert_eq!(remotes.len(), 1); @@ -1235,7 +1235,7 @@ subgraphs: version = SpecVersion::current() ); - let ob_yaml = OrderbookYaml::new(vec![yaml], OrderbookYamlValidation::default()).unwrap(); + let ob_yaml = RaindexYaml::new(vec![yaml], RaindexYamlValidation::default()).unwrap(); let err = ob_yaml.get_local_db_remote("polygon").unwrap_err(); assert_eq!(err, YamlError::KeyNotFound("polygon".to_string())); } @@ -1258,7 +1258,7 @@ local-db-sync: "#, version = SpecVersion::current() ); - let ob_yaml = OrderbookYaml::new(vec![yaml], OrderbookYamlValidation::default()).unwrap(); + let ob_yaml = RaindexYaml::new(vec![yaml], RaindexYamlValidation::default()).unwrap(); let keys = ob_yaml.get_local_db_sync_keys().unwrap(); assert_eq!(keys, vec!["test".to_string()]); @@ -1295,7 +1295,7 @@ local-db-sync: "#, version = SpecVersion::current() ); - let ob_yaml = OrderbookYaml::new(vec![yaml], OrderbookYamlValidation::default()).unwrap(); + let ob_yaml = RaindexYaml::new(vec![yaml], RaindexYamlValidation::default()).unwrap(); let cfg = ob_yaml.get_local_db_sync("test").unwrap(); assert_eq!(cfg.key, "test"); @@ -1327,7 +1327,7 @@ local-db-sync: "#, version = SpecVersion::current() ); - let ob_yaml = OrderbookYaml::new(vec![yaml], OrderbookYamlValidation::default()).unwrap(); + let ob_yaml = RaindexYaml::new(vec![yaml], RaindexYamlValidation::default()).unwrap(); let err = ob_yaml.get_local_db_sync("nonexistent").unwrap_err(); assert_eq!(err, YamlError::KeyNotFound("nonexistent".to_string())); @@ -1341,7 +1341,7 @@ version: {version} test: test"#, version = SpecVersion::current() ); - let ob_yaml = OrderbookYaml::new(vec![yaml], OrderbookYamlValidation::default()).unwrap(); + let ob_yaml = RaindexYaml::new(vec![yaml], RaindexYamlValidation::default()).unwrap(); let syncs = ob_yaml.get_local_db_syncs().unwrap(); assert!(syncs.is_empty()); diff --git a/crates/subgraph/Cargo.toml b/crates/subgraph/Cargo.toml index 5508309c26..e052b3d9aa 100644 --- a/crates/subgraph/Cargo.toml +++ b/crates/subgraph/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "rain_orderbook_subgraph_client" -description = "Subgraph client, queries & schemas for the Rain Orderbook" +name = "raindex_subgraph_client" +description = "Subgraph client, queries & schemas for the Raindex" version.workspace = true edition.workspace = true license.workspace = true @@ -15,8 +15,8 @@ thiserror = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } alloy = { workspace = true, features = ["rand"] } -rain_orderbook_bindings = { workspace = true } -rain_orderbook_math = { workspace = true } +raindex_bindings = { workspace = true } +raindex_math = { workspace = true } chrono = { workspace = true } url = { workspace = true, features = ["serde"] } cynic-introspection = "3.7.3" diff --git a/crates/subgraph/schema/orderbook.graphql b/crates/subgraph/schema/raindex.graphql similarity index 100% rename from crates/subgraph/schema/orderbook.graphql rename to crates/subgraph/schema/raindex.graphql diff --git a/crates/subgraph/src/multi_orderbook_client.rs b/crates/subgraph/src/multi_raindex_client.rs similarity index 100% rename from crates/subgraph/src/multi_orderbook_client.rs rename to crates/subgraph/src/multi_raindex_client.rs diff --git a/crates/subgraph/src/performance/apy.rs b/crates/subgraph/src/performance/apy.rs index a30a3a35f6..298dbf93f5 100644 --- a/crates/subgraph/src/performance/apy.rs +++ b/crates/subgraph/src/performance/apy.rs @@ -6,7 +6,7 @@ use crate::{ use alloy::primitives::U256; use chrono::TimeDelta; use rain_math_float::Float; -use rain_orderbook_math::{BigUintMath, ONE18}; +use raindex_math::{BigUintMath, ONE18}; use serde::{Deserialize, Serialize}; use std::str::FromStr; #[cfg(target_family = "wasm")] diff --git a/crates/subgraph/src/performance/mod.rs b/crates/subgraph/src/performance/mod.rs index 758b7290eb..6ca3e56dbd 100644 --- a/crates/subgraph/src/performance/mod.rs +++ b/crates/subgraph/src/performance/mod.rs @@ -1,5 +1,5 @@ use rain_math_float::FloatError; -use rain_orderbook_math::MathError; +use raindex_math::MathError; use std::num::ParseIntError; use thiserror::Error; @@ -7,7 +7,7 @@ use thiserror::Error; // use alloy::primitives::{ruint::ParseError, U256}; // use chrono::TimeDelta; // use once_cell::sync::Lazy; -// use rain_orderbook_math::ONE18; +// use raindex_math::ONE18; // TODO: APY related logic // pub mod apy; diff --git a/crates/subgraph/src/performance/order_performance.rs b/crates/subgraph/src/performance/order_performance.rs index 140c031cd6..645a3db858 100644 --- a/crates/subgraph/src/performance/order_performance.rs +++ b/crates/subgraph/src/performance/order_performance.rs @@ -8,7 +8,7 @@ use crate::{ }; use alloy::primitives::U256; use rain_math_float::Float; -use rain_orderbook_math::{BigUintMath, ONE18}; +use raindex_math::{BigUintMath, ONE18}; use serde::{Deserialize, Serialize}; use std::cmp::Ordering; use std::collections::HashMap; diff --git a/crates/subgraph/src/orderbook_client/mod.rs b/crates/subgraph/src/raindex_client/mod.rs similarity index 100% rename from crates/subgraph/src/orderbook_client/mod.rs rename to crates/subgraph/src/raindex_client/mod.rs diff --git a/crates/subgraph/src/orderbook_client/order.rs b/crates/subgraph/src/raindex_client/order.rs similarity index 100% rename from crates/subgraph/src/orderbook_client/order.rs rename to crates/subgraph/src/raindex_client/order.rs diff --git a/crates/subgraph/src/orderbook_client/order_trade.rs b/crates/subgraph/src/raindex_client/order_trade.rs similarity index 100% rename from crates/subgraph/src/orderbook_client/order_trade.rs rename to crates/subgraph/src/raindex_client/order_trade.rs diff --git a/crates/subgraph/src/orderbook_client/performance.rs b/crates/subgraph/src/raindex_client/performance.rs similarity index 100% rename from crates/subgraph/src/orderbook_client/performance.rs rename to crates/subgraph/src/raindex_client/performance.rs diff --git a/crates/subgraph/src/orderbook_client/token.rs b/crates/subgraph/src/raindex_client/token.rs similarity index 100% rename from crates/subgraph/src/orderbook_client/token.rs rename to crates/subgraph/src/raindex_client/token.rs diff --git a/crates/subgraph/src/orderbook_client/transaction.rs b/crates/subgraph/src/raindex_client/transaction.rs similarity index 100% rename from crates/subgraph/src/orderbook_client/transaction.rs rename to crates/subgraph/src/raindex_client/transaction.rs diff --git a/crates/subgraph/src/orderbook_client/vault.rs b/crates/subgraph/src/raindex_client/vault.rs similarity index 100% rename from crates/subgraph/src/orderbook_client/vault.rs rename to crates/subgraph/src/raindex_client/vault.rs diff --git a/crates/subgraph/src/types/order_detail_traits.rs b/crates/subgraph/src/types/order_detail_traits.rs index 10e0e32578..0b947bdb84 100644 --- a/crates/subgraph/src/types/order_detail_traits.rs +++ b/crates/subgraph/src/types/order_detail_traits.rs @@ -5,7 +5,7 @@ use alloy::primitives::{ Address, B256, }; use alloy::sol_types::SolValue; -use rain_orderbook_bindings::IRaindexV6::{OrderV4, IOV2}; +use raindex_bindings::IRaindexV6::{OrderV4, IOV2}; use std::{num::TryFromIntError, str::FromStr}; use thiserror::Error; @@ -49,7 +49,7 @@ impl TryFrom for OrderV4 { mod tests { use alloy::hex; use alloy::primitives::{bytes, B256}; - use rain_orderbook_bindings::IRaindexV6::EvaluableV4; + use raindex_bindings::IRaindexV6::EvaluableV4; use std::vec; use super::*; diff --git a/crates/subgraph/tests/batch_order_test.rs b/crates/subgraph/tests/batch_order_test.rs index bc5e06ea6b..cf670968f0 100644 --- a/crates/subgraph/tests/batch_order_test.rs +++ b/crates/subgraph/tests/batch_order_test.rs @@ -1,6 +1,6 @@ use insta::assert_snapshot; -use rain_orderbook_subgraph_client::types::common::*; -use rain_orderbook_subgraph_client::types::order::{ +use raindex_subgraph_client::types::common::*; +use raindex_subgraph_client::types::order::{ SgBatchOrderDetailQuery, SgBatchOrderDetailQueryVariables, SgOrderIdList, }; diff --git a/crates/subgraph/tests/order_test.rs b/crates/subgraph/tests/order_test.rs index a75027a371..503f45bb81 100644 --- a/crates/subgraph/tests/order_test.rs +++ b/crates/subgraph/tests/order_test.rs @@ -1,7 +1,7 @@ use cynic::Id; use insta::assert_snapshot; -use rain_orderbook_subgraph_client::types::common::*; -use rain_orderbook_subgraph_client::types::order::SgOrderDetailByIdQuery; +use raindex_subgraph_client::types::common::*; +use raindex_subgraph_client::types::order::SgOrderDetailByIdQuery; #[test] fn orders_query_gql_output() { diff --git a/crates/subgraph/tests/order_trade_test.rs b/crates/subgraph/tests/order_trade_test.rs index 6e6c1b6b1f..258cca3299 100644 --- a/crates/subgraph/tests/order_trade_test.rs +++ b/crates/subgraph/tests/order_trade_test.rs @@ -1,7 +1,7 @@ use cynic::Id; use insta::assert_snapshot; -use rain_orderbook_subgraph_client::types::common::*; -use rain_orderbook_subgraph_client::types::order_trade::SgOrderTradeDetailQuery; +use raindex_subgraph_client::types::common::*; +use raindex_subgraph_client::types::order_trade::SgOrderTradeDetailQuery; #[test] fn vaults_query_gql_output() { diff --git a/crates/subgraph/tests/order_trades_test.rs b/crates/subgraph/tests/order_trades_test.rs index 3216621cf3..1f09873ce7 100644 --- a/crates/subgraph/tests/order_trades_test.rs +++ b/crates/subgraph/tests/order_trades_test.rs @@ -1,7 +1,7 @@ use cynic::Id; use insta::assert_snapshot; -use rain_orderbook_subgraph_client::types::common::*; -use rain_orderbook_subgraph_client::types::order_trade::SgOrderTradesListQuery; +use raindex_subgraph_client::types::common::*; +use raindex_subgraph_client::types::order_trade::SgOrderTradesListQuery; #[test] fn vaults_query_gql_output() { diff --git a/crates/subgraph/tests/orders_test.rs b/crates/subgraph/tests/orders_test.rs index ac138d6847..903253602d 100644 --- a/crates/subgraph/tests/orders_test.rs +++ b/crates/subgraph/tests/orders_test.rs @@ -1,6 +1,6 @@ use insta::assert_snapshot; -use rain_orderbook_subgraph_client::types::common::*; -use rain_orderbook_subgraph_client::types::order::SgOrdersListQuery; +use raindex_subgraph_client::types::common::*; +use raindex_subgraph_client::types::order::SgOrdersListQuery; #[test] fn orders_query_gql_output() { diff --git a/crates/subgraph/tests/vault_balance_changes_test.rs b/crates/subgraph/tests/vault_balance_changes_test.rs index 5c52c548c8..ac0a6ddcab 100644 --- a/crates/subgraph/tests/vault_balance_changes_test.rs +++ b/crates/subgraph/tests/vault_balance_changes_test.rs @@ -1,7 +1,7 @@ use cynic::Id; use insta::assert_snapshot; -use rain_orderbook_subgraph_client::types::common::*; -use rain_orderbook_subgraph_client::types::vault::SgVaultBalanceChangesListQuery; +use raindex_subgraph_client::types::common::*; +use raindex_subgraph_client::types::vault::SgVaultBalanceChangesListQuery; #[test] fn vault_balance_changes_list_query_gql_output() { diff --git a/crates/subgraph/tests/vault_test.rs b/crates/subgraph/tests/vault_test.rs index 6ca690b1c9..cacdfd9dd4 100644 --- a/crates/subgraph/tests/vault_test.rs +++ b/crates/subgraph/tests/vault_test.rs @@ -1,7 +1,7 @@ use cynic::Id; use insta::assert_snapshot; -use rain_orderbook_subgraph_client::types::common::*; -use rain_orderbook_subgraph_client::types::vault::SgVaultDetailQuery; +use raindex_subgraph_client::types::common::*; +use raindex_subgraph_client::types::vault::SgVaultDetailQuery; #[test] fn vaults_query_gql_output() { diff --git a/crates/subgraph/tests/vaults_test.rs b/crates/subgraph/tests/vaults_test.rs index d70917243f..d697c8c62b 100644 --- a/crates/subgraph/tests/vaults_test.rs +++ b/crates/subgraph/tests/vaults_test.rs @@ -1,6 +1,6 @@ use insta::assert_snapshot; -use rain_orderbook_subgraph_client::types::common::*; -use rain_orderbook_subgraph_client::types::vault::SgVaultsListQuery; +use raindex_subgraph_client::types::common::*; +use raindex_subgraph_client::types::vault::SgVaultsListQuery; #[test] fn vaults_query_gql_output() { diff --git a/crates/test_fixtures/Cargo.toml b/crates/test_fixtures/Cargo.toml index 404446079c..9971db1027 100644 --- a/crates/test_fixtures/Cargo.toml +++ b/crates/test_fixtures/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "rain_orderbook_test_fixtures" +name = "raindex_test_fixtures" version.workspace = true edition.workspace = true license.workspace = true From 1807c4e9aec0daa5c2f23f3dcfaf0e22051cf587 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Thu, 26 Mar 2026 17:24:14 +0400 Subject: [PATCH 04/69] Bump YAML spec version to 6 for raindex key renames Rename YAML config keys (orderbooks -> raindexes) and bump spec version from 5 to 6. Fix remaining Orderbook type references in js_api yaml module and settings crate. Co-Authored-By: Claude Opus 4.6 (1M context) --- crates/js_api/src/yaml/mod.rs | 104 ++++++++++++++-------------- crates/settings/src/spec_version.rs | 6 +- 2 files changed, 55 insertions(+), 55 deletions(-) diff --git a/crates/js_api/src/yaml/mod.rs b/crates/js_api/src/yaml/mod.rs index 42583f7725..5a527c2b77 100644 --- a/crates/js_api/src/yaml/mod.rs +++ b/crates/js_api/src/yaml/mod.rs @@ -2,11 +2,11 @@ use std::str::FromStr; use alloy::{hex::FromHexError, primitives::Address}; use raindex_app_settings::{ - orderbook::OrderbookCfg, + raindex::RaindexCfg, remote_tokens::{ParseRemoteTokensError, RemoteTokensCfg}, spec_version::CURRENT_SPEC_VERSION, yaml::{ - orderbook::{OrderbookYaml as OrderbookYamlCfg, OrderbookYamlValidation}, + raindex::{RaindexYaml as RaindexYamlCfg, RaindexYamlValidation}, YamlError, YamlParsable, }, }; @@ -17,43 +17,43 @@ use wasm_bindgen_utils::prelude::*; #[derive(Serialize, Deserialize, Debug, Clone)] #[wasm_bindgen] -pub struct OrderbookYaml { - yaml: OrderbookYamlCfg, +pub struct RaindexYaml { + yaml: RaindexYamlCfg, } #[wasm_export] -impl OrderbookYaml { - /// Creates a new OrderbookYaml instance from YAML configuration sources. +impl RaindexYaml { + /// Creates a new RaindexYaml instance from YAML configuration sources. /// - /// This constructor parses one or more YAML configuration strings to create an OrderbookYaml - /// instance that provides access to orderbook configurations, network settings, tokens, and + /// This constructor parses one or more YAML configuration strings to create an RaindexYaml + /// instance that provides access to raindex configurations, network settings, tokens, and /// other deployment metadata. The YAML sources are merged and validated according to the - /// [orderbook specification](https://github.com/rainlanguage/specs/blob/main/ob-yaml.md). + /// [raindex specification](https://github.com/rainlanguage/specs/blob/main/ob-yaml.md). /// /// ## Examples /// /// ```javascript /// // Basic usage with single YAML source /// const yamlConfig = ` - /// version: "5" + /// version: "6" /// networks: /// mainnet: /// rpc: https://mainnet.infura.io /// chain-id: 1 - /// orderbooks: - /// my-orderbook: + /// raindexes: + /// my-raindex: /// address: 0x1234567890abcdef1234567890abcdef12345678 /// network: mainnet /// ... /// `; /// - /// const result = OrderbookYaml.new([yamlConfig], false); + /// const result = RaindexYaml.new([yamlConfig], false); /// if (result.error) { /// console.error("Configuration error:", result.error.readableMsg); /// return; /// } - /// const orderbookYaml = result.value; - /// // Do something with the orderbookYaml + /// const raindexYaml = result.value; + /// // Do something with the raindexYaml /// ``` #[wasm_export( js_name = "new", @@ -69,12 +69,12 @@ impl OrderbookYaml { param_description = "Optional boolean to enable strict validation (defaults to false)" )] validate: Option, - ) -> Result { - let yaml = OrderbookYamlCfg::new( + ) -> Result { + let yaml = RaindexYamlCfg::new( sources, match validate { - Some(true) => OrderbookYamlValidation::full(), - _ => OrderbookYamlValidation::default(), + Some(true) => RaindexYamlValidation::full(), + _ => RaindexYamlValidation::default(), }, )?; Ok(Self { yaml }) @@ -84,7 +84,7 @@ impl OrderbookYaml { js_name = "getCurrentSpecVersion", return_description = "Current spec version" )] - pub fn get_current_spec_version() -> Result { + pub fn get_current_spec_version() -> Result { Ok(CURRENT_SPEC_VERSION.to_string()) } @@ -98,7 +98,7 @@ impl OrderbookYaml { /// /// ```javascript /// // Basic usage - /// const result = orderbookYaml.getOrderbookByAddress("0x1234567890abcdef1234567890abcdef12345678"); + /// const result = raindexYaml.getOrderbookByAddress("0x1234567890abcdef1234567890abcdef12345678"); /// if (result.error) { /// console.error("Error:", result.error.readableMsg); /// return; @@ -108,16 +108,16 @@ impl OrderbookYaml { /// ``` #[wasm_export( js_name = "getOrderbookByAddress", - unchecked_return_type = "OrderbookCfg", + unchecked_return_type = "RaindexCfg", return_description = "Complete orderbook configuration" )] pub fn get_orderbook_by_address( &self, #[wasm_export(param_description = "The hexadecimal address of the orderbook contract")] orderbook_address: &str, - ) -> Result { + ) -> Result { let address = - Address::from_str(orderbook_address).map_err(OrderbookYamlError::FromHexError)?; + Address::from_str(orderbook_address).map_err(RaindexYamlError::FromHexError)?; Ok(self.yaml.get_orderbook_by_address(address)?) } @@ -130,7 +130,7 @@ impl OrderbookYaml { /// ## Examples /// /// ```javascript - /// const result = await orderbookYaml.getTokens(); + /// const result = await raindexYaml.getTokens(); /// if (result.error) { /// console.error("Error:", result.error.readableMsg); /// return; @@ -146,7 +146,7 @@ impl OrderbookYaml { unchecked_return_type = "ExtendedTokenInfo[]", return_description = "Array of token information" )] - pub async fn get_tokens(&mut self) -> Result, OrderbookYamlError> { + pub async fn get_tokens(&mut self) -> Result, RaindexYamlError> { if let Some(remote_tokens_cfg) = self.yaml.get_remote_tokens()? { let networks = self.yaml.get_networks()?; let remote_tokens = RemoteTokensCfg::fetch_tokens(&networks, remote_tokens_cfg).await?; @@ -165,7 +165,7 @@ impl OrderbookYaml { } #[derive(Error, Debug)] -pub enum OrderbookYamlError { +pub enum RaindexYamlError { #[error("Orderbook yaml error: {0}")] YamlError(#[from] YamlError), #[error("Invalid address: {0}")] @@ -178,30 +178,30 @@ pub enum OrderbookYamlError { ERC20Error(#[from] raindex_common::erc20::Error), } -impl OrderbookYamlError { +impl RaindexYamlError { pub fn to_readable_msg(&self) -> String { match self { - OrderbookYamlError::YamlError(err) => + RaindexYamlError::YamlError(err) => format!("There was an error processing the YAML configuration. Please check the YAML file for any issues. Error: \"{}\"", err), - OrderbookYamlError::FromHexError(err) => + RaindexYamlError::FromHexError(err) => format!("The provided address is invalid. Please ensure the address is in the correct hexadecimal format. Error: \"{}\"", err), - OrderbookYamlError::MissingField(field) => + RaindexYamlError::MissingField(field) => format!("A required field is missing from the token configuration: \"{}\". Please ensure all tokens have decimals, label, and symbol defined.", field), - OrderbookYamlError::ParseRemoteTokensError(err) => + RaindexYamlError::ParseRemoteTokensError(err) => format!("Failed to fetch or parse remote tokens. Please check the using-tokens-from URLs are accessible and return valid token data. Error: \"{}\"", err), - OrderbookYamlError::ERC20Error(err) => + RaindexYamlError::ERC20Error(err) => format!("Failed to fetch token information from the blockchain. Please check your network connection and RPC settings. Error: \"{}\"", err), } } } -impl From for JsValue { - fn from(value: OrderbookYamlError) -> Self { +impl From for JsValue { + fn from(value: RaindexYamlError) -> Self { JsError::new(&value.to_string()).into() } } -impl From for WasmEncodedError { - fn from(value: OrderbookYamlError) -> Self { +impl From for WasmEncodedError { + fn from(value: RaindexYamlError) -> Self { WasmEncodedError { msg: value.to_string(), readable_msg: value.to_readable_msg(), @@ -233,7 +233,7 @@ pub(crate) mod tests { metaboards: board1: https://meta.example.com/board1 board2: https://meta.example.com/board2 - orderbooks: + raindexes: orderbook1: address: 0x0000000000000000000000000000000000000002 network: mainnet @@ -263,13 +263,13 @@ pub(crate) mod tests { #[wasm_bindgen_test] fn test_get_current_spec_version() { - let version = OrderbookYaml::get_current_spec_version().unwrap(); + let version = RaindexYaml::get_current_spec_version().unwrap(); assert_eq!(version, SpecVersion::current().to_string()); } #[wasm_bindgen_test] fn test_orderbook_yaml() { - let orderbook_yaml = OrderbookYaml::new(vec![get_yaml()], None).unwrap(); + let orderbook_yaml = RaindexYaml::new(vec![get_yaml()], None).unwrap(); let orderbook = orderbook_yaml .get_orderbook_by_address("0x0000000000000000000000000000000000000002") .unwrap(); @@ -286,7 +286,7 @@ pub(crate) mod tests { #[wasm_bindgen_test] fn test_orderbook_yaml_error() { - let orderbook_yaml = OrderbookYaml::new(vec![get_yaml()], None).unwrap(); + let orderbook_yaml = RaindexYaml::new(vec![get_yaml()], None).unwrap(); let orderbook = orderbook_yaml.get_orderbook_by_address("invalid-address"); assert!(orderbook.is_err()); @@ -323,7 +323,7 @@ pub(crate) mod tests { label: Ethereum Mainnet network-id: 1 currency: ETH - orderbooks: + raindexes: orderbook1: address: 0x0000000000000000000000000000000000000002 network: nonexistent-network @@ -337,7 +337,7 @@ pub(crate) mod tests { #[wasm_bindgen_test] fn test_orderbook_yaml_invalid_with_validation_enabled() { - let result = OrderbookYaml::new(vec![get_invalid_yaml()], Some(true)); + let result = RaindexYaml::new(vec![get_invalid_yaml()], Some(true)); match result { Ok(_) => panic!("Expected validation error with invalid YAML"), Err(err) => { @@ -351,7 +351,7 @@ pub(crate) mod tests { #[wasm_bindgen_test] async fn test_get_tokens_local_only() { - let mut orderbook_yaml = OrderbookYaml::new(vec![get_yaml()], None).unwrap(); + let mut orderbook_yaml = RaindexYaml::new(vec![get_yaml()], None).unwrap(); let tokens = orderbook_yaml.get_tokens().await.unwrap(); assert_eq!(tokens.len(), 1); @@ -406,7 +406,7 @@ pub(crate) mod tests { #[wasm_bindgen_test] async fn test_get_tokens_multiple_networks() { let mut orderbook_yaml = - OrderbookYaml::new(vec![get_yaml_multiple_networks()], None).unwrap(); + RaindexYaml::new(vec![get_yaml_multiple_networks()], None).unwrap(); let tokens = orderbook_yaml.get_tokens().await.unwrap(); assert_eq!(tokens.len(), 2); @@ -444,13 +444,13 @@ pub(crate) mod tests { #[wasm_bindgen_test] async fn test_get_tokens_missing_fields_tries_rpc() { - let mut orderbook_yaml = OrderbookYaml::new(vec![get_yaml_missing_fields()], None).unwrap(); + let mut orderbook_yaml = RaindexYaml::new(vec![get_yaml_missing_fields()], None).unwrap(); let result = orderbook_yaml.get_tokens().await; assert!(result.is_err()); let err = result.unwrap_err(); assert!( - matches!(err, OrderbookYamlError::ERC20Error(_)), + matches!(err, RaindexYamlError::ERC20Error(_)), "Expected ERC20Error when trying to fetch missing token info from RPC, got: {:?}", err ); @@ -510,7 +510,7 @@ mod non_wasm_tests { url = server.base_url() ); - let mut orderbook_yaml = OrderbookYaml::new(vec![yaml], None).unwrap(); + let mut orderbook_yaml = RaindexYaml::new(vec![yaml], None).unwrap(); let tokens = orderbook_yaml.get_tokens().await.unwrap(); assert_eq!(tokens.len(), 1); @@ -570,7 +570,7 @@ mod non_wasm_tests { url = server.base_url() ); - let mut orderbook_yaml = OrderbookYaml::new(vec![yaml], None).unwrap(); + let mut orderbook_yaml = RaindexYaml::new(vec![yaml], None).unwrap(); let tokens = orderbook_yaml.get_tokens().await.unwrap(); assert_eq!(tokens.len(), 2); @@ -620,7 +620,7 @@ mod non_wasm_tests { url = server.base_url() ); - let mut orderbook_yaml = OrderbookYaml::new(vec![yaml], None).unwrap(); + let mut orderbook_yaml = RaindexYaml::new(vec![yaml], None).unwrap(); let tokens = orderbook_yaml.get_tokens().await.unwrap(); assert_eq!(tokens.len(), 2); @@ -652,7 +652,7 @@ mod non_wasm_tests { url = server.base_url() ); - let mut orderbook_yaml = OrderbookYaml::new(vec![yaml], None).unwrap(); + let mut orderbook_yaml = RaindexYaml::new(vec![yaml], None).unwrap(); let result = orderbook_yaml.get_tokens().await; assert!(result.is_err()); @@ -712,7 +712,7 @@ mod non_wasm_tests { url = server.base_url() ); - let mut orderbook_yaml = OrderbookYaml::new(vec![yaml], None).unwrap(); + let mut orderbook_yaml = RaindexYaml::new(vec![yaml], None).unwrap(); let tokens = orderbook_yaml.get_tokens().await.unwrap(); assert_eq!(tokens.len(), 2); diff --git a/crates/settings/src/spec_version.rs b/crates/settings/src/spec_version.rs index 335afc962c..59d8d0c904 100644 --- a/crates/settings/src/spec_version.rs +++ b/crates/settings/src/spec_version.rs @@ -5,7 +5,7 @@ use strict_yaml_rust::StrictYaml; #[derive(Clone, Debug)] pub struct SpecVersion; -pub const CURRENT_SPEC_VERSION: &str = "5"; +pub const CURRENT_SPEC_VERSION: &str = "6"; impl SpecVersion { pub fn current() -> String { @@ -90,13 +90,13 @@ mod tests { #[test] fn test_is_current() { - assert!(SpecVersion::is_current("5")); + assert!(SpecVersion::is_current("6")); assert!(!SpecVersion::is_current("1")); } #[test] fn test_current() { - assert_eq!(SpecVersion::current(), "5"); + assert_eq!(SpecVersion::current(), "6"); } #[test] From dcab78af7b5907e097521aa1d40d41b85ca49a8a Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Thu, 26 Mar 2026 17:28:43 +0400 Subject: [PATCH 05/69] Fix remaining Orderbook references in dotrain_order and js_api Update import paths, YAML key strings, and constant prefixes that were missed in the initial Rust rename pass. Co-Authored-By: Claude Opus 4.6 (1M context) --- crates/common/src/dotrain_order.rs | 44 +++++++++++++++--------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/crates/common/src/dotrain_order.rs b/crates/common/src/dotrain_order.rs index 99328aaab8..a58982d59d 100644 --- a/crates/common/src/dotrain_order.rs +++ b/crates/common/src/dotrain_order.rs @@ -1,5 +1,5 @@ use crate::{ - add_order::{ORDERBOOK_ADDORDER_POST_TASK_ENTRYPOINTS, ORDERBOOK_ORDER_ENTRYPOINTS}, + add_order::{RAINDEX_ADDORDER_POST_TASK_ENTRYPOINTS, RAINDEX_ORDER_ENTRYPOINTS}, rainlang::compose_to_rainlang, }; use alloy::primitives::Address; @@ -9,13 +9,13 @@ use futures::future::join_all; use rain_interpreter_parser::{Parser2, ParserError, ParserV2}; pub use rain_metadata::types::authoring::v2::*; use raindex_app_settings::yaml::{ - clone_section_entry, context::ContextProfile, dotrain::DotrainYaml, orderbook::OrderbookYaml, + clone_section_entry, context::ContextProfile, dotrain::DotrainYaml, raindex::RaindexYaml, FieldErrorKind, YamlError, YamlParsable, }; use raindex_app_settings::{ remote_networks::ParseRemoteNetworksError, remote_tokens::ParseRemoteTokensError, - yaml::{dotrain::DotrainYamlValidation, orderbook::OrderbookYamlValidation}, + yaml::{dotrain::DotrainYamlValidation, raindex::RaindexYamlValidation}, }; use raindex_app_settings::{scenario::ScenarioCfg, spec_version::SpecVersion}; use serde::{Deserialize, Serialize}; @@ -25,7 +25,7 @@ use thiserror::Error; use wasm_bindgen_utils::prelude::*; /// DotrainOrder represents a parsed and validated dotrain configuration that combines -/// YAML frontmatter with Rainlang code for orderbook operations. +/// YAML frontmatter with Rainlang code for raindex operations. /// /// A dotrain file contains: /// - YAML frontmatter defining networks, tokens, orders, scenarios, and deployments @@ -313,8 +313,8 @@ impl DotrainOrder { sources.extend(settings); } - let mut orderbook_yaml = - OrderbookYaml::new(sources.clone(), OrderbookYamlValidation::default())?; + let mut raindex_yaml = + RaindexYaml::new(sources.clone(), RaindexYamlValidation::default())?; let mut dotrain_yaml = DotrainYaml::new_with_profile( sources.clone(), @@ -322,7 +322,7 @@ impl DotrainOrder { profile, )?; - let remote_data = orderbook_yaml.fetch_remote_data().await?; + let remote_data = raindex_yaml.fetch_remote_data().await?; if !remote_data.remote_networks.is_empty() { dotrain_yaml .cache @@ -396,7 +396,7 @@ impl DotrainOrder { Ok(compose_to_rainlang( self.dotrain.clone(), scenario.bindings.clone(), - &ORDERBOOK_ORDER_ENTRYPOINTS, + &RAINDEX_ORDER_ENTRYPOINTS, )?) } @@ -433,7 +433,7 @@ impl DotrainOrder { Ok(compose_to_rainlang( self.dotrain.clone(), scenario.bindings.clone(), - &ORDERBOOK_ADDORDER_POST_TASK_ENTRYPOINTS, + &RAINDEX_ADDORDER_POST_TASK_ENTRYPOINTS, )?) } @@ -472,7 +472,7 @@ impl DotrainOrder { Ok(compose_to_rainlang( self.dotrain.clone(), scenario.bindings.clone(), - &ORDERBOOK_ORDER_ENTRYPOINTS, + &RAINDEX_ORDER_ENTRYPOINTS, )?) } } @@ -482,8 +482,8 @@ impl DotrainOrder { self.dotrain_yaml.clone() } - pub fn orderbook_yaml(&self) -> OrderbookYaml { - OrderbookYaml::from_dotrain_yaml(self.dotrain_yaml.clone()) + pub fn raindex_yaml(&self) -> RaindexYaml { + RaindexYaml::from_dotrain_yaml(self.dotrain_yaml.clone()) } pub async fn get_pragmas_for_scenario( @@ -519,7 +519,7 @@ impl DotrainOrder { .iter() .map(|rpc| rpc.to_string()) .collect::>(); - let metaboard = self.orderbook_yaml().get_metaboard(&network.key)?.url; + let metaboard = self.raindex_yaml().get_metaboard(&network.key)?.url; Ok(AuthoringMetaV2::fetch_for_contract(address, rpcs, metaboard.to_string()).await?) } @@ -604,7 +604,7 @@ impl DotrainOrder { } pub async fn validate_spec_version(&self) -> Result<(), DotrainOrderError> { - let spec_version = self.orderbook_yaml().get_spec_version()?; + let spec_version = self.raindex_yaml().get_spec_version()?; if !SpecVersion::is_current(&spec_version) { return Err(DotrainOrderError::SpecVersionMismatch( SpecVersion::current(), @@ -620,7 +620,7 @@ impl DotrainOrder { deployment_key: &str, ) -> Result { let dotrain_yaml = self.dotrain_yaml(); - let orderbook_yaml = self.orderbook_yaml(); + let raindex_yaml = self.raindex_yaml(); let deployment = dotrain_yaml.get_deployment(deployment_key)?; let order_cfg = deployment.order.clone(); let scenario_cfg = deployment.scenario.clone(); @@ -637,7 +637,7 @@ impl DotrainOrder { let order_key = order_cfg.key.clone(); let deployment_key = deployment.key.clone(); - let metaboard_key = match orderbook_yaml.get_metaboard(&network_key) { + let metaboard_key = match raindex_yaml.get_metaboard(&network_key) { Ok(cfg) => Some(cfg.key.clone()), Err(YamlError::KeyNotFound(_)) => None, Err(YamlError::Field { @@ -649,7 +649,7 @@ impl DotrainOrder { let documents = dotrain_yaml.documents.clone(); - let spec_version = orderbook_yaml.get_spec_version()?; + let spec_version = raindex_yaml.get_spec_version()?; let mut root_hash = StrictYamlHash::new(); root_hash.insert( @@ -676,12 +676,12 @@ impl DotrainOrder { ); if let Some(orderbook_key) = orderbook_key { - let orderbook_value = clone_section_entry(&documents, "orderbooks", &orderbook_key) + let orderbook_value = clone_section_entry(&documents, "raindexes", &orderbook_key) .map_err(|err| DotrainOrderError::CleanUnusedFrontmatterError(err.to_string()))?; let mut orderbooks_hash = StrictYamlHash::new(); orderbooks_hash.insert(StrictYaml::String(orderbook_key.clone()), orderbook_value); root_hash.insert( - StrictYaml::String("orderbooks".to_string()), + StrictYaml::String("raindexes".to_string()), StrictYaml::Hash(orderbooks_hash), ); } @@ -928,7 +928,7 @@ _ _: 0 0; assert_eq!( dotrain_order - .orderbook_yaml() + .raindex_yaml() .get_network("polygon") .unwrap() .rpcs @@ -1205,7 +1205,7 @@ _ _: 0 0; let root = get_root_hash(&frontmatter); let StrictYaml::Hash(orderbooks) = root - .get(&StrictYaml::String("orderbooks".to_string())) + .get(&StrictYaml::String("raindexes".to_string())) .expect("orderbooks present") .clone() else { @@ -1389,7 +1389,7 @@ networks: assert_eq!( dotrain_order - .orderbook_yaml() + .raindex_yaml() .get_network("mainnet") .unwrap() .rpcs From d744018d400051937b6ca695ff27d15dd9b320a5 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Thu, 26 Mar 2026 17:50:56 +0400 Subject: [PATCH 06/69] Rename OrderBook to Raindex in config files Update foundry.toml, flake.nix, .gitignore, .devcontainer.json, package.json, README.md, AGENTS.md, copilot instructions, and GitHub workflow files. Co-Authored-By: Claude Opus 4.6 (1M context) --- .devcontainer.json | 2 +- .github/copilot-instructions.md | 14 ++++---- .github/workflows/build-cli-binary.yaml | 2 +- .github/workflows/npm-package-release.yml | 44 +++++++++++------------ .github/workflows/test-ui-components.yaml | 2 +- .github/workflows/test-webapp.yaml | 2 +- .gitignore | 8 ++--- AGENTS.md | 4 +-- README.md | 18 +++++----- flake.nix | 22 ++++++------ foundry.toml | 6 ++-- package.json | 10 +++--- 12 files changed, 68 insertions(+), 66 deletions(-) diff --git a/.devcontainer.json b/.devcontainer.json index 05cc6697d8..6fda67b28f 100644 --- a/.devcontainer.json +++ b/.devcontainer.json @@ -1,5 +1,5 @@ { - "name": "rain.orderbook dev", + "name": "raindex dev", "image": "ghcr.io/zombiezen/codespaces-nix", "remoteUser": "vscode", "features": { diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index a696e407c1..e8825f7061 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,6 +1,6 @@ > NOTE: Before using this guide, read the repository root `AGENTS.md` for authoritative agent instructions. -# Rain Orderbook – Agent Guide (Concise) +# Raindex – Agent Guide (Concise) Always run commands via Nix: `nix develop -c `. Never cancel long-running tasks (45–90 min builds, 30+ min tests). @@ -8,9 +8,9 @@ Always run commands via Nix: `nix develop -c `. Never cancel long-runni ```bash nix develop -c cargo build nix develop -c cargo build --target wasm32-unknown-unknown --lib -r --workspace \ - --exclude rain_orderbook_cli --exclude rain_orderbook_integration_tests + --exclude raindex_cli --exclude raindex_integration_tests nix develop -c npm install -nix develop -c npm run build:orderbook +nix develop -c npm run build:raindex nix develop -c npm run build:ui ``` @@ -19,7 +19,7 @@ If any step fails due to earlier lint/test issues, use the fallback below. ## 2. Development loop - Edit code - Rebuild dependencies you touched: - - Rust used by `@rainlanguage/orderbook` → `nix develop -c npm run build:orderbook` + - Rust used by `@rainlanguage/raindex` → `nix develop -c npm run build:raindex` - `@rainlanguage/ui-components` → `nix develop -c npm run build -w @rainlanguage/ui-components` - Run targeted tests and lints for changed areas @@ -28,7 +28,7 @@ If any step fails due to earlier lint/test issues, use the fallback below. | Area | Build (if needed) | Lint/Check | Tests | |------|--------------------|------------|-------| | Rust crates (`crates/*`) | `nix develop -c cargo build` | `nix develop -c cargo clippy --workspace --all-targets --all-features -D warnings` | `nix develop -c cargo test --workspace` or `--package ` | -| Orderbook TS (`packages/orderbook`) | `nix develop -c npm run build:orderbook` | `nix develop -c npm run check -w @rainlanguage/orderbook` | `nix develop -c npm run test -w @rainlanguage/orderbook` | +| Orderbook TS (`packages/orderbook`) | `nix develop -c npm run build:raindex` | `nix develop -c npm run check -w @rainlanguage/raindex` | `nix develop -c npm run test -w @rainlanguage/raindex` | | UI components (`packages/ui-components`) | `nix develop -c npm run build -w @rainlanguage/ui-components` | `nix develop -c npm run svelte-lint-format-check -w @rainlanguage/ui-components` | `nix develop -c npm run test -w @rainlanguage/ui-components` | | Webapp (`packages/webapp`) | `nix develop -c npm run build -w @rainlanguage/webapp` | `nix develop -c npm run svelte-lint-format-check -w @rainlanguage/webapp` | `nix develop -c npm run test -w @rainlanguage/webapp` | | Solidity contracts | `nix develop -c forge build` | — | `nix develop -c forge test` | @@ -48,7 +48,7 @@ Partial commits are OK during the session. Before your final commit of the sessi ```bash ./prep-all.sh nix develop -c npm run lint-format-check:all -nix develop -c npm run build:orderbook # if Rust/orderbook changed +nix develop -c npm run build:raindex # if Rust/orderbook changed nix develop -c npm run build:ui nix develop -c cargo test --workspace nix develop -c npm run test @@ -72,7 +72,7 @@ nix develop -c bash -c '(cd lib/rain.interpreter/lib/rain.interpreter.interface/ nix develop -c bash -c '(cd lib/rain.interpreter/lib/rain.metadata && rainix-sol-prelude && rainix-rs-prelude)' nix develop -c rainix-sol-prelude && nix develop -c rainix-rs-prelude && nix develop -c raindex-prelude nix develop -c ob-ui-components-prelude -nix develop -c npm run build -w @rainlanguage/orderbook +nix develop -c npm run build -w @rainlanguage/raindex nix develop -c npm run build -w @rainlanguage/ui-components nix develop -c npm run build -w @rainlanguage/webapp ``` diff --git a/.github/workflows/build-cli-binary.yaml b/.github/workflows/build-cli-binary.yaml index fd33e38a0f..e550828f91 100644 --- a/.github/workflows/build-cli-binary.yaml +++ b/.github/workflows/build-cli-binary.yaml @@ -51,7 +51,7 @@ jobs: BUILD_TIMESTAMP=$(date -u +"%Y%m%dT%H%M%SZ") echo "TAG_NAME=cli-${SHORT_SHA}-${BUILD_TIMESTAMP}" >> "$GITHUB_ENV" echo "RELEASE_NAME=CLI Binary ${SHORT_SHA} (${BUILD_TIMESTAMP})" >> "$GITHUB_ENV" - echo "ASSET_PATH=crates/cli/bin/rain-orderbook-cli.tar.gz" >> "$GITHUB_ENV" + echo "ASSET_PATH=crates/cli/bin/raindex-cli.tar.gz" >> "$GITHUB_ENV" - name: Publish GitHub release uses: softprops/action-gh-release@v2 diff --git a/.github/workflows/npm-package-release.yml b/.github/workflows/npm-package-release.yml index ca17145963..759ab2d41c 100644 --- a/.github/workflows/npm-package-release.yml +++ b/.github/workflows/npm-package-release.yml @@ -78,13 +78,13 @@ jobs: run: | echo "Checking repository consistency..." GIT_REPO=$(git remote get-url origin | sed 's/.*github.com[/:]//; s/.git$//') - OB_PKG_REPO=$(node -e "console.log(require('./packages/orderbook/package.json').repository?.url || '')" | sed 's|https://github.com/||; s|git+||; s|.git$||') + DEX_PKG_REPO=$(node -e "console.log(require('./packages/raindex/package.json').repository?.url || '')" | sed 's|https://github.com/||; s|git+||; s|.git$||') UC_PKG_REPO=$(node -e "console.log(require('./packages/ui-components/package.json').repository?.url || '')" | sed 's|https://github.com/||; s|git+||; s|.git$||') echo "Git remote: $GIT_REPO" - echo "orderbook package.json: $OB_PKG_REPO" + echo "raindex package.json: $DEX_PKG_REPO" echo "ui-components package.json: $UC_PKG_REPO" - if [ "$GIT_REPO" != "$OB_PKG_REPO" ]; then - echo "Repository mismatch for orderbook!" + if [ "$GIT_REPO" != "$DEX_PKG_REPO" ]; then + echo "Repository mismatch for raindex!" echo "This will cause 422 error during publish" exit 1 fi @@ -134,12 +134,12 @@ jobs: - name: Test UI Components run: nix develop -c npm run test -w @rainlanguage/ui-components - # check for npm package blacklists pkgs across all orderbook related packages + # check for npm package blacklists pkgs across all raindex related packages - uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main - uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main with: - working-directory: packages/orderbook + working-directory: packages/raindex - uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main with: @@ -154,18 +154,18 @@ jobs: # get hash of latest published pkgs from npm and concat them - name: Get Old Hash run: | - OB_PKG_OLD_HASH=$(npm view @rainlanguage/orderbook@latest dist.shasum 2>/dev/null || echo "none") + DEX_PKG_OLD_HASH=$(npm view @rainlanguage/raindex@latest dist.shasum 2>/dev/null || echo "none") UC_PKG_OLD_HASH=$(npm view @rainlanguage/ui-components@latest dist.shasum 2>/dev/null || echo "none") - OLD_HASH=$OB_PKG_OLD_HASH-$UC_PKG_OLD_HASH + OLD_HASH=$DEX_PKG_OLD_HASH-$UC_PKG_OLD_HASH echo "OLD_HASH=$OLD_HASH" >> $GITHUB_ENV echo "old hash: $OLD_HASH" # calc hash of current workspace pkgs by packing them and concat them - name: Get New Hash run: | - OB_PKG_NEW_HASH=$(npm pack --silent -w @rainlanguage/orderbook | xargs shasum | cut -c1-40) + DEX_PKG_NEW_HASH=$(npm pack --silent -w @rainlanguage/raindex | xargs shasum | cut -c1-40) UC_PKG_NEW_HASH=$(npm pack --silent -w @rainlanguage/ui-components | xargs shasum | cut -c1-40) - NEW_HASH=$OB_PKG_NEW_HASH-$UC_PKG_NEW_HASH + NEW_HASH=$DEX_PKG_NEW_HASH-$UC_PKG_NEW_HASH echo "NEW_HASH=$NEW_HASH" >> $GITHUB_ENV echo "new hash: $NEW_HASH" rm -f *.tgz @@ -176,27 +176,27 @@ jobs: - name: Set Version if: ${{ env.OLD_HASH != env.NEW_HASH }} run: | - npm version prerelease --preid alpha --no-git-tag-version -w @rainlanguage/orderbook - NEW_VERSION=$(jq -r '.version' ./packages/orderbook/package.json) + npm version prerelease --preid alpha --no-git-tag-version -w @rainlanguage/raindex + NEW_VERSION=$(jq -r '.version' ./packages/raindex/package.json) echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV - jq --arg v "$NEW_VERSION" '.dependencies."@rainlanguage/orderbook" = $v' ./packages/ui-components/package.json > tmp.json && mv tmp.json ./packages/ui-components/package.json + jq --arg v "$NEW_VERSION" '.dependencies."@rainlanguage/raindex" = $v' ./packages/ui-components/package.json > tmp.json && mv tmp.json ./packages/ui-components/package.json npx prettier --write ./packages/ui-components/package.json npm version prerelease --preid alpha --no-git-tag-version -w @rainlanguage/ui-components - # Create orderbook npm package tarball - - name: Create orderbook NPM Package Tarball + # Create raindex npm package tarball + - name: Create raindex NPM Package Tarball if: ${{ env.OLD_HASH != env.NEW_HASH }} - run: echo "OB_NPM_PACKAGE=$(npm pack --silent -w @rainlanguage/orderbook)" >> $GITHUB_ENV + run: echo "OB_NPM_PACKAGE=$(npm pack --silent -w @rainlanguage/raindex)" >> $GITHUB_ENV - - name: Rename orderbook NPM Package Tarball + - name: Rename raindex NPM Package Tarball if: ${{ env.OLD_HASH != env.NEW_HASH }} - run: mv ${{ env.OB_NPM_PACKAGE }} orderbook_npm_package_${{ env.NEW_VERSION }}.tgz + run: mv ${{ env.OB_NPM_PACKAGE }} raindex_npm_package_${{ env.NEW_VERSION }}.tgz # publish orderbook pkg to npm - - name: Publish orderbook pkg To NPM + - name: Publish raindex pkg To NPM if: ${{ env.OLD_HASH != env.NEW_HASH }} run: | - npm publish orderbook_npm_package_${{ env.NEW_VERSION }}.tgz \ + npm publish raindex_npm_package_${{ env.NEW_VERSION }}.tgz \ --access public \ --tag latest \ --verbose @@ -223,7 +223,7 @@ jobs: - name: Commit And Tag if: ${{ env.OLD_HASH != env.NEW_HASH }} run: | - git add "packages/orderbook/package.json" + git add "packages/raindex/package.json" git add "packages/ui-components/package.json" git add "package-lock.json" git commit -m "NPM Package Release v${{ env.NEW_VERSION }}" @@ -247,7 +247,7 @@ jobs: tag_name: npm-v${{ env.NEW_VERSION }} name: NPM Package Release v${{ env.NEW_VERSION }} files: | - orderbook_npm_package_${{ env.NEW_VERSION }}.tgz + raindex_npm_package_${{ env.NEW_VERSION }}.tgz ui_components_npm_package_${{ env.NEW_VERSION }}.tgz env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test-ui-components.yaml b/.github/workflows/test-ui-components.yaml index 11724ca986..be5049c380 100644 --- a/.github/workflows/test-ui-components.yaml +++ b/.github/workflows/test-ui-components.yaml @@ -62,7 +62,7 @@ jobs: - uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main with: - working-directory: packages/orderbook + working-directory: packages/raindex - uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main with: diff --git a/.github/workflows/test-webapp.yaml b/.github/workflows/test-webapp.yaml index e1061e1a16..c1ba4971ad 100644 --- a/.github/workflows/test-webapp.yaml +++ b/.github/workflows/test-webapp.yaml @@ -66,7 +66,7 @@ jobs: - uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main with: - working-directory: packages/orderbook + working-directory: packages/raindex - uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main with: diff --git a/.gitignore b/.gitignore index 0192bcf53d..01a26e9273 100644 --- a/.gitignore +++ b/.gitignore @@ -10,10 +10,10 @@ subgraph/tests/.latest.json node_modules temp dist -packages/orderbook/cjs.js -packages/orderbook/cjs.d.ts -packages/orderbook/esm.js -packages/orderbook/esm.d.ts +packages/raindex/cjs.js +packages/raindex/cjs.d.ts +packages/raindex/esm.js +packages/raindex/esm.d.ts .direnv/ # Audit proposed fixes diff --git a/AGENTS.md b/AGENTS.md index 98b5486c95..99c8dffad8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -3,7 +3,7 @@ ## Project Structure & Module Organization - Solidity contracts: `src/`, tests in `test/` with fixtures in `test-resources/`. - Rust workspace: `crates/*` (e.g., `cli`, `common`, `bindings`, `js_api`, `quote`, `subgraph`, `settings`, `math`, `integration_tests`). -- JavaScript/Svelte: `packages/*` — `webapp`, `ui-components`, `orderbook` (wasm wrapper published to npm). +- JavaScript/Svelte: `packages/*` — `webapp`, `ui-components`, `raindex` (wasm wrapper published to npm). - Subgraph and tooling: `subgraph/`, `script/`, helper scripts like `prep-all.sh`. ## Build, Test, and Development Commands @@ -11,7 +11,7 @@ - Rust: `cargo build --workspace`; tests: `cargo test`. - Solidity (Foundry): `forge build`; tests: `forge test`. - Webapp: `cd packages/webapp && npm run dev`. -- JS workspaces (top-level): `npm run test`, `npm run build:ui`, `npm run build:orderbook`. +- JS workspaces (top-level): `npm run test`, `npm run build:ui`, `npm run build:raindex`. - WASM bundle: `rainix-wasm-artifacts`. ## Coding Style & Naming Conventions diff --git a/README.md b/README.md index 71159711e9..59a6afb2e9 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,25 @@ -# rain.orderbook +# Raindex -Rain Orderbook (also known as Raindex) is an open source, permissionless orderbook system with no fees or admin keys. +Raindex is an open source, permissionless orderbook system with no fees or admin keys. ## Repository Structure This repository contains several components: -- **Solidity Contracts**: The core smart contracts for the Rain Orderbook (`src`) -- **Rust Crates**: Various tooling and libraries for interacting with the Rain Orderbook (`crates/*`) +- **Solidity Contracts**: The core smart contracts for Raindex (`src`) +- **Rust Crates**: Various tooling and libraries for interacting with Raindex (`crates/*`) - **JavaScript Packages (`packages/*`)**: - `webapp`: A SvelteKit site for Raindex - `ui-components`: A shared component library used in the webapp - - `orderbook`: A TypeScript package (published to npm) that provides bindings to the Rust crates + - `raindex`: A TypeScript package (published to npm) that provides bindings to the Rust crates ### Architecture -We use wasm-bindgen to create the `orderbook` package from our Rust crates, which is then used by: +We use wasm-bindgen to create the `raindex` package from our Rust crates, which is then used by: - The UI components library - The webapp -This same package is [published to npm](https://www.npmjs.com/package/@rainlanguage/orderbook), allowing developers to more easily create their own frontends for Raindex. +This same package is [published to npm](https://www.npmjs.com/package/@rainlanguage/raindex), allowing developers to more easily create their own frontends for Raindex. ## Setup for local development @@ -48,8 +48,8 @@ Contracts are deployed via the Foundry script at `script/Deploy.sol`. The script - `DEPLOYMENT_KEY` — the deployer private key - `DEPLOYMENT_SUITE` — which contracts to deploy. One of: - - `raindex` — OrderBookV6 only - - `subparser` — OrderBookV6SubParser only + - `raindex` — RaindexV6 only + - `subparser` — RaindexV6SubParser only - `route-processor` — Sushi RouteProcessor4 only - `arb` — arb contracts only (order takers and flash borrowers) diff --git a/flake.nix b/flake.nix index c3a5f1f4ad..8e21de91f9 100644 --- a/flake.nix +++ b/flake.nix @@ -23,12 +23,12 @@ mkdir -p meta; forge script --silent ./script/BuildAuthoringMeta.sol; rain meta build \ - -i <(cat ./meta/OrderBookV6SubParserAuthoringMeta.rain.meta) \ + -i <(cat ./meta/RaindexV6SubParserAuthoringMeta.rain.meta) \ -m authoring-meta-v2 \ -t cbor \ -e deflate \ -l none \ - -o meta/OrderBookV6SubParser.rain.meta \ + -o meta/RaindexV6SubParser.rain.meta \ ; ''; }; @@ -62,17 +62,17 @@ set -euxo pipefail OUTPUT_DIR=crates/cli/bin - ARCHIVE_NAME=rain-orderbook-cli.tar.gz - BINARY_NAME=rain-orderbook-cli + ARCHIVE_NAME=raindex-cli.tar.gz + BINARY_NAME=raindex-cli TARGET_TRIPLE=x86_64-unknown-linux-gnu - cargo build --release -p rain_orderbook_cli --target "$TARGET_TRIPLE" + cargo build --release -p raindex_cli --target "$TARGET_TRIPLE" mkdir -p "$OUTPUT_DIR" rm -f "$OUTPUT_DIR/$ARCHIVE_NAME" - cp "target/$TARGET_TRIPLE/release/rain_orderbook_cli" "$OUTPUT_DIR/$BINARY_NAME" + cp "target/$TARGET_TRIPLE/release/raindex_cli" "$OUTPUT_DIR/$BINARY_NAME" chmod 755 "$OUTPUT_DIR/$BINARY_NAME" strip "$OUTPUT_DIR/$BINARY_NAME" || true @@ -87,7 +87,7 @@ body = '' set -euxo pipefail - cargo build --profile release-wasm --target wasm32-unknown-unknown --lib -p rain_orderbook_js_api + cargo build --profile release-wasm --target wasm32-unknown-unknown --lib -p raindex_js_api ''; }; @@ -96,7 +96,7 @@ body = '' set -euxo pipefail - CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER='wasm-bindgen-test-runner' cargo test --target wasm32-unknown-unknown --lib -p rain_orderbook_quote -p rain_orderbook_bindings -p rain_orderbook_js_api -p rain_orderbook_common + CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER='wasm-bindgen-test-runner' cargo test --target wasm32-unknown-unknown --lib -p raindex_quote -p raindex_bindings -p raindex_js_api -p raindex_common ''; }; @@ -121,7 +121,7 @@ name = "js-install"; body = '' set -euxo pipefail - cd packages/orderbook + cd packages/raindex npm install --no-check ''; }; @@ -130,7 +130,7 @@ name = "build-js-bindings"; body = '' set -euxo pipefail - cd packages/orderbook + cd packages/raindex npm run build ''; }; @@ -139,7 +139,7 @@ name = "test-js-bindings"; body = '' set -euxo pipefail - cd packages/orderbook + cd packages/raindex npm install --no-check npm run build npm test diff --git a/foundry.toml b/foundry.toml index 5f0694e3f1..3212810d14 100644 --- a/foundry.toml +++ b/foundry.toml @@ -18,8 +18,10 @@ evm_version = "cancun" # optimizer settings for snapshotting. optimizer = true # Lowered from 1000000 → 1000 → 800 to stay under the EIP-170 24KB contract -# size limit. At 1000 runs OrderBookV6 was 24,650 bytes (74 over); at 800 it +# size limit. At 1000 runs RaindexV6 was 24,650 bytes (74 over); at 800 it # is 23,437 bytes (1,139 under). +# NOTE: the size was measured when the contract was named OrderBookV6; +# after the rename to RaindexV6 the bytecode is identical. optimizer_runs = 800 bytecode_hash = "none" @@ -33,7 +35,7 @@ fs_permissions = [ { access = "read", path = "./lib/rain.interpreter/deployments/latest/RainterpreterStoreNPE2" }, { access = "read", path = "./lib/rain.interpreter/deployments/latest/RainterpreterNPE2" }, { access = "read", path = "./lib/rain.interpreter/deployments/latest/RainterpreterExpressionDeployerNPE2" }, - { access = "read-write", path = "./meta/OrderBookV6SubParserAuthoringMeta.rain.meta"}, + { access = "read-write", path = "./meta/RaindexV6SubParserAuthoringMeta.rain.meta"}, { access = "read-write", path = "src/generated" }, { access = "read", path = "./subgraph" }, ] diff --git a/package.json b/package.json index 17107eeb38..d6b06a623a 100644 --- a/package.json +++ b/package.json @@ -5,19 +5,19 @@ "private": true, "repository": { "type": "git", - "url": "https://github.com/rainlanguage/rain.orderbook.git" + "url": "https://github.com/rainlanguage/raindex.git" }, "keywords": [], "bugs": { - "url": "https://github.com/rainlanguage/rain.orderbook/issues" + "url": "https://github.com/rainlanguage/raindex/issues" }, - "homepage": "https://github.com/rainlanguage/rain.orderbook#readme", + "homepage": "https://github.com/rainlanguage/raindex#readme", "engines": { "node": ">=18" }, "scripts": { "build": "npm run build --workspaces", - "build:orderbook": "npm run build -w @rainlanguage/orderbook", + "build:raindex": "npm run build -w @rainlanguage/raindex", "build:ui": "npm run build -w @rainlanguage/ui-components && npm run build -w @rainlanguage/webapp", "dev": "npm run dev --workspaces", "test": "npm run test --workspaces", @@ -74,7 +74,7 @@ ], "dependencies": { "@fast-check/vitest": "0.2.0", - "@rainlanguage/orderbook": "workspace:*", + "@rainlanguage/raindex": "workspace:*", "@rainlanguage/sqlite-web": "^0.0.2", "@rainlanguage/ui-components": "workspace:*", "@reown/appkit": "1.6.4", From b1cfa280f3f74fbec67e2f7606f906bf7ac1077b Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Thu, 26 Mar 2026 21:41:05 +0400 Subject: [PATCH 07/69] Rename packages/orderbook to packages/raindex Rename directory, update package.json names and URLs, update build scripts (wasm crate name, wbg json), ARCHITECTURE.md, README.md, test files, and ui-components dependency reference. Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/{orderbook => raindex}/.gitignore | 0 packages/{orderbook => raindex}/.prettierrc | 0 .../{orderbook => raindex}/ARCHITECTURE.md | 63 +++++----- packages/{orderbook => raindex}/README.md | 58 ++++----- packages/{orderbook => raindex}/package.json | 12 +- .../{orderbook => raindex}/scripts/build.js | 0 .../scripts/buildPackage.js | 10 +- .../{orderbook => raindex}/scripts/setup.js | 0 .../scripts/sizeCheck.js | 0 .../test/bindings/test.test.ts | 0 .../test/common/test.test.ts | 0 .../test/js_api/dotrainRainlang.test.ts | 0 .../test/js_api/gui.test.ts | 0 .../test/js_api/raindexClient.test.ts | 0 .../test/js_api/raindexYaml.test.ts} | 114 +++++++++--------- .../{orderbook => raindex}/test/tsconfig.json | 0 packages/{orderbook => raindex}/tsconfig.json | 0 packages/{orderbook => raindex}/typedoc.json | 0 packages/ui-components/package.json | 4 +- 19 files changed, 130 insertions(+), 131 deletions(-) rename packages/{orderbook => raindex}/.gitignore (100%) rename packages/{orderbook => raindex}/.prettierrc (100%) rename packages/{orderbook => raindex}/ARCHITECTURE.md (52%) rename packages/{orderbook => raindex}/README.md (94%) rename packages/{orderbook => raindex}/package.json (75%) rename packages/{orderbook => raindex}/scripts/build.js (100%) rename packages/{orderbook => raindex}/scripts/buildPackage.js (95%) rename packages/{orderbook => raindex}/scripts/setup.js (100%) rename packages/{orderbook => raindex}/scripts/sizeCheck.js (100%) rename packages/{orderbook => raindex}/test/bindings/test.test.ts (100%) rename packages/{orderbook => raindex}/test/common/test.test.ts (100%) rename packages/{orderbook => raindex}/test/js_api/dotrainRainlang.test.ts (100%) rename packages/{orderbook => raindex}/test/js_api/gui.test.ts (100%) rename packages/{orderbook => raindex}/test/js_api/raindexClient.test.ts (100%) rename packages/{orderbook/test/js_api/orderbookYaml.test.ts => raindex/test/js_api/raindexYaml.test.ts} (82%) rename packages/{orderbook => raindex}/test/tsconfig.json (100%) rename packages/{orderbook => raindex}/tsconfig.json (100%) rename packages/{orderbook => raindex}/typedoc.json (100%) diff --git a/packages/orderbook/.gitignore b/packages/raindex/.gitignore similarity index 100% rename from packages/orderbook/.gitignore rename to packages/raindex/.gitignore diff --git a/packages/orderbook/.prettierrc b/packages/raindex/.prettierrc similarity index 100% rename from packages/orderbook/.prettierrc rename to packages/raindex/.prettierrc diff --git a/packages/orderbook/ARCHITECTURE.md b/packages/raindex/ARCHITECTURE.md similarity index 52% rename from packages/orderbook/ARCHITECTURE.md rename to packages/raindex/ARCHITECTURE.md index 9294432a70..a05dc20790 100644 --- a/packages/orderbook/ARCHITECTURE.md +++ b/packages/raindex/ARCHITECTURE.md @@ -1,6 +1,6 @@ -# @rainlanguage/orderbook — Architecture +# @rainlanguage/raindex — Architecture -This package is the JavaScript/TypeScript SDK that exposes Rain Orderbook functionality to web and Node.js consumers. It packages the Rust WASM crate surface (primarily `rain_orderbook_js_api`, plus re‑exports from sibling crates) into a single, installable NPM module with CJS and ESM entry points. +This package is the JavaScript/TypeScript SDK that exposes Raindex functionality to web and Node.js consumers. It packages the Rust WASM crate surface (primarily `raindex_js_api`, plus re-exports from sibling crates) into a single, installable NPM module with CJS and ESM entry points. The SDK is designed to work in browsers, Node.js, and hybrid runtimes. It embeds the compiled `.wasm` bytes directly in the published bundle so consumers do not need network fetches or filesystem access at runtime. @@ -8,17 +8,17 @@ The SDK is designed to work in browsers, Node.js, and hybrid runtimes. It embeds ## Overview - Purpose - - Provide a WASM‑backed API for: YAML parsing/validation, orderbook queries (subgraph), quoting, vault management, transaction calldata generation (add/remove, deposit/withdraw), GUI helpers to deploy orders from dotrain, and low‑level hashing/ABI helpers. + - Provide a WASM-backed API for: YAML parsing/validation, raindex queries (subgraph), quoting, vault management, transaction calldata generation (add/remove, deposit/withdraw), GUI helpers to deploy orders from dotrain, and low-level hashing/ABI helpers. - Targets - ESM (browser) and CJS (Node.js) builds are both published. - - The WASM is base64‑embedded to avoid runtime `fetch`/`fs` requirements. + - The WASM is base64-embedded to avoid runtime `fetch`/`fs` requirements. - Upstream crates - - Backed by `rain_orderbook_js_api` (WASM cdylib) which re‑exports `rain_orderbook_app_settings`, `rain_orderbook_common`, and `rain_orderbook_subgraph_client` for a unified JS surface. + - Backed by `raindex_js_api` (WASM cdylib) which re-exports `raindex_app_settings`, `raindex_common`, and `raindex_subgraph_client` for a unified JS surface. Typical import ```ts -import { RaindexClient, DotrainOrderGui, parseYaml, getOrderHash } from "@rainlanguage/orderbook"; +import { RaindexClient, DotrainOrderGui, parseYaml, getOrderHash } from "@rainlanguage/raindex"; ``` @@ -27,19 +27,19 @@ import { RaindexClient, DotrainOrderGui, parseYaml, getOrderHash } from "@rainla All builds should be run inside a Nix shell to ensure toolchain parity (`nix develop -c `). - Entry generation (`scripts/build.js`) - - Writes thin top‑level entry files: `cjs.js` (CommonJS re‑export), `esm.js` (ESM re‑export), plus `.d.ts` stubs. + - Writes thin top-level entry files: `cjs.js` (CommonJS re-export), `esm.js` (ESM re-export), plus `.d.ts` stubs. - Creates `dist/cjs` and `dist/esm` directories. - Invokes `npm run build-wasm` to compile the Rust workspace to `wasm32-unknown-unknown` in release mode (excludes CLI and integration tests). - For each package (currently just `js_api`), calls `scripts/buildPackage.js` to produce JS bindings and package artifacts. - WASM binding & embedding (`scripts/buildPackage.js`) - Runs `wasm-bindgen` twice to generate Node (CJS) and Web (ESM) wrappers from the compiled `.wasm`. The `wasm-bindgen` binary comes from the Nix environment. - - Reads the generated `.wasm` files and writes `dist/cjs/orderbook_wbg.json` and `dist/esm/orderbook_wbg.json` containing base64‑encoded bytes. + - Reads the generated `.wasm` files and writes `dist/cjs/raindex_wbg.json` and `dist/esm/raindex_wbg.json` containing base64-encoded bytes. - Rewrites the generated JS to: - CJS: read bytes from the embedded JSON via `Buffer.from(base64)` and initialize the module without touching the filesystem. - - ESM: import the embedded JSON and use top‑level `await __wbg_init(bytes)` to initialize the WASM before exporting symbols. - - Copies type declarations to `dist/*/index.d.ts` and prefixes generated files with a note that they are auto‑generated. + - ESM: import the embedded JSON and use top-level `await __wbg_init(bytes)` to initialize the WASM before exporting symbols. + - Copies type declarations to `dist/*/index.d.ts` and prefixes generated files with a note that they are auto-generated. - Prepublish bootstrap (`scripts/setup.js`) - - If `./dist` exists, exits early (supporting installs from already‑built tarballs). + - If `./dist` exists, exits early (supporting installs from already-built tarballs). - Otherwise, cleans temp/outputs and runs the full build inside Nix: `nix develop -c node scripts/build`. - Type checking & tests - `npm run check` runs `tsc` over the built JS to validate the emitted types. @@ -54,52 +54,52 @@ Key commands ## Directory Layout -- `cjs.js`, `esm.js` — Top‑level re‑exports pointing at `dist/` (published files). -- `cjs.d.ts`, `esm.d.ts` — Type re‑export stubs for consumers. +- `cjs.js`, `esm.js` — Top-level re-exports pointing at `dist/` (published files). +- `cjs.d.ts`, `esm.d.ts` — Type re-export stubs for consumers. - `dist/` — Build output (published) - `cjs/` - - `index.js` — Auto‑generated CommonJS glue that initializes WASM from `orderbook_wbg.json`. + - `index.js` — Auto-generated CommonJS glue that initializes WASM from `raindex_wbg.json`. - `index.d.ts` — Type declarations. - - `orderbook_wbg.json` — Base64‑encoded WASM bytes. + - `raindex_wbg.json` — Base64-encoded WASM bytes. - `esm/` - - `index.js` — Auto‑generated ESM glue with top‑level `await` for WASM init. + - `index.js` — Auto-generated ESM glue with top-level `await` for WASM init. - `index.d.ts` — Type declarations. - - `orderbook_wbg.json` — Base64‑encoded WASM bytes. + - `raindex_wbg.json` — Base64-encoded WASM bytes. - `scripts/` - `build.js` — Orchestrates the full build. - `buildPackage.js` — Runs `wasm-bindgen`, embeds WASM, writes JS/TS outputs. - `setup.js` — Prepublish bootstrap inside Nix. - `test/` — Vitest suites exercising bindings (bindings/common/js_api). - `typedoc.json`, `tsconfig.json` — Documentation and TS settings for the published surface. -- `README.md` — End‑user SDK guide with examples. +- `README.md` — End-user SDK guide with examples. ## Exports & API Surface -The package re‑exports the WASM‑bound API from the Rust crates. Representative items: +The package re-exports the WASM-bound API from the Rust crates. Representative items: - Functions - `parseYaml`, `getOrderHash`, `getTakeOrders3Calldata`, `keccak256`, `keccak256HexString`. -- High‑level classes (selected) - - `RaindexClient` — orderbook queries (orders, trades, vaults, quotes, transactions) across configured networks/subgraphs. Constructor is async (`await RaindexClient.new(...)`) and accepts optional `queryCallback` (for applying fetched records to the local DB), `wipeCallback` (for cleaning up stale data during full re-sync), and `statusCallback` (for reporting sync progress/errors to the caller) args for local DB sync when the YAML has `local-db-sync` sections. The sync scheduler starts automatically when configured and shuts down via Drop. +- High-level classes (selected) + - `RaindexClient` — raindex queries (orders, trades, vaults, quotes, transactions) across configured networks/subgraphs. Constructor is async (`await RaindexClient.new(...)`) and accepts optional `queryCallback` (for applying fetched records to the local DB), `wipeCallback` (for cleaning up stale data during full re-sync), and `statusCallback` (for reporting sync progress/errors to the caller) args for local DB sync when the YAML has `local-db-sync` sections. The sync scheduler starts automatically when configured and shuts down via Drop. - `RaindexOrder`, `RaindexVault`, `RaindexTrade`, `RaindexTransaction`, `RaindexVaultsList`, etc. - - `DotrainOrder`, `DotrainOrderGui`, `DotrainRegistry` — dotrain parsing, GUI orchestration, registry fetching (including `getOrderbookYaml()` for token queries), and deployment calldata. - - `OrderbookYaml` — typed access to networks, tokens (via `getTokens()`), orderbooks, subgraphs, deployers, accounts, metaboards. - - `Float` — arbitrary‑precision float utilities used across the API. + - `DotrainOrder`, `DotrainOrderGui`, `DotrainRegistry` — dotrain parsing, GUI orchestration, registry fetching (including `getRaindexYaml()` for token queries), and deployment calldata. + - `RaindexYaml` — typed access to networks, tokens (via `getTokens()`), raindexes, subgraphs, deployers, accounts, metaboards. + - `Float` — arbitrary-precision float utilities used across the API. - Errors & results - - Most methods return `WasmEncodedResult` with either `{ value }` or `{ error: { msg, readableMsg } }` for ergonomic, user‑readable error handling in JS. + - Most methods return `WasmEncodedResult` with either `{ value }` or `{ error: { msg, readableMsg } }` for ergonomic, user-readable error handling in JS. Notes on runtime behavior -- ESM builds use top‑level `await` to initialize the WASM module before exports are used. Ensure your bundler/runtime supports top‑level await. +- ESM builds use top-level `await` to initialize the WASM module before exports are used. Ensure your bundler/runtime supports top-level await. - No network fetches are performed to load the WASM bytes; they are embedded via JSON. ## How It Fits The Workspace -- Rust crates under `crates/*` implement the core logic. `rain_orderbook_js_api` compiles to WASM and re‑exports pieces of `common`, `settings`, `subgraph`, and others for a cohesive JS surface. +- Rust crates under `crates/*` implement the core logic. `raindex_js_api` compiles to WASM and re-exports pieces of `common`, `settings`, `subgraph`, and others for a cohesive JS surface. - This package is the NPM wrapper that compiles those crates for WASM, generates JS glue, and publishes the resulting SDK. -- Consumers use only `@rainlanguage/orderbook`; no direct interaction with the Rust build is required. +- Consumers use only `@rainlanguage/raindex`; no direct interaction with the Rust build is required. ## Testing & Documentation @@ -110,7 +110,7 @@ Notes on runtime behavior ## Publishing & Versioning -- The `prepublish` script ensures the package is fully rebuilt within a Nix shell and includes the embedded WASM. Tarballs contain `dist/` and thin top‑level entry points. +- The `prepublish` script ensures the package is fully rebuilt within a Nix shell and includes the embedded WASM. Tarballs contain `dist/` and thin top-level entry points. - Node.js >= 22 is required (see `package.json#engines`). A small `buffer` dependency is bundled for ESM environments that lack a native `Buffer`. @@ -118,7 +118,6 @@ Notes on runtime behavior - Always run build/test inside `nix develop` so `wasm-bindgen`, Rust toolchains, and targets are available. - If you add new WASM crates/exports in the workspace, extend the `packages` array in `scripts/build.js` and mirror any binding tweaks in `scripts/buildPackage.js`. -- If you see initialization issues in the browser, confirm your bundler supports top‑level await and that `orderbook_wbg.json` is included in the bundle. - -This document explains what the `packages/orderbook` directory is for, how the WASM artifacts are produced and embedded, what gets exported to consumers, and how it connects to the rest of the Rain Orderbook workspace. +- If you see initialization issues in the browser, confirm your bundler supports top-level await and that `raindex_wbg.json` is included in the bundle. +This document explains what the `packages/raindex` directory is for, how the WASM artifacts are produced and embedded, what gets exported to consumers, and how it connects to the rest of the Raindex workspace. diff --git a/packages/orderbook/README.md b/packages/raindex/README.md similarity index 94% rename from packages/orderbook/README.md rename to packages/raindex/README.md index c2f3a05c0c..a14593d661 100644 --- a/packages/orderbook/README.md +++ b/packages/raindex/README.md @@ -37,7 +37,7 @@ Before using this SDK, ensure you have: ## Installation ```bash -npm install @rainlanguage/orderbook +npm install @rainlanguage/raindex ``` ## Quick Start @@ -50,7 +50,7 @@ All of the code snippets below reuse the same fixed-limit dotrain/settings sourc ```ts const FIXED_LIMIT_SOURCE = ` -version: 5 +version: 6 networks: base: @@ -69,7 +69,7 @@ subgraphs: local-db-remotes: raindex: https://example.com/subgraph -orderbooks: +raindexes: base: network: base address: 0x52CEB8eBEf648744fFDDE89F7Bc9C3aC35944775 @@ -98,7 +98,7 @@ rainlangs: orders: fixed-limit: - orderbook: base + raindex: base inputs: - token: usdc vault-id: 1 @@ -109,7 +109,7 @@ orders: scenarios: base: - orderbook: base + raindex: base runs: 1 bindings: raindex-subparser: 0x22839F16281E67E5Fd395fAFd1571e820CbD46cB @@ -185,7 +185,7 @@ io: if( :; `; -const ORDERBOOK_SETTINGS = FIXED_LIMIT_SOURCE.split('---')[0]; +const RAINDEX_SETTINGS = FIXED_LIMIT_SOURCE.split('---')[0]; ``` ### 1. Create a raindex client @@ -193,9 +193,9 @@ const ORDERBOOK_SETTINGS = FIXED_LIMIT_SOURCE.split('---')[0]; This first snippet does three things: (1) load one or more settings YAML strings (these describe networks, accounts, and subgraph URLs), (2) feed those sources into `RaindexClient.new` so the WASM layer can parse and validate them, and (3) unwrap the resulting `WasmEncodedResult` so downstream samples can call the client with standard JS error handling expectations. The constructor is **async** — use `await`. ```ts -import { RaindexClient } from '@rainlanguage/orderbook'; +import { RaindexClient } from '@rainlanguage/raindex'; -const clientResult = await RaindexClient.new([ORDERBOOK_SETTINGS]); +const clientResult = await RaindexClient.new([RAINDEX_SETTINGS]); if (clientResult.error) throw new Error(clientResult.error.readableMsg); const client = clientResult.value; ``` @@ -206,7 +206,7 @@ When the YAML includes `local-db-sync` sections, pass optional callbacks to wire ```ts const clientResult = await RaindexClient.new( - [ORDERBOOK_SETTINGS], + [RAINDEX_SETTINGS], undefined, localDb.query.bind(localDb), localDb.wipeAndRecreate.bind(localDb), @@ -221,7 +221,7 @@ The client will automatically start the sync scheduler and route queries to the Here we scope the query by chain IDs and typical filters (owner, token, activity flag), ask the client to hydrate matching orders, and then walk the richer helpers on a single `RaindexOrder`—vault listings, trades, quotes, and detail lookups—to show how pagination + follow-up queries hang together. ```ts -import type { ChainIds, GetOrdersFilters } from '@rainlanguage/orderbook'; +import type { ChainIds, GetOrdersFilters } from '@rainlanguage/raindex'; const chainIds: ChainIds = [8453]; const filters: GetOrdersFilters = { @@ -259,7 +259,7 @@ Additional helpers worth wiring up: After you submit an `execute`/`addOrders` transaction you immediately have the transaction hash, but the subgraph still needs a few blocks to index the resulting order. Rather than re-querying every order and diffing manually, poll `client.getAddOrdersForTransaction` with that hash until it returns at least one `RaindexOrder`. ```ts -import type { RaindexClient } from '@rainlanguage/orderbook'; +import type { RaindexClient } from '@rainlanguage/raindex'; const POLL_INTERVAL_MS = 5_000; const MAX_ATTEMPTS = 12; @@ -317,7 +317,7 @@ if (removeCalldataResult.error) throw new Error(removeCalldataResult.error.reada Vault workflows usually require combining filters, inspecting the returned `RaindexVaultsList`, and then producing calldata or math-heavy amounts. This example chains those steps: fetch vaults, narrow the list to withdrawable entries, pull history, parse human inputs with `Float`, and finally build deposit/withdraw/approval payloads while checking allowances. ```ts -import { Float, type GetVaultsFilters } from '@rainlanguage/orderbook'; +import { Float, type GetVaultsFilters } from '@rainlanguage/raindex'; const vaultFilters: GetVaultsFilters = { owners: ['0x1234...'], @@ -376,7 +376,7 @@ if (balanceChangesResult.error) throw new Error(balanceChangesResult.error.reada Once you have hydrated orders, you typically need deterministic hashes plus calldata builders. The snippet below hashes an order struct, generates take-orders calldata, asks an order for its removal calldata, and fetches quotes—mirroring the usual "inspect -> prepare transaction -> submit" flow. ```ts -import { getOrderHash, getTakeOrders3Calldata } from '@rainlanguage/orderbook'; +import { getOrderHash, getTakeOrders3Calldata } from '@rainlanguage/raindex'; const orderHashResult = getOrderHash(orderV4Struct); if (orderHashResult.error) throw new Error(orderHashResult.error.readableMsg); @@ -403,7 +403,7 @@ The SDK provides two approaches for executing `takeOrders4` transactions: auto-d Use `client.getTakeOrdersCalldata()` to discover and aggregate liquidity across all active orders for a given token pair: ```ts -import type { TakeOrdersRequest } from '@rainlanguage/orderbook'; +import type { TakeOrdersRequest } from '@rainlanguage/raindex'; const request: TakeOrdersRequest = { chainId: 137, @@ -482,7 +482,7 @@ const { Use directional token filters to find orders matching specific trading pairs: ```ts -import type { GetOrdersFilters, GetOrdersTokenFilter } from '@rainlanguage/orderbook'; +import type { GetOrdersFilters, GetOrdersTokenFilter } from '@rainlanguage/raindex'; const tokenFilter: GetOrdersTokenFilter = { inputs: ['0xUSDC...'], // Orders that accept USDC as input @@ -504,7 +504,7 @@ const ordersResult = await client.getOrders([137], filters, 1); If you maintain a hosted registry, instantiate the helper, inspect what it exposes, and pull down any dotrain/GUI definitions you need: ```ts -import { DotrainRegistry } from '@rainlanguage/orderbook'; +import { DotrainRegistry } from '@rainlanguage/raindex'; const registryResult = await DotrainRegistry.new('https://example.com/registry.txt'); if (registryResult.error) throw new Error(registryResult.error.readableMsg); @@ -532,21 +532,21 @@ The SDK merges the shared settings YAML with each order's `.rain` content before #### Access tokens from registry settings -Use `getOrderbookYaml()` to access the shared settings as an `OrderbookYaml` instance, then query tokens, networks, or orderbooks: +Use `getRaindexYaml()` to access the shared settings as an `RaindexYaml` instance, then query tokens, networks, or raindexes: ```ts -const orderbookYamlResult = registry.getOrderbookYaml(); -if (orderbookYamlResult.error) throw new Error(orderbookYamlResult.error.readableMsg); -const orderbookYaml = orderbookYamlResult.value; +const raindexYamlResult = registry.getRaindexYaml(); +if (raindexYamlResult.error) throw new Error(raindexYamlResult.error.readableMsg); +const raindexYaml = raindexYamlResult.value; -const tokensResult = await orderbookYaml.getTokens(); +const tokensResult = await raindexYaml.getTokens(); if (tokensResult.error) throw new Error(tokensResult.error.readableMsg); const tokens = tokensResult.value; // TokenInfo[] with chain_id, address, decimals, symbol, name ``` #### Get a RaindexClient from registry settings -Use `getRaindexClient()` to create a `RaindexClient` directly from the registry's shared settings, without manually bridging through `OrderbookYaml`: +Use `getRaindexClient()` to create a `RaindexClient` directly from the registry's shared settings, without manually bridging through `RaindexYaml`: ```ts const clientResult = registry.getRaindexClient(); @@ -564,7 +564,7 @@ Any dotrain file that includes a `gui:` block plus the usual settings YAML is en With that single source string (read from disk or built dynamically) you can drive the full GUI workflow: ```ts -import { DotrainOrderGui } from '@rainlanguage/orderbook'; +import { DotrainOrderGui } from '@rainlanguage/raindex'; const dotrainWithGui = FIXED_LIMIT_SOURCE; const SAMPLE_YAML = ` @@ -573,7 +573,7 @@ rainlangs: rainlang1: network: mainnet address: 0x... -orderbooks: +raindexes: orderbook1: address: 0x... network: mainnet @@ -661,7 +661,7 @@ A typical deployment flow is: 4. Poll `client.getAddOrdersForTransaction` (the helper shown earlier) with the deployment hash until the subgraph surfaces your `RaindexOrder` ```ts -import type { RaindexClient } from '@rainlanguage/orderbook'; +import type { RaindexClient } from '@rainlanguage/raindex'; const deploymentArgsResult = await gui.getDeploymentTransactionArgs(owner); if (deploymentArgsResult.error) throw new Error(deploymentArgsResult.error.readableMsg); @@ -686,7 +686,7 @@ const raindexOrder = await waitForOrderFromTx(client as RaindexClient, { After you have a local GUI-aware dotrain source, you can also fetch equivalent sources from a registry and run the same flow: ```ts -import { DotrainRegistry } from '@rainlanguage/orderbook'; +import { DotrainRegistry } from '@rainlanguage/raindex'; const registryResult = await DotrainRegistry.new('https://example.com/registry.txt'); if (registryResult.error) throw new Error(registryResult.error.readableMsg); @@ -705,9 +705,9 @@ const guiFromRegistry = guiSourceResult.value; If you just need Rainlang composition (no GUI state), read the dotrain text plus shared settings yourself, instantiate a `DotrainOrder`, and then ask it to compose scenario/deployment/post-task Rainlang. The example below reuses `FIXED_LIMIT_SOURCE`, but you can replace it with the contents of any `.rain` file. ```ts -import { DotrainOrder } from '@rainlanguage/orderbook'; +import { DotrainOrder } from '@rainlanguage/raindex'; -const dotrainResult = await DotrainOrder.create(FIXED_LIMIT_SOURCE, [ORDERBOOK_SETTINGS]); +const dotrainResult = await DotrainOrder.create(FIXED_LIMIT_SOURCE, [RAINDEX_SETTINGS]); if (dotrainResult.error) throw new Error(dotrainResult.error.readableMsg); const dotrain = dotrainResult.value; @@ -725,7 +725,7 @@ if (!postTaskResult.error) console.log(postTaskResult.value); - `getOrderHash`, `keccak256`, `keccak256HexString` – deterministic hashing helpers for Rain orders or arbitrary payloads. - `Float` – arbitrary-precision arithmetic with parsing, formatting, comparisons, math ops, fixed-decimal conversions, and helpers like `Float.zero()` or `.formatWithRange(...)`. -- `OrderbookYaml.getTokens()` – async method returning all tokens from YAML configuration with `chain_id`, `address`, `decimals`, `symbol`, and `name`. Automatically fetches remote tokens from `using-tokens-from` URLs. +- `RaindexYaml.getTokens()` – async method returning all tokens from YAML configuration with `chain_id`, `address`, `decimals`, `symbol`, and `name`. Automatically fetches remote tokens from `using-tokens-from` URLs. - `RaindexClient.getAllAccounts()` / `getAllVaultTokens()` – introspect accounts and ERC20 metadata defined in your YAML or discovered via subgraphs. - Local DB sync – pass `queryCallback`, `wipeCallback`, and `statusCallback` to `RaindexClient.new()` when YAML has `local-db-sync` sections to enable an offline-capable persistent cache. The scheduler starts automatically and queries route to the local DB once the first sync cycle completes. - `RaindexVaultsList.getWithdrawCalldata()` – multicall builder that withdraws every vault with a balance. diff --git a/packages/orderbook/package.json b/packages/raindex/package.json similarity index 75% rename from packages/orderbook/package.json rename to packages/raindex/package.json index 74002175d5..8c930504d9 100644 --- a/packages/orderbook/package.json +++ b/packages/raindex/package.json @@ -1,18 +1,18 @@ { - "name": "@rainlanguage/orderbook", - "description": "Provides RainLanguage Orderbook rust crates' functionalities in typescript through wasm bindgen", + "name": "@rainlanguage/raindex", + "description": "Provides RainLanguage Raindex rust crates' functionalities in typescript through wasm bindgen", "version": "0.0.1-alpha.229", "license": "LicenseRef-DCL-1.0", "author": "Rain Open Source Software Ltd", "repository": { "type": "git", - "url": "https://github.com/rainlanguage/rain.orderbook.git" + "url": "https://github.com/rainlanguage/raindex.git" }, "keywords": [], "bugs": { - "url": "https://github.com/rainlanguage/rain.orderbook/issues" + "url": "https://github.com/rainlanguage/raindex/issues" }, - "homepage": "https://github.com/rainlanguage/rain.orderbook#readme", + "homepage": "https://github.com/rainlanguage/raindex#readme", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "browser": { @@ -32,7 +32,7 @@ "scripts": { "prepublish": "node ./scripts/setup", "build": "npm run rm-dist && npm run rm-temp && npm run build-wasm && node ./scripts/build && npm run check", - "build-wasm": "cargo build --target wasm32-unknown-unknown --lib --profile release-wasm -p rain_orderbook_js_api", + "build-wasm": "cargo build --target wasm32-unknown-unknown --lib --profile release-wasm -p raindex_js_api", "rm-dist": "rimraf ./dist", "rm-temp": "rimraf ./temp", "test": "npm run check && vitest run --dir test", diff --git a/packages/orderbook/scripts/build.js b/packages/raindex/scripts/build.js similarity index 100% rename from packages/orderbook/scripts/build.js rename to packages/raindex/scripts/build.js diff --git a/packages/orderbook/scripts/buildPackage.js b/packages/raindex/scripts/buildPackage.js similarity index 95% rename from packages/orderbook/scripts/buildPackage.js rename to packages/raindex/scripts/buildPackage.js index 1e96dd55ed..7ba3821985 100644 --- a/packages/orderbook/scripts/buildPackage.js +++ b/packages/raindex/scripts/buildPackage.js @@ -1,7 +1,7 @@ const fs = require('fs'); const { execSync } = require('child_process'); -const packagePrefix = 'rain_orderbook_'; +const packagePrefix = 'raindex_'; // after using opt-level on wasm build, WasmEncodedResult and WasmEncodedError // are duplicated in the dts so we need to dedupe them @@ -26,7 +26,7 @@ module.exports.buildCjs = function (pkg) { // in js modules in order to avoid using fetch or fs operations const wasmCjsBytes = fs.readFileSync(`./temp/node/${pkg}/${pkg}_bg.wasm`); fs.writeFileSync( - "./dist/cjs/orderbook_wbg.json", + "./dist/cjs/raindex_wbg.json", JSON.stringify({ wasm: Buffer.from(wasmCjsBytes, 'binary').toString('base64') }) @@ -62,7 +62,7 @@ module.exports.buildCjs = function (pkg) { const bytes = require('fs').readFileSync(path);`, ` const { Buffer } = require('buffer'); -const wasmB64 = require('./orderbook_wbg.json'); +const wasmB64 = require('./raindex_wbg.json'); const bytes = Buffer.from(wasmB64.wasm, 'base64');` ); cjs = cjs.replace('const { TextEncoder, TextDecoder } = require(`util`);', ''); @@ -83,7 +83,7 @@ module.exports.buildEsm = function (pkg) { // in js modules in order to avoid using fetch or fs operations const wasmEsmBytes = fs.readFileSync(`./temp/web/${pkg}/${pkg}_bg.wasm`); fs.writeFileSync( - `./dist/esm/orderbook_wbg.json`, + `./dist/esm/raindex_wbg.json`, JSON.stringify({ wasm: Buffer.from(wasmEsmBytes, 'binary').toString('base64') }) @@ -121,7 +121,7 @@ module.exports.buildEsm = function (pkg) { esm = esm.replace(`export { initSync }; export default __wbg_init;`, `import { Buffer } from 'buffer'; -import wasmB64 from './orderbook_wbg.json'; +import wasmB64 from './raindex_wbg.json'; const bytes = Buffer.from(wasmB64.wasm, 'base64');\n initSync(bytes);` ); diff --git a/packages/orderbook/scripts/setup.js b/packages/raindex/scripts/setup.js similarity index 100% rename from packages/orderbook/scripts/setup.js rename to packages/raindex/scripts/setup.js diff --git a/packages/orderbook/scripts/sizeCheck.js b/packages/raindex/scripts/sizeCheck.js similarity index 100% rename from packages/orderbook/scripts/sizeCheck.js rename to packages/raindex/scripts/sizeCheck.js diff --git a/packages/orderbook/test/bindings/test.test.ts b/packages/raindex/test/bindings/test.test.ts similarity index 100% rename from packages/orderbook/test/bindings/test.test.ts rename to packages/raindex/test/bindings/test.test.ts diff --git a/packages/orderbook/test/common/test.test.ts b/packages/raindex/test/common/test.test.ts similarity index 100% rename from packages/orderbook/test/common/test.test.ts rename to packages/raindex/test/common/test.test.ts diff --git a/packages/orderbook/test/js_api/dotrainRainlang.test.ts b/packages/raindex/test/js_api/dotrainRainlang.test.ts similarity index 100% rename from packages/orderbook/test/js_api/dotrainRainlang.test.ts rename to packages/raindex/test/js_api/dotrainRainlang.test.ts diff --git a/packages/orderbook/test/js_api/gui.test.ts b/packages/raindex/test/js_api/gui.test.ts similarity index 100% rename from packages/orderbook/test/js_api/gui.test.ts rename to packages/raindex/test/js_api/gui.test.ts diff --git a/packages/orderbook/test/js_api/raindexClient.test.ts b/packages/raindex/test/js_api/raindexClient.test.ts similarity index 100% rename from packages/orderbook/test/js_api/raindexClient.test.ts rename to packages/raindex/test/js_api/raindexClient.test.ts diff --git a/packages/orderbook/test/js_api/orderbookYaml.test.ts b/packages/raindex/test/js_api/raindexYaml.test.ts similarity index 82% rename from packages/orderbook/test/js_api/orderbookYaml.test.ts rename to packages/raindex/test/js_api/raindexYaml.test.ts index 7c904550dd..e16060a092 100644 --- a/packages/orderbook/test/js_api/orderbookYaml.test.ts +++ b/packages/raindex/test/js_api/raindexYaml.test.ts @@ -1,11 +1,11 @@ import assert from 'assert'; import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest'; -import { OrderbookYaml, OrderbookCfg, WasmEncodedResult } from '../../dist/cjs'; +import { RaindexYaml, RaindexCfg, WasmEncodedResult } from '../../dist/cjs'; import { getLocal } from 'mockttp'; -const SPEC_VERSION = OrderbookYaml.getCurrentSpecVersion().value; +const SPEC_VERSION = RaindexYaml.getCurrentSpecVersion().value; -const YAML_WITHOUT_ORDERBOOK = ` +const YAML_WITHOUT_RAINDEX = ` version: ${SPEC_VERSION} networks: @@ -28,10 +28,10 @@ rainlangs: address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba local-db-remotes: - some-orderbook: http://example.com + some-raindex: http://example.com local-db-sync: - some-orderbook: + some-raindex: batch-size: 2000 max-concurrent-batches: 10 retry-attempts: 3 @@ -41,8 +41,8 @@ local-db-sync: bootstrap-block-threshold: 1000 sync-interval-ms: 5000 -orderbooks: - some-orderbook: +raindexes: + some-raindex: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: some-network subgraph: some-sg @@ -81,7 +81,7 @@ orders: - token: token2 vault-id: 1 rainlang: some-rainlang - orderbook: some-orderbook + raindex: some-raindex deployments: some-deployment: @@ -104,14 +104,14 @@ const extractWasmEncodedData = (result: WasmEncodedResult, errorMessage?: return result.value; }; -const buildYaml = (source: string, validate?: boolean): OrderbookYaml => { - const result = OrderbookYaml.new([source], validate); - return extractWasmEncodedData(result); +const buildYaml = (source: string, validate?: boolean): RaindexYaml => { + const result = RaindexYaml.new([source], validate); + return extractWasmEncodedData(result); }; -describe('Rain Orderbook JS API Package Bindgen Tests - Settings', async function () { +describe('Raindex JS API Package Bindgen Tests - Settings', async function () { it('should return current spec version', async function () { - const result = OrderbookYaml.getCurrentSpecVersion(); + const result = RaindexYaml.getCurrentSpecVersion(); if (result.error) assert.fail(result.error.msg); const version = result.value; assert.ok(version); @@ -120,35 +120,35 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Settings', async functio }); it('should create a new settings object', async function () { - const orderbookYaml = buildYaml(YAML_WITHOUT_ORDERBOOK); - assert.ok(orderbookYaml); + const raindexYaml = buildYaml(YAML_WITHOUT_RAINDEX); + assert.ok(raindexYaml); }); - describe('orderbook tests', async function () { - it('should get the orderbook', async function () { - const orderbookYaml = buildYaml(YAML_WITHOUT_ORDERBOOK); + describe('raindex tests', async function () { + it('should get the raindex', async function () { + const raindexYaml = buildYaml(YAML_WITHOUT_RAINDEX); - const orderbook = extractWasmEncodedData( - orderbookYaml.getOrderbookByAddress('0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6') + const raindexCfg = extractWasmEncodedData( + raindexYaml.getRaindexByAddress('0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6') ); - assert.equal(orderbook.address, '0xc95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a6'); - assert.equal(orderbook.network.chainId, 123); - assert.equal(orderbook.subgraph.url, 'https://www.some-sg.com/'); + assert.equal(raindexCfg.address, '0xc95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a6'); + assert.equal(raindexCfg.network.chainId, 123); + assert.equal(raindexCfg.subgraph.url, 'https://www.some-sg.com/'); - let result = orderbookYaml.getOrderbookByAddress('invalid-address'); + let result = raindexYaml.getRaindexByAddress('invalid-address'); if (!result.error) expect.fail('Expected error'); expect(result.error.msg).toBe('Invalid address: odd number of digits'); expect(result.error.readableMsg).toBe( 'The provided address is invalid. Please ensure the address is in the correct hexadecimal format. Error: "odd number of digits"' ); - result = orderbookYaml.getOrderbookByAddress('0x0000000000000000000000000000000000000000'); + result = raindexYaml.getRaindexByAddress('0x0000000000000000000000000000000000000000'); if (!result.error) expect.fail('Expected error'); expect(result.error.msg).toBe( - 'Orderbook yaml error: orderbook with address: 0x0000000000000000000000000000000000000000 not found' + 'Raindex yaml error: raindex with address: 0x0000000000000000000000000000000000000000 not found' ); expect(result.error.readableMsg).toBe( - 'There was an error processing the YAML configuration. Please check the YAML file for any issues. Error: "orderbook with address: 0x0000000000000000000000000000000000000000 not found"' + 'There was an error processing the YAML configuration. Please check the YAML file for any issues. Error: "raindex with address: 0x0000000000000000000000000000000000000000 not found"' ); }); }); @@ -164,8 +164,8 @@ networks: network-id: 123 currency: ETH -orderbooks: - some-orderbook: +raindexes: + some-raindex: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: nonexistent-network subgraph: nonexistent-subgraph @@ -173,36 +173,36 @@ orderbooks: `; it('should succeed with valid YAML and validation enabled', async function () { - const orderbookYaml = buildYaml(YAML_WITHOUT_ORDERBOOK, true); - assert.ok(orderbookYaml); + const raindexYaml = buildYaml(YAML_WITHOUT_RAINDEX, true); + assert.ok(raindexYaml); }); it('should succeed with valid YAML and validation disabled', async function () { - const orderbookYaml = buildYaml(YAML_WITHOUT_ORDERBOOK, false); - assert.ok(orderbookYaml); + const raindexYaml = buildYaml(YAML_WITHOUT_RAINDEX, false); + assert.ok(raindexYaml); }); it('should succeed with valid YAML and default validation', async function () { - const orderbookYaml = buildYaml(YAML_WITHOUT_ORDERBOOK); - assert.ok(orderbookYaml); + const raindexYaml = buildYaml(YAML_WITHOUT_RAINDEX); + assert.ok(raindexYaml); }); it('should fail with invalid YAML and validation enabled', async function () { - const result = OrderbookYaml.new([INVALID_YAML], true); + const result = RaindexYaml.new([INVALID_YAML], true); if (!result.error) expect.fail('Expected validation error with invalid YAML'); - expect(result.error.msg).toContain('Orderbook yaml error'); + expect(result.error.msg).toContain('Raindex yaml error'); expect(result.error.readableMsg).toContain( 'There was an error processing the YAML configuration' ); }); it('should succeed construction but fail usage with invalid YAML when validation is disabled', async function () { - const orderbookYaml = buildYaml(INVALID_YAML, false); - const orderbookResult = orderbookYaml.getOrderbookByAddress( + const raindexYaml = buildYaml(INVALID_YAML, false); + const raindexResult = raindexYaml.getRaindexByAddress( '0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6' ); - if (!orderbookResult.error) expect.fail('Expected error when using invalid YAML'); - expect(orderbookResult.error.msg).toContain('Orderbook yaml error'); + if (!raindexResult.error) expect.fail('Expected error when using invalid YAML'); + expect(raindexResult.error.msg).toContain('Raindex yaml error'); }); }); @@ -222,8 +222,8 @@ orderbooks: }); it('should return local tokens with chainId', async function () { - const orderbookYaml = buildYaml(YAML_WITHOUT_ORDERBOOK); - const tokensResult = await orderbookYaml.getTokens(); + const raindexYaml = buildYaml(YAML_WITHOUT_RAINDEX); + const tokensResult = await raindexYaml.getTokens(); const tokens = extractWasmEncodedData(tokensResult); assert.strictEqual(tokens.length, 2); @@ -263,8 +263,8 @@ tokens: // No mock set up - RPC call will fail // This tests that when token fields are missing, the code attempts to fetch from RPC // (rather than immediately returning a "missing field" error) - const orderbookYaml = buildYaml(YAML_MISSING_FIELDS); - const tokensResult = await orderbookYaml.getTokens(); + const raindexYaml = buildYaml(YAML_MISSING_FIELDS); + const tokensResult = await raindexYaml.getTokens(); assert.ok(tokensResult.error, 'Expected error when RPC fetch fails'); expect(tokensResult.error.readableMsg).toContain('Failed to fetch token information'); @@ -296,8 +296,8 @@ tokens: label: USD Coin PoS symbol: USDC `; - const orderbookYaml = buildYaml(MULTI_NETWORK_YAML); - const tokensResult = await orderbookYaml.getTokens(); + const raindexYaml = buildYaml(MULTI_NETWORK_YAML); + const tokensResult = await raindexYaml.getTokens(); const tokens = extractWasmEncodedData(tokensResult); assert.strictEqual(tokens.length, 2); @@ -366,8 +366,8 @@ networks: using-tokens-from: - http://localhost:8232/tokens.json `; - const orderbookYaml = buildYaml(yaml); - const tokensResult = await orderbookYaml.getTokens(); + const raindexYaml = buildYaml(yaml); + const tokensResult = await raindexYaml.getTokens(); const tokens = extractWasmEncodedData(tokensResult); assert.strictEqual(tokens.length, 2); @@ -421,8 +421,8 @@ tokens: label: Wrapped Ether symbol: WETH `; - const orderbookYaml = buildYaml(yaml); - const tokensResult = await orderbookYaml.getTokens(); + const raindexYaml = buildYaml(yaml); + const tokensResult = await raindexYaml.getTokens(); const tokens = extractWasmEncodedData(tokensResult); assert.strictEqual(tokens.length, 2); @@ -484,8 +484,8 @@ using-tokens-from: - http://localhost:8232/tokens1.json - http://localhost:8232/tokens2.json `; - const orderbookYaml = buildYaml(yaml); - const tokensResult = await orderbookYaml.getTokens(); + const raindexYaml = buildYaml(yaml); + const tokensResult = await raindexYaml.getTokens(); const tokens = extractWasmEncodedData(tokensResult); assert.strictEqual(tokens.length, 2); @@ -540,8 +540,8 @@ networks: using-tokens-from: - http://localhost:8232/tokens-ext.json `; - const orderbookYaml = buildYaml(yaml); - const tokensResult = await orderbookYaml.getTokens(); + const raindexYaml = buildYaml(yaml); + const tokensResult = await raindexYaml.getTokens(); const tokens = extractWasmEncodedData(tokensResult); const usdc = tokens.find((t: { symbol: string }) => t.symbol === 'USDC'); @@ -596,8 +596,8 @@ networks: using-tokens-from: - http://localhost:8232/tokens.json `; - const orderbookYaml = buildYaml(yaml); - const tokensResult = await orderbookYaml.getTokens(); + const raindexYaml = buildYaml(yaml); + const tokensResult = await raindexYaml.getTokens(); const tokens = extractWasmEncodedData(tokensResult); assert.strictEqual(tokens.length, 2); diff --git a/packages/orderbook/test/tsconfig.json b/packages/raindex/test/tsconfig.json similarity index 100% rename from packages/orderbook/test/tsconfig.json rename to packages/raindex/test/tsconfig.json diff --git a/packages/orderbook/tsconfig.json b/packages/raindex/tsconfig.json similarity index 100% rename from packages/orderbook/tsconfig.json rename to packages/raindex/tsconfig.json diff --git a/packages/orderbook/typedoc.json b/packages/raindex/typedoc.json similarity index 100% rename from packages/orderbook/typedoc.json rename to packages/raindex/typedoc.json diff --git a/packages/ui-components/package.json b/packages/ui-components/package.json index 844ee6a995..96f02d6b39 100644 --- a/packages/ui-components/package.json +++ b/packages/ui-components/package.json @@ -6,7 +6,7 @@ "author": "Rain Open Source Software Ltd", "repository": { "type": "git", - "url": "https://github.com/rainlanguage/rain.orderbook.git" + "url": "https://github.com/rainlanguage/raindex.git" }, "main": "dist/index.js", "module": "dist/index.js", @@ -57,7 +57,7 @@ "@fontsource/dm-sans": "5.1.0", "@imask/svelte": "7.6.1", "@observablehq/plot": "0.6.16", - "@rainlanguage/orderbook": "0.0.1-alpha.229", + "@rainlanguage/raindex": "0.0.1-alpha.229", "@reown/appkit": "1.6.4", "@reown/appkit-adapter-wagmi": "1.6.4", "@sentry/sveltekit": "7.120.0", From 6400ec9b88354df42696a848404f45126e74062b Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Fri, 27 Mar 2026 09:42:28 +0400 Subject: [PATCH 08/69] Rename OrderBook to Raindex in UI components and packages Rename Svelte components (DropdownOrderbooksFilter -> DropdownRaindexesFilter, ListViewOrderbookFilters -> ListViewRaindexFilters), update imports, types, and variable names. Update ui-components and raindex package dependencies and URLs. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../DropdownOrderbooksFilter.test.ts | 180 +++++++++--------- ...s.svelte => ListViewRaindexFilters.svelte} | 14 +- ....svelte => DropdownRaindexesFilter.svelte} | 112 +++++------ 3 files changed, 153 insertions(+), 153 deletions(-) rename packages/ui-components/src/lib/components/{ListViewOrderbookFilters.svelte => ListViewRaindexFilters.svelte} (89%) rename packages/ui-components/src/lib/components/dropdown/{DropdownOrderbooksFilter.svelte => DropdownRaindexesFilter.svelte} (53%) diff --git a/packages/ui-components/src/__tests__/DropdownOrderbooksFilter.test.ts b/packages/ui-components/src/__tests__/DropdownOrderbooksFilter.test.ts index ea8c0c0238..9ea032f32c 100644 --- a/packages/ui-components/src/__tests__/DropdownOrderbooksFilter.test.ts +++ b/packages/ui-components/src/__tests__/DropdownOrderbooksFilter.test.ts @@ -1,21 +1,21 @@ import { render, fireEvent, screen, waitFor } from '@testing-library/svelte'; import { get, writable } from 'svelte/store'; -import DropdownOrderbooksFilter from '../lib/components/dropdown/DropdownOrderbooksFilter.svelte'; +import DropdownRaindexesFilter from '../lib/components/dropdown/DropdownRaindexesFilter.svelte'; import { expect, test, describe, beforeEach, vi, type Mock } from 'vitest'; -import type { Address } from '@rainlanguage/orderbook'; +import type { Address } from '@rainlanguage/raindex'; import { useRaindexClient } from '$lib/hooks/useRaindexClient'; vi.mock('$lib/hooks/useRaindexClient', () => ({ useRaindexClient: vi.fn() })); -const mockOrderbooksData = new Map([ +const mockRaindexsData = new Map([ [ 'orderbook1', { key: 'orderbook1', address: '0x1234567890123456789012345678901234567890', - label: 'Orderbook One', + label: 'Raindex One', network: { chainId: 1 } } ], @@ -24,7 +24,7 @@ const mockOrderbooksData = new Map([ { key: 'orderbook2', address: '0x2345678901234567890123456789012345678901', - label: 'Orderbook Two', + label: 'Raindex Two', network: { chainId: 1 } } ], @@ -39,15 +39,15 @@ const mockOrderbooksData = new Map([ ] ]); -describe('DropdownOrderbooksFilter', () => { - let activeOrderbookAddresses: ReturnType>; +describe('DropdownRaindexesFilter', () => { + let activeRaindexAddresses: ReturnType>; beforeEach(() => { - activeOrderbookAddresses = writable([]); + activeRaindexAddresses = writable([]); (useRaindexClient as Mock).mockReturnValue({ - getAllOrderbooks: vi.fn(() => ({ - value: mockOrderbooksData, + getAllRaindexs: vi.fn(() => ({ + value: mockRaindexsData, error: undefined })) }); @@ -56,16 +56,16 @@ describe('DropdownOrderbooksFilter', () => { describe('Empty state', () => { test('displays empty message when no orderbooks available', async () => { (useRaindexClient as Mock).mockReturnValue({ - getAllOrderbooks: vi.fn(() => ({ + getAllRaindexs: vi.fn(() => ({ value: new Map(), error: undefined })) }); - render(DropdownOrderbooksFilter, { + render(DropdownRaindexesFilter, { props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], + activeRaindexAddresses, + selectedRaindexAddresses: [], selectedChainIds: [] } }); @@ -79,18 +79,18 @@ describe('DropdownOrderbooksFilter', () => { test('displays custom empty message', async () => { (useRaindexClient as Mock).mockReturnValue({ - getAllOrderbooks: vi.fn(() => ({ + getAllRaindexs: vi.fn(() => ({ value: new Map(), error: undefined })) }); - const customEmptyMessage = 'Orderbook list is empty'; + const customEmptyMessage = 'Raindex list is empty'; - render(DropdownOrderbooksFilter, { + render(DropdownRaindexesFilter, { props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], + activeRaindexAddresses, + selectedRaindexAddresses: [], selectedChainIds: [], emptyMessage: customEmptyMessage } @@ -105,19 +105,19 @@ describe('DropdownOrderbooksFilter', () => { }); describe('Error state', () => { - test('displays error message when getAllOrderbooks returns error', async () => { + test('displays error message when getAllRaindexs returns error', async () => { const errorMessage = 'Failed to load orderbooks'; (useRaindexClient as Mock).mockReturnValue({ - getAllOrderbooks: vi.fn(() => ({ + getAllRaindexs: vi.fn(() => ({ value: undefined, error: { readableMsg: errorMessage } })) }); - render(DropdownOrderbooksFilter, { + render(DropdownRaindexesFilter, { props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], + activeRaindexAddresses, + selectedRaindexAddresses: [], selectedChainIds: [] } }); @@ -134,10 +134,10 @@ describe('DropdownOrderbooksFilter', () => { describe('Selected orderbooks display', () => { test('displays "Select orderbooks" when no orderbooks are selected', () => { - render(DropdownOrderbooksFilter, { + render(DropdownRaindexesFilter, { props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], + activeRaindexAddresses, + selectedRaindexAddresses: [], selectedChainIds: [] } }); @@ -146,14 +146,14 @@ describe('DropdownOrderbooksFilter', () => { }); test('displays "All orderbooks" when all orderbooks are selected', () => { - const allAddresses = Array.from(mockOrderbooksData.values()).map( + const allAddresses = Array.from(mockRaindexsData.values()).map( (ob) => ob.address ) as Address[]; - render(DropdownOrderbooksFilter, { + render(DropdownRaindexesFilter, { props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: allAddresses, + activeRaindexAddresses, + selectedRaindexAddresses: allAddresses, selectedChainIds: [] } }); @@ -162,15 +162,15 @@ describe('DropdownOrderbooksFilter', () => { }); test('displays custom all label when all orderbooks are selected', () => { - const allAddresses = Array.from(mockOrderbooksData.values()).map( + const allAddresses = Array.from(mockRaindexsData.values()).map( (ob) => ob.address ) as Address[]; const customAllLabel = 'Everything selected'; - render(DropdownOrderbooksFilter, { + render(DropdownRaindexesFilter, { props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: allAddresses, + activeRaindexAddresses, + selectedRaindexAddresses: allAddresses, selectedChainIds: [], allLabel: customAllLabel } @@ -180,12 +180,12 @@ describe('DropdownOrderbooksFilter', () => { }); test('displays count when one orderbook is selected', () => { - const selectedAddress = Array.from(mockOrderbooksData.values())[0].address as Address; + const selectedAddress = Array.from(mockRaindexsData.values())[0].address as Address; - render(DropdownOrderbooksFilter, { + render(DropdownRaindexesFilter, { props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [selectedAddress], + activeRaindexAddresses, + selectedRaindexAddresses: [selectedAddress], selectedChainIds: [] } }); @@ -194,14 +194,14 @@ describe('DropdownOrderbooksFilter', () => { }); test('displays plural count when multiple orderbooks are selected', () => { - const selectedAddresses = Array.from(mockOrderbooksData.values()) + const selectedAddresses = Array.from(mockRaindexsData.values()) .slice(0, 2) .map((ob) => ob.address) as Address[]; - render(DropdownOrderbooksFilter, { + render(DropdownRaindexesFilter, { props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: selectedAddresses, + activeRaindexAddresses, + selectedRaindexAddresses: selectedAddresses, selectedChainIds: [] } }); @@ -210,10 +210,10 @@ describe('DropdownOrderbooksFilter', () => { }); test('updates selected orderbooks when checkbox is clicked', async () => { - render(DropdownOrderbooksFilter, { + render(DropdownRaindexesFilter, { props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], + activeRaindexAddresses, + selectedRaindexAddresses: [], selectedChainIds: [] } }); @@ -224,18 +224,18 @@ describe('DropdownOrderbooksFilter', () => { await fireEvent.click(checkboxes[0]); await waitFor(() => { - const selected = get(activeOrderbookAddresses); + const selected = get(activeRaindexAddresses); expect(selected.length).toBe(1); }); }); test('shows selected orderbooks as checked', async () => { - const selectedAddress = Array.from(mockOrderbooksData.values())[0].address as Address; + const selectedAddress = Array.from(mockRaindexsData.values())[0].address as Address; - render(DropdownOrderbooksFilter, { + render(DropdownRaindexesFilter, { props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [selectedAddress], + activeRaindexAddresses, + selectedRaindexAddresses: [selectedAddress], selectedChainIds: [] } }); @@ -250,10 +250,10 @@ describe('DropdownOrderbooksFilter', () => { describe('Chain filtering', () => { test('shows all orderbooks when selectedChainIds is empty', async () => { - render(DropdownOrderbooksFilter, { + render(DropdownRaindexesFilter, { props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], + activeRaindexAddresses, + selectedRaindexAddresses: [], selectedChainIds: [] } }); @@ -267,10 +267,10 @@ describe('DropdownOrderbooksFilter', () => { }); test('filters orderbooks by selected chain ID', async () => { - render(DropdownOrderbooksFilter, { + render(DropdownRaindexesFilter, { props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], + activeRaindexAddresses, + selectedRaindexAddresses: [], selectedChainIds: [1] } }); @@ -284,10 +284,10 @@ describe('DropdownOrderbooksFilter', () => { }); test('shows orderbooks from multiple selected chains', async () => { - render(DropdownOrderbooksFilter, { + render(DropdownRaindexesFilter, { props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], + activeRaindexAddresses, + selectedRaindexAddresses: [], selectedChainIds: [1, 137] } }); @@ -303,10 +303,10 @@ describe('DropdownOrderbooksFilter', () => { describe('Display format', () => { test('displays label with truncated address when label exists', async () => { - render(DropdownOrderbooksFilter, { + render(DropdownRaindexesFilter, { props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], + activeRaindexAddresses, + selectedRaindexAddresses: [], selectedChainIds: [] } }); @@ -314,16 +314,16 @@ describe('DropdownOrderbooksFilter', () => { await fireEvent.click(screen.getByTestId('dropdown-orderbooks-filter-button')); await waitFor(() => { - expect(screen.getByText(/Orderbook One/)).toBeInTheDocument(); + expect(screen.getByText(/Raindex One/)).toBeInTheDocument(); expect(screen.getByText(/0x1234\.\.\.7890/)).toBeInTheDocument(); }); }); test('displays only truncated address when no label', async () => { - render(DropdownOrderbooksFilter, { + render(DropdownRaindexesFilter, { props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], + activeRaindexAddresses, + selectedRaindexAddresses: [], selectedChainIds: [137] } }); @@ -336,10 +336,10 @@ describe('DropdownOrderbooksFilter', () => { }); test('displays network name next to each orderbook', async () => { - render(DropdownOrderbooksFilter, { + render(DropdownRaindexesFilter, { props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], + activeRaindexAddresses, + selectedRaindexAddresses: [], selectedChainIds: [] } }); @@ -355,10 +355,10 @@ describe('DropdownOrderbooksFilter', () => { describe('Search and keyboard navigation', () => { test('filters orderbooks based on search term (label)', async () => { - render(DropdownOrderbooksFilter, { + render(DropdownRaindexesFilter, { props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], + activeRaindexAddresses, + selectedRaindexAddresses: [], selectedChainIds: [] } }); @@ -371,15 +371,15 @@ describe('DropdownOrderbooksFilter', () => { await waitFor(() => { const options = screen.getAllByTestId('dropdown-orderbooks-filter-option'); expect(options).toHaveLength(1); - expect(screen.getByText(/Orderbook One/)).toBeInTheDocument(); + expect(screen.getByText(/Raindex One/)).toBeInTheDocument(); }); }); test('filters orderbooks based on search term (address)', async () => { - render(DropdownOrderbooksFilter, { + render(DropdownRaindexesFilter, { props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], + activeRaindexAddresses, + selectedRaindexAddresses: [], selectedChainIds: [] } }); @@ -396,10 +396,10 @@ describe('DropdownOrderbooksFilter', () => { }); test('shows "No orderbooks match your search" when search yields no results', async () => { - render(DropdownOrderbooksFilter, { + render(DropdownRaindexesFilter, { props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], + activeRaindexAddresses, + selectedRaindexAddresses: [], selectedChainIds: [] } }); @@ -415,10 +415,10 @@ describe('DropdownOrderbooksFilter', () => { }); test('keyboard navigation works correctly (ArrowDown/ArrowUp)', async () => { - render(DropdownOrderbooksFilter, { + render(DropdownRaindexesFilter, { props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], + activeRaindexAddresses, + selectedRaindexAddresses: [], selectedChainIds: [] } }); @@ -445,10 +445,10 @@ describe('DropdownOrderbooksFilter', () => { }); test('Enter key selects highlighted orderbook', async () => { - render(DropdownOrderbooksFilter, { + render(DropdownRaindexesFilter, { props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], + activeRaindexAddresses, + selectedRaindexAddresses: [], selectedChainIds: [] } }); @@ -467,16 +467,16 @@ describe('DropdownOrderbooksFilter', () => { await fireEvent.keyDown(searchInput, { key: 'Enter' }); await waitFor(() => { - const selected = get(activeOrderbookAddresses); + const selected = get(activeRaindexAddresses); expect(selected).toContain('0x1234567890123456789012345678901234567890'.toLowerCase()); }); }); test('Escape key clears search', async () => { - render(DropdownOrderbooksFilter, { + render(DropdownRaindexesFilter, { props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], + activeRaindexAddresses, + selectedRaindexAddresses: [], selectedChainIds: [] } }); diff --git a/packages/ui-components/src/lib/components/ListViewOrderbookFilters.svelte b/packages/ui-components/src/lib/components/ListViewRaindexFilters.svelte similarity index 89% rename from packages/ui-components/src/lib/components/ListViewOrderbookFilters.svelte rename to packages/ui-components/src/lib/components/ListViewRaindexFilters.svelte index 973fbec1e3..d6c7691324 100644 --- a/packages/ui-components/src/lib/components/ListViewOrderbookFilters.svelte +++ b/packages/ui-components/src/lib/components/ListViewRaindexFilters.svelte @@ -9,7 +9,7 @@ import type { Address, RaindexVaultToken } from '@rainlanguage/orderbook'; import CheckboxActiveOrders from './checkbox/CheckboxActiveOrders.svelte'; import DropdownTokensFilter from './dropdown/DropdownTokensFilter.svelte'; - import DropdownOrderbooksFilter from './dropdown/DropdownOrderbooksFilter.svelte'; + import DropdownRaindexesFilter from './dropdown/DropdownRaindexesFilter.svelte'; import InputOrderHash from './input/InputOrderHash.svelte'; import InputOwnerFilter from './input/InputOwnerFilter.svelte'; import CheckboxZeroBalanceVault from './CheckboxZeroBalanceVault.svelte'; @@ -24,8 +24,8 @@ export let activeTokens: AppStoresInterface['activeTokens']; export let selectedTokens: Address[]; export let tokensQuery: Readable>; - export let activeOrderbookAddresses: AppStoresInterface['activeOrderbookAddresses']; - export let selectedOrderbookAddresses: Address[]; + export let activeRaindexAddresses: AppStoresInterface['activeRaindexAddresses']; + export let selectedRaindexAddresses: Address[]; export let ownerFilter: AppStoresInterface['ownerFilter']; $: isVaultsPage = $page.url.pathname === '/vaults'; @@ -62,11 +62,11 @@ {/if} - {/if} diff --git a/packages/ui-components/src/lib/components/dropdown/DropdownOrderbooksFilter.svelte b/packages/ui-components/src/lib/components/dropdown/DropdownRaindexesFilter.svelte similarity index 53% rename from packages/ui-components/src/lib/components/dropdown/DropdownOrderbooksFilter.svelte rename to packages/ui-components/src/lib/components/dropdown/DropdownRaindexesFilter.svelte index 13b6d2689f..bcb759d021 100644 --- a/packages/ui-components/src/lib/components/dropdown/DropdownOrderbooksFilter.svelte +++ b/packages/ui-components/src/lib/components/dropdown/DropdownRaindexesFilter.svelte @@ -2,20 +2,20 @@ import { Button, Dropdown, Label, Checkbox, Input } from 'flowbite-svelte'; import { ChevronDownSolid, SearchSolid } from 'flowbite-svelte-icons'; import { isEmpty } from 'lodash'; - import type { Address, OrderbookCfg } from '@rainlanguage/orderbook'; + import type { Address, RaindexCfg } from '@rainlanguage/raindex'; import type { AppStoresInterface } from '../../types/appStores'; import { getNetworkName } from '$lib/utils/getNetworkName'; import { useRaindexClient } from '$lib/hooks/useRaindexClient'; - export let activeOrderbookAddresses: AppStoresInterface['activeOrderbookAddresses']; - export let selectedOrderbookAddresses: Address[]; + export let activeRaindexAddresses: AppStoresInterface['activeRaindexAddresses']; + export let selectedRaindexAddresses: Address[]; export let selectedChainIds: number[]; - export let label: string = 'Filter by orderbook'; - export let allLabel: string = 'All orderbooks'; - export let emptyMessage: string = 'No orderbooks available'; + export let label: string = 'Filter by raindex'; + export let allLabel: string = 'All raindexes'; + export let emptyMessage: string = 'No raindexes available'; - interface OrderbookItem { + interface RaindexItem { key: string; address: Address; label: string | undefined; @@ -24,17 +24,17 @@ const raindexClient = useRaindexClient(); - let filteredOrderbooks: OrderbookItem[] = []; + let filteredRaindexes: RaindexItem[] = []; let searchTerm: string = ''; let selectedIndex = 0; - $: orderbooksResult = raindexClient.getAllOrderbooks(); - $: orderbooksMap = orderbooksResult?.value ?? new Map(); - $: orderbooksError = orderbooksResult?.error; + $: raindexesResult = raindexClient.getAllRaindexes(); + $: raindexesMap = raindexesResult?.value ?? new Map(); + $: raindexesError = raindexesResult?.error; - $: availableOrderbooks = (() => { - const items: OrderbookItem[] = []; - orderbooksMap.forEach((cfg: OrderbookCfg, key: string) => { + $: availableRaindexes = (() => { + const items: RaindexItem[] = []; + raindexesMap.forEach((cfg: RaindexCfg, key: string) => { if (selectedChainIds.length === 0 || selectedChainIds.includes(cfg.network.chainId)) { items.push({ key, @@ -47,82 +47,82 @@ return items; })(); - $: selectedCount = selectedOrderbookAddresses.length; + $: selectedCount = selectedRaindexAddresses.length; - $: allSelected = selectedCount === availableOrderbooks.length && availableOrderbooks.length > 0; + $: allSelected = selectedCount === availableRaindexes.length && availableRaindexes.length > 0; $: buttonText = selectedCount === 0 - ? 'Select orderbooks' + ? 'Select raindexes' : allSelected ? allLabel - : `${selectedCount} orderbook${selectedCount > 1 ? 's' : ''}`; + : `${selectedCount} raindex${selectedCount > 1 ? 's' : ''}`; $: { if (searchTerm.trim() === '') { - filteredOrderbooks = availableOrderbooks; + filteredRaindexes = availableRaindexes; selectedIndex = 0; } else { const term = searchTerm.toLowerCase(); - filteredOrderbooks = availableOrderbooks.filter( + filteredRaindexes = availableRaindexes.filter( (ob) => ob.label?.toLowerCase().includes(term) || ob.address?.toLowerCase().includes(term) || ob.key?.toLowerCase().includes(term) ); - selectedIndex = filteredOrderbooks.length > 0 ? 0 : -1; + selectedIndex = filteredRaindexes.length > 0 ? 0 : -1; } } - $: sortedFilteredOrderbooks = [...filteredOrderbooks].sort((a, b) => { - const aSelected = selectedOrderbookAddresses.some( + $: sortedFilteredRaindexes = [...filteredRaindexes].sort((a, b) => { + const aSelected = selectedRaindexAddresses.some( (addr) => addr.toLowerCase() === a.address.toLowerCase() ); - const bSelected = selectedOrderbookAddresses.some( + const bSelected = selectedRaindexAddresses.some( (addr) => addr.toLowerCase() === b.address.toLowerCase() ); if (aSelected === bSelected) return 0; return aSelected ? -1 : 1; }); - function getDisplayName(ob: OrderbookItem): string { + function getDisplayName(ob: RaindexItem): string { const truncatedAddr = `${ob.address.slice(0, 6)}...${ob.address.slice(-4)}`; return ob.label ? `${ob.label} (${truncatedAddr})` : truncatedAddr; } - function updateSelectedOrderbooks(newSelection: Address[]) { - activeOrderbookAddresses.set(newSelection); + function updateSelectedRaindexes(newSelection: Address[]) { + activeRaindexAddresses.set(newSelection); } - function toggleOrderbook({ address }: OrderbookItem) { + function toggleRaindex({ address }: RaindexItem) { if (!address) return; const normalizedAddress = address.toLowerCase() as Address; - const isSelected = selectedOrderbookAddresses.some( + const isSelected = selectedRaindexAddresses.some( (addr) => addr.toLowerCase() === normalizedAddress ); const newSelection = isSelected - ? $activeOrderbookAddresses.filter((addr) => addr.toLowerCase() !== normalizedAddress) - : [...$activeOrderbookAddresses, normalizedAddress]; + ? $activeRaindexAddresses.filter((addr) => addr.toLowerCase() !== normalizedAddress) + : [...$activeRaindexAddresses, normalizedAddress]; - updateSelectedOrderbooks(newSelection); + updateSelectedRaindexes(newSelection); } function handleKeyDown(event: KeyboardEvent) { - if (!sortedFilteredOrderbooks.length) return; + if (!sortedFilteredRaindexes.length) return; switch (event.key) { case 'Enter': event.preventDefault(); - if (sortedFilteredOrderbooks.length > 0) { - const orderbookToToggle = sortedFilteredOrderbooks[selectedIndex]; - if (orderbookToToggle) { - toggleOrderbook(orderbookToToggle); + if (sortedFilteredRaindexes.length > 0) { + const raindexToToggle = sortedFilteredRaindexes[selectedIndex]; + if (raindexToToggle) { + toggleRaindex(raindexToToggle); } } break; case 'ArrowDown': event.preventDefault(); - selectedIndex = Math.min(selectedIndex + 1, sortedFilteredOrderbooks.length - 1); + selectedIndex = Math.min(selectedIndex + 1, sortedFilteredRaindexes.length - 1); break; case 'ArrowUp': event.preventDefault(); @@ -142,8 +142,8 @@ - + diff --git a/packages/ui-components/src/lib/components/LocalDbStatusModal.svelte b/packages/ui-components/src/lib/components/LocalDbStatusModal.svelte index c590714f2f..a81cc04316 100644 --- a/packages/ui-components/src/lib/components/LocalDbStatusModal.svelte +++ b/packages/ui-components/src/lib/components/LocalDbStatusModal.svelte @@ -1,36 +1,36 @@ diff --git a/packages/ui-components/src/lib/components/VaultCard.svelte b/packages/ui-components/src/lib/components/VaultCard.svelte index 49b42ac87e..d60e0f7182 100644 --- a/packages/ui-components/src/lib/components/VaultCard.svelte +++ b/packages/ui-components/src/lib/components/VaultCard.svelte @@ -9,7 +9,7 @@ event.stopPropagation(); event.preventDefault(); // Navigate to vault details page - goto(`/vaults/${vault.chainId}-${vault.orderbook}-${vault.id}`); + goto(`/vaults/${vault.chainId}-${vault.raindex}-${vault.id}`); }; diff --git a/packages/ui-components/src/lib/components/detail/OrderDetail.svelte b/packages/ui-components/src/lib/components/detail/OrderDetail.svelte index e73e5f1b0d..cfb1462c29 100644 --- a/packages/ui-components/src/lib/components/detail/OrderDetail.svelte +++ b/packages/ui-components/src/lib/components/detail/OrderDetail.svelte @@ -41,7 +41,7 @@ export let handleDebugTradeModal: DebugTradeModalHandler | undefined = undefined; export let codeMirrorTheme; export let lightweightChartsTheme; - export let orderbookAddress: Address; + export let raindexAddress: Address; export let orderHash: Hex; export let chainId: number; export let rpcs: string[] | undefined = undefined; @@ -86,7 +86,7 @@ $: orderDetailQuery = createQuery({ queryKey: [QKEY_ORDER, orderHash], queryFn: async () => { - const result = await raindexClient.getOrderByHash(chainId, orderbookAddress, orderHash); + const result = await raindexClient.getOrderByHash(chainId, raindexAddress, orderHash); if (result.error) throw new Error(result.error.readableMsg); return result.value; } @@ -167,9 +167,9 @@
- Orderbook + Raindex - + @@ -261,7 +261,7 @@
{#each filteredVaults as vault} - + {#if matchesAccount(vault.owner)}
diff --git a/packages/ui-components/src/lib/components/detail/VaultDetail.svelte b/packages/ui-components/src/lib/components/detail/VaultDetail.svelte index ef2620cf75..6b2e654e3c 100644 --- a/packages/ui-components/src/lib/components/detail/VaultDetail.svelte +++ b/packages/ui-components/src/lib/components/detail/VaultDetail.svelte @@ -33,7 +33,7 @@ import { useRaindexClient } from '$lib/hooks/useRaindexClient'; export let id: Hex; - export let orderbookAddress: Address; + export let raindexAddress: Address; export let chainId: number; // export let lightweightChartsTheme: Readable | undefined = undefined; @@ -57,7 +57,7 @@ $: vaultDetailQuery = createQuery({ queryKey: [id, QKEY_VAULT + id], queryFn: async () => { - const result = await raindexClient.getVault(chainId, orderbookAddress, id); + const result = await raindexClient.getVault(chainId, raindexAddress, id); if (result.error) throw new Error(result.error.readableMsg); return result.value; } @@ -123,10 +123,10 @@ {toHex(data.vaultId)} - - Orderbook + + Raindex - + @@ -170,7 +170,7 @@

{#if data.ordersAsInput && data.ordersAsInput.length > 0} {#each data.ordersAsInput as order} - + {/each} {:else} None @@ -185,7 +185,7 @@

{#if data.ordersAsOutput && data.ordersAsOutput.length > 0} {#each data.ordersAsOutput as order} - + {/each} {:else} None diff --git a/packages/ui-components/src/lib/components/tables/OrdersListTable.svelte b/packages/ui-components/src/lib/components/tables/OrdersListTable.svelte index 3d74d8d513..b7071a4a4d 100644 --- a/packages/ui-components/src/lib/components/tables/OrdersListTable.svelte +++ b/packages/ui-components/src/lib/components/tables/OrdersListTable.svelte @@ -97,7 +97,7 @@ selectedTokens.length > 0 ? { inputs: selectedTokens, outputs: selectedTokens } : undefined, - orderbookAddresses: + raindexAddresses: selectedRaindexAddresses.length > 0 ? selectedRaindexAddresses : undefined }, pageParam + 1 @@ -137,7 +137,7 @@ emptyMessage="No Orders Found" dataSelector={(page) => page.orders} on:clickRow={(e) => { - goto(`/orders/${e.detail.item.chainId}-${e.detail.item.orderbook}-${e.detail.item.orderHash}`); + goto(`/orders/${e.detail.item.chainId}-${e.detail.item.raindex}-${e.detail.item.orderHash}`); }} > @@ -213,8 +213,8 @@

- Orderbook: - + Raindex: +
diff --git a/packages/ui-components/src/lib/components/tables/VaultsListTable.svelte b/packages/ui-components/src/lib/components/tables/VaultsListTable.svelte index c3e14db115..78f55ea0c5 100644 --- a/packages/ui-components/src/lib/components/tables/VaultsListTable.svelte +++ b/packages/ui-components/src/lib/components/tables/VaultsListTable.svelte @@ -116,7 +116,7 @@ owners, hideZeroBalance: $hideZeroBalanceVaults, tokens: selectedTokens, - orderbookAddresses: + raindexAddresses: selectedRaindexAddresses.length > 0 ? selectedRaindexAddresses : undefined, onlyActiveOrders: $hideInactiveOrdersVaults }, @@ -234,7 +234,7 @@ queryKey={QKEY_VAULTS} emptyMessage="No Vaults Found" on:clickRow={(e) => { - goto(`/vaults/${e.detail.item.chainId}-${e.detail.item.orderbook}-${e.detail.item.id}`); + goto(`/vaults/${e.detail.item.chainId}-${e.detail.item.raindex}-${e.detail.item.id}`); }} > @@ -299,8 +299,8 @@
- Orderbook: - + Raindex: +
Owner: @@ -324,7 +324,7 @@ type="orders" orderOrVault={order} chainId={item.chainId} - orderbookAddress={item.orderbook} + raindexAddress={item.raindex} /> {/each} {#if item.ordersAsInput.length > 3}...{/if} @@ -339,7 +339,7 @@ type="orders" orderOrVault={order} chainId={item.chainId} - orderbookAddress={item.orderbook} + raindexAddress={item.raindex} /> {/each} {#if item.ordersAsOutput.length > 3}...{/if} diff --git a/packages/ui-components/src/lib/providers/transactions/TransactionManager.ts b/packages/ui-components/src/lib/providers/transactions/TransactionManager.ts index 576c5acd2b..57b5b5e1bf 100644 --- a/packages/ui-components/src/lib/providers/transactions/TransactionManager.ts +++ b/packages/ui-components/src/lib/providers/transactions/TransactionManager.ts @@ -126,7 +126,7 @@ export class TransactionManager { } /** - * Creates and initializes a new transaction for removing an order from the orderbook. + * Creates and initializes a new transaction for removing an order from the raindex. * @param args - Configuration for the remove order transaction. * @param args.txHash - Hash of the transaction to track. * @param args.chainId - Chain ID where the transaction is being executed. @@ -149,7 +149,7 @@ export class TransactionManager { const successMessage = 'Order removed successfully.'; const { chainId, - entity: { orderbook }, + entity: { raindex }, queryKey, txHash, raindexClient @@ -164,7 +164,7 @@ export class TransactionManager { ]; const awaitIndexingFn = createSdkIndexingFn({ - call: () => raindexClient.getRemoveOrdersForTransaction(chainId, orderbook, txHash), + call: () => raindexClient.getRemoveOrdersForTransaction(chainId, raindex, txHash), isSuccess: (orders) => Array.isArray(orders) && orders.length > 0 }); @@ -203,7 +203,7 @@ export class TransactionManager { const successMessage = 'Withdrawal successful.'; const { chainId, - entity: { orderbook }, + entity: { raindex }, queryKey, txHash, raindexClient @@ -212,7 +212,7 @@ export class TransactionManager { const explorerLink = await getExplorerLink(txHash, chainId, 'tx'); const toastLinks: ToastLink[] = [ { - link: `/vaults/${chainId}-${orderbook}-${queryKey}`, + link: `/vaults/${chainId}-${raindex}-${queryKey}`, label: 'View vault' }, { @@ -222,7 +222,7 @@ export class TransactionManager { ]; const awaitIndexingFn = createSdkIndexingFn({ - call: () => raindexClient.getTransaction(chainId, orderbook, txHash), + call: () => raindexClient.getTransaction(chainId, raindex, txHash), isSuccess: (tx) => !!tx }); @@ -240,12 +240,12 @@ export class TransactionManager { /** * Creates a multicall withdrawal transaction. * - * Precondition: all provided vaults must share the same Raindex orderbook. + * Precondition: all provided vaults must share the same raindex. * This is enforced upstream in handleVaultsWithdrawAll.ts: - * if (vaults.some(v => v.orderbook !== vaults[0].orderbook)) { … } + * if (vaults.some(v => v.raindex !== vaults[0].raindex)) { … } * * @param args.chainId the target chain ID - * @param args.vaults list of RaindexVault instances (must share an orderbook) + * @param args.vaults list of RaindexVault instances (must share a raindex) * @param args.txHash the transaction hash to wrap * @param args.queryKey cache key for invalidation * @param args.raindexClient Raindex API client * @example @@ -268,9 +268,9 @@ export class TransactionManager { if (vaults.length === 0) { throw new Error('At least one vault is required for withdrawal'); } - // All vaults must share the same orderbook for multicall transactions + // All vaults must share the same raindex for multicall transactions // It should be validated before calling this method - const orderbook = vaults[0].orderbook; + const raindex = vaults[0].raindex; const explorerLink = await getExplorerLink(txHash, chainId, 'tx'); const toastLinks: ToastLink[] = [ { @@ -284,7 +284,7 @@ export class TransactionManager { ]; const awaitIndexingFn = createSdkIndexingFn({ - call: () => raindexClient.getTransaction(chainId, orderbook, txHash), + call: () => raindexClient.getTransaction(chainId, raindex, txHash), isSuccess: (tx) => !!tx }); @@ -336,7 +336,7 @@ export class TransactionManager { if (entity) { toastLinks = [ { - link: `/vaults/${chainId}-${entity.orderbook}-${queryKey}`, + link: `/vaults/${chainId}-${entity.raindex}-${queryKey}`, label: 'View vault' }, ...toastLinks @@ -412,7 +412,7 @@ export class TransactionManager { const successMessage = 'Deposit successful.'; const { chainId, - entity: { orderbook }, + entity: { raindex }, txHash, queryKey, raindexClient @@ -421,7 +421,7 @@ export class TransactionManager { const explorerLink = await getExplorerLink(txHash, chainId, 'tx'); const toastLinks: ToastLink[] = [ { - link: `/vaults/${chainId}-${orderbook}-${queryKey}`, + link: `/vaults/${chainId}-${raindex}-${queryKey}`, label: 'View vault' }, { @@ -431,7 +431,7 @@ export class TransactionManager { ]; const awaitIndexingFn = createSdkIndexingFn({ - call: () => raindexClient.getTransaction(chainId, orderbook, txHash), + call: () => raindexClient.getTransaction(chainId, raindex, txHash), isSuccess: (tx) => !!tx }); @@ -462,9 +462,9 @@ export class TransactionManager { */ public async createAddOrderTransaction( - args: InternalTransactionArgs & { orderbook: Address; raindexClient: RaindexClient } + args: InternalTransactionArgs & { raindex: Address; raindexClient: RaindexClient } ): Promise { - const { queryKey, txHash, chainId, orderbook, raindexClient } = args; + const { queryKey, txHash, chainId, raindex, raindexClient } = args; const name = 'Deploying order'; const errorMessage = 'Deployment failed.'; const successMessage = 'Order deployed successfully.'; @@ -480,7 +480,7 @@ export class TransactionManager { // SDK-based indexing - the SDK's getAddOrdersForTransaction handles // local-DB-first polling followed by subgraph fallback internally const awaitIndexingFn = createSdkIndexingFn({ - call: () => raindexClient.getAddOrdersForTransaction(chainId, orderbook, txHash), + call: () => raindexClient.getAddOrdersForTransaction(chainId, raindex, txHash), isSuccess: (orders) => Array.isArray(orders) && orders.length > 0, buildLinks: (orders) => { if (!Array.isArray(orders) || orders.length === 0) return []; @@ -488,7 +488,7 @@ export class TransactionManager { if (!firstOrder?.orderHash) return []; return [ { - link: `/orders/${chainId}-${orderbook}-${firstOrder.orderHash}`, + link: `/orders/${chainId}-${raindex}-${firstOrder.orderHash}`, label: 'View order' } ]; @@ -531,7 +531,7 @@ export class TransactionManager { const successMessage = 'Order taken successfully.'; const { chainId, - entity: { orderbook }, + entity: { raindex }, queryKey, txHash, raindexClient @@ -545,7 +545,7 @@ export class TransactionManager { } ]; const awaitIndexingFn = createSdkIndexingFn({ - call: () => raindexClient.getTransaction(chainId, orderbook, txHash), + call: () => raindexClient.getTransaction(chainId, raindex, txHash), isSuccess: (tx) => !!tx }); diff --git a/packages/ui-components/src/lib/services/awaitTransactionIndexing.ts b/packages/ui-components/src/lib/services/awaitTransactionIndexing.ts index 4e3518a889..8f3563763f 100644 --- a/packages/ui-components/src/lib/services/awaitTransactionIndexing.ts +++ b/packages/ui-components/src/lib/services/awaitTransactionIndexing.ts @@ -14,12 +14,12 @@ import type { export type AwaitSubgraphConfig = { chainId: number; - orderbook: Address; + raindex: Address; txHash: Hex; successMessage: string; fetchEntityFn: ( chainId: number, - orderbook: Address, + raindex: Address, txHash: Hex ) => Promise>; isSuccess: (data: RaindexTransaction | RaindexOrder[]) => boolean; @@ -68,7 +68,7 @@ export type IndexingResult = { * @template T The type of data returned by the subgraph * @param options Configuration options for the indexing operation * @param options.chainId Chain ID to query - * @param options.orderbook Orderbook address to query + * @param options.raindex Raindex address to query * @param options.txHash Transaction hash to check for indexing * @param options.successMessage Message to display on successful indexing * @param options.maxAttempts Maximum number of attempts before timing out (default: 10) @@ -84,9 +84,9 @@ export const awaitSubgraphIndexing = async (options: { */ chainId: number; /** - * Orderbook address to query + * Raindex address to query */ - orderbook: Address; + raindex: Address; /** * Transaction hash to check for indexing */ @@ -110,12 +110,12 @@ export const awaitSubgraphIndexing = async (options: { /** * Function to fetch data from the subgraph * @param chainId Chain ID to query - * @param orderbook Orderbook address to query + * @param raindex Raindex address to query * @param txHash Transaction hash to query */ fetchEntityFn: ( chainId: number, - orderbook: Address, + raindex: Address, txHash: Hex ) => Promise>; /** @@ -126,7 +126,7 @@ export const awaitSubgraphIndexing = async (options: { }): Promise> => { const { chainId, - orderbook, + raindex, txHash, successMessage, maxAttempts = 10, @@ -138,7 +138,7 @@ export const awaitSubgraphIndexing = async (options: { const checkIndexing = async (attempt: number): Promise> => { try { - const data = await fetchEntityFn(chainId, orderbook, txHash); + const data = await fetchEntityFn(chainId, raindex, txHash); if (data.value && isSuccess(data.value)) { let newOrderHash; diff --git a/packages/ui-components/src/lib/services/historicalOrderCharts.ts b/packages/ui-components/src/lib/services/historicalOrderCharts.ts index f49ded40f7..56e9db5539 100644 --- a/packages/ui-components/src/lib/services/historicalOrderCharts.ts +++ b/packages/ui-components/src/lib/services/historicalOrderCharts.ts @@ -88,7 +88,7 @@ if (import.meta.vitest) { timestamp: BigInt(1632000000), blockNumber: BigInt(0) } as unknown as RaindexTransaction, - orderbook: '0x1' + raindex: '0x1' } as unknown as RaindexVaultBalanceChange, orderHash: 'orderHash', inputVaultBalanceChange: { @@ -114,9 +114,9 @@ if (import.meta.vitest) { timestamp: BigInt(1632000000), blockNumber: BigInt(0) } as unknown as RaindexTransaction, - orderbook: '0x1' + raindex: '0x1' } as unknown as RaindexVaultBalanceChange, - orderbook: '0x00' + raindex: '0x00' } as unknown as RaindexTrade, { id: '2', @@ -150,7 +150,7 @@ if (import.meta.vitest) { timestamp: BigInt(1632000000), blockNumber: BigInt(0) } as unknown as RaindexTransaction, - orderbook: '0x1' + raindex: '0x1' } as unknown as RaindexVaultBalanceChange, orderHash: 'orderHash', inputVaultBalanceChange: { @@ -176,9 +176,9 @@ if (import.meta.vitest) { timestamp: BigInt(1632000000), blockNumber: BigInt(0) } as unknown as RaindexTransaction, - orderbook: '0x1' + raindex: '0x1' } as unknown as RaindexVaultBalanceChange, - orderbook: '0x00' + raindex: '0x00' } as unknown as RaindexTrade, { id: '3', @@ -212,7 +212,7 @@ if (import.meta.vitest) { timestamp: BigInt(1632000000), blockNumber: BigInt(0) } as unknown as RaindexTransaction, - orderbook: '0x1' + raindex: '0x1' } as unknown as RaindexVaultBalanceChange, orderHash: 'orderHash', inputVaultBalanceChange: { @@ -238,9 +238,9 @@ if (import.meta.vitest) { timestamp: BigInt(1632000000), blockNumber: BigInt(0) } as unknown as RaindexTransaction, - orderbook: '0x1' + raindex: '0x1' } as unknown as RaindexVaultBalanceChange, - orderbook: '0x00' + raindex: '0x00' } as unknown as RaindexTrade ]; @@ -294,7 +294,7 @@ if (import.meta.vitest) { blockNumber: BigInt(0) } as unknown as RaindexTransaction, __typename: 'Withdraw', - orderbook: '0x1' + raindex: '0x1' } as unknown as RaindexVaultBalanceChange, orderHash: 'orderHash', inputVaultBalanceChange: { @@ -319,9 +319,9 @@ if (import.meta.vitest) { timestamp: BigInt(1632000000), blockNumber: BigInt(0) } as unknown as RaindexTransaction, - orderbook: '0x1' + raindex: '0x1' } as unknown as RaindexVaultBalanceChange, - orderbook: '0x00' + raindex: '0x00' } as unknown as RaindexTrade, { id: '2', @@ -354,7 +354,7 @@ if (import.meta.vitest) { timestamp: BigInt(1632000000), blockNumber: BigInt(0) } as unknown as RaindexTransaction, - orderbook: '0x1' + raindex: '0x1' } as unknown as RaindexVaultBalanceChange, orderHash: 'orderHash', inputVaultBalanceChange: { @@ -379,9 +379,9 @@ if (import.meta.vitest) { timestamp: BigInt(1632000000), blockNumber: BigInt(0) } as unknown as RaindexTransaction, - orderbook: '0x1' + raindex: '0x1' } as unknown as RaindexVaultBalanceChange, - orderbook: '0x00' + raindex: '0x00' } as unknown as RaindexTrade, { id: '3', @@ -414,7 +414,7 @@ if (import.meta.vitest) { timestamp: BigInt(1632000000), blockNumber: BigInt(0) } as unknown as RaindexTransaction, - orderbook: '0x1' + raindex: '0x1' } as unknown as RaindexVaultBalanceChange, orderHash: 'orderHash', inputVaultBalanceChange: { @@ -439,9 +439,9 @@ if (import.meta.vitest) { timestamp: BigInt(1632000000), blockNumber: BigInt(0) } as unknown as RaindexTransaction, - orderbook: '0x1' + raindex: '0x1' } as unknown as RaindexVaultBalanceChange, - orderbook: '0x00' + raindex: '0x00' } as unknown as RaindexTrade ]; diff --git a/packages/ui-components/src/lib/utils/constructHashLink.ts b/packages/ui-components/src/lib/utils/constructHashLink.ts index 340b98910e..0461771874 100644 --- a/packages/ui-components/src/lib/utils/constructHashLink.ts +++ b/packages/ui-components/src/lib/utils/constructHashLink.ts @@ -17,14 +17,14 @@ function isOrder(obj: OrderOrVault): obj is RaindexOrder | RaindexOrderAsIO { * @param orderOrVault - The order or vault object * @param type - The type of resource ('orders' or 'vaults') * @param chainId - The chain id - * @param orderbookAddress - The orderbook address + * @param raindexAddress - The raindex address * @returns The constructed link path */ export function constructHashLink( orderOrVault: OrderOrVault, type: 'orders' | 'vaults', chainId: number, - orderbookAddress: Address + raindexAddress: Address ): string { if (!orderOrVault) { return `/${type}`; @@ -32,7 +32,7 @@ export function constructHashLink( const slug = isOrder(orderOrVault) ? orderOrVault.orderHash : (orderOrVault as RaindexVault).id; - return `/${type}/${chainId}-${orderbookAddress}-${slug}`; + return `/${type}/${chainId}-${raindexAddress}-${slug}`; } /** @@ -69,14 +69,14 @@ if (import.meta.vitest) { fc.oneof(fc.constant('orders'), fc.constant('vaults')), fc.integer(), fc.string() - ])('constructs correct link for orders', (order, type, chainId, orderbookAddress) => { + ])('constructs correct link for orders', (order, type, chainId, raindexAddress) => { const result = constructHashLink( order as RaindexOrder, type, chainId, - orderbookAddress as Address + raindexAddress as Address ); - expect(result).toBe(`/${type}/${chainId}-${orderbookAddress}-${order.orderHash}`); + expect(result).toBe(`/${type}/${chainId}-${raindexAddress}-${order.orderHash}`); }); test.prop([ @@ -87,14 +87,14 @@ if (import.meta.vitest) { fc.oneof(fc.constant('orders'), fc.constant('vaults')), fc.integer(), fc.string() - ])('constructs correct link for vaults', (vault, type, chainId, orderbookAddress) => { + ])('constructs correct link for vaults', (vault, type, chainId, raindexAddress) => { const result = constructHashLink( vault as RaindexVault, type, chainId, - orderbookAddress as Address + raindexAddress as Address ); - expect(result).toBe(`/${type}/${chainId}-${orderbookAddress}-${vault.id}`); + expect(result).toBe(`/${type}/${chainId}-${raindexAddress}-${vault.id}`); }); }); From 9c7ae962ce8d977ec6696fed0bb98bcae38e05d3 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Tue, 31 Mar 2026 16:32:21 +0400 Subject: [PATCH 19/69] Rename remaining OrderBook references across all crates Co-Authored-By: Claude Opus 4.6 (1M context) --- crates/common/src/local_db/decode.rs | 4 +- crates/common/src/local_db/insert.rs | 2 +- .../src/local_db/pipeline/adapters/events.rs | 2 +- .../common/src/raindex_client/add_orders.rs | 18 +- .../common/src/raindex_client/local_db/mod.rs | 8 +- .../local_db/pipeline/runner/config.rs | 6 +- .../local_db/pipeline/runner/mod.rs | 46 ++--- .../pipeline/runner/scheduler/native.rs | 2 +- .../local_db/pipeline/status/mod.rs | 18 +- .../local_db/pipeline/status/native.rs | 2 +- .../local_db/query/fetch_order_trades.rs | 6 +- .../query/fetch_order_trades_count.rs | 6 +- .../query/fetch_order_vaults_volume.rs | 6 +- .../local_db/query/fetch_orders.rs | 12 +- .../local_db/query/fetch_store_addresses.rs | 6 +- .../query/fetch_transaction_by_hash.rs | 12 +- .../query/fetch_vault_balance_changes.rs | 18 +- .../local_db/query/fetch_vaults.rs | 10 +- .../src/raindex_client/local_db/state.rs | 4 +- crates/common/src/raindex_client/mod.rs | 16 +- .../common/src/raindex_client/order_quotes.rs | 22 +- crates/common/src/raindex_client/orders.rs | 56 +++--- .../common/src/raindex_client/orders_list.rs | 10 +- .../src/raindex_client/remove_orders.rs | 28 +-- .../raindex_client/take_orders/approval.rs | 28 +-- .../raindex_client/take_orders/e2e_tests.rs | 188 +++++++++--------- .../src/raindex_client/take_orders/mod.rs | 2 +- .../src/raindex_client/take_orders/result.rs | 2 +- .../src/raindex_client/take_orders/single.rs | 36 ++-- crates/common/src/raindex_client/trades.rs | 24 +-- .../common/src/raindex_client/transactions.rs | 4 +- crates/common/src/raindex_client/vaults.rs | 42 ++-- .../common/src/raindex_client/vaults_list.rs | 10 +- crates/common/src/remove_order.rs | 6 +- crates/common/src/subgraph.rs | 6 +- crates/common/src/take_orders/candidates.rs | 4 +- crates/common/src/test_helpers.rs | 12 +- .../common/src/types/order_detail_extended.rs | 8 +- .../src/types/order_takes_list_flattened.rs | 8 +- .../common/src/types/orders_list_flattened.rs | 16 +- .../common/src/types/token_vault_flattened.rs | 4 +- .../types/vault_balance_change_flattened.rs | 4 +- crates/quote/src/cli/mod.rs | 6 +- crates/quote/src/order_quotes.rs | 12 +- crates/quote/src/quote.rs | 12 +- crates/quote/src/quote_debug.rs | 6 +- crates/rest_api/src/routes/take_orders.rs | 2 +- crates/test_fixtures/src/lib.rs | 2 +- 48 files changed, 382 insertions(+), 382 deletions(-) diff --git a/crates/common/src/local_db/decode.rs b/crates/common/src/local_db/decode.rs index 7ac55e0584..1661faa23c 100644 --- a/crates/common/src/local_db/decode.rs +++ b/crates/common/src/local_db/decode.rs @@ -10,7 +10,7 @@ use raindex_bindings::{ IRaindexV6::{ AddOrderV3, AfterClearV2, ClearV3, DepositV2, RemoveOrderV3, TakeOrderV3, WithdrawV2, }, - OrderBook::MetaV1_2, + Raindex::MetaV1_2, }; use serde::{Deserialize, Serialize}; @@ -215,7 +215,7 @@ mod test_helpers { RemoveOrderV3, SignedContextV1, TakeOrderConfigV4, TakeOrderV3, WithdrawV2, }, IRaindexV6::{EvaluableV4, OrderV4, IOV2}, - OrderBook::MetaV1_2, + Raindex::MetaV1_2, }; use serde_json::Value; use std::str::FromStr; diff --git a/crates/common/src/local_db/insert.rs b/crates/common/src/local_db/insert.rs index 9549781e44..222383858f 100644 --- a/crates/common/src/local_db/insert.rs +++ b/crates/common/src/local_db/insert.rs @@ -14,7 +14,7 @@ use raindex_bindings::IRaindexV6::{ AddOrderV3, AfterClearV2, ClearV3, DepositV2, OrderV4, RemoveOrderV3, TakeOrderV3, WithdrawV2, IOV2, }; -use raindex_bindings::OrderBook::MetaV1_2; +use raindex_bindings::Raindex::MetaV1_2; use std::collections::HashMap; use std::convert::TryInto; use thiserror::Error; diff --git a/crates/common/src/local_db/pipeline/adapters/events.rs b/crates/common/src/local_db/pipeline/adapters/events.rs index 5a4b6ebfe8..ee11cd63f9 100644 --- a/crates/common/src/local_db/pipeline/adapters/events.rs +++ b/crates/common/src/local_db/pipeline/adapters/events.rs @@ -93,7 +93,7 @@ mod tests { use alloy::primitives::{b256, Bytes, U256}; use alloy::sol_types::SolEvent; use httpmock::MockServer; - use raindex_bindings::OrderBook::MetaV1_2; + use raindex_bindings::Raindex::MetaV1_2; use serde_json::json; use std::str::FromStr; diff --git a/crates/common/src/raindex_client/add_orders.rs b/crates/common/src/raindex_client/add_orders.rs index 1bcc047d74..486f5abcbf 100644 --- a/crates/common/src/raindex_client/add_orders.rs +++ b/crates/common/src/raindex_client/add_orders.rs @@ -137,8 +137,8 @@ impl RaindexClient { .await { Ok(orders) => orders, - Err(RaindexError::OrderbookSubgraphClientError( - raindex_subgraph_client::OrderbookSubgraphClientError::Empty, + Err(RaindexError::RaindexSubgraphClientError( + raindex_subgraph_client::RaindexSubgraphClientError::Empty, )) => return Err(PollError::Empty), Err(e) => return Err(PollError::Inner(e)), }; @@ -179,7 +179,7 @@ mod tests { mod non_wasm { use super::*; use crate::raindex_client::tests::{ - get_test_yaml, new_with_local_db, CHAIN_ID_1_ORDERBOOK_ADDRESS, + get_test_yaml, new_with_local_db, CHAIN_ID_1_RAINDEX_ADDRESS, }; use crate::{ local_db::query::{ @@ -274,7 +274,7 @@ mod tests { "symbol": "sFLR", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "ordersAsOutput": [ @@ -301,7 +301,7 @@ mod tests { "symbol": "WFLR", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "ordersAsOutput": [], @@ -315,7 +315,7 @@ mod tests { "balanceChanges": [] } ], - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "active": true, @@ -364,7 +364,7 @@ mod tests { let res = raindex_client .get_add_orders_for_transaction( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), None, None, @@ -549,7 +549,7 @@ mod tests { let res = raindex_client .get_add_orders_for_transaction( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), Some(DEFAULT_ADD_ORDER_POLL_ATTEMPTS), Some(10), @@ -583,7 +583,7 @@ mod tests { let err = raindex_client .get_add_orders_for_transaction( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), Some(DEFAULT_ADD_ORDER_POLL_ATTEMPTS), Some(10), diff --git a/crates/common/src/raindex_client/local_db/mod.rs b/crates/common/src/raindex_client/local_db/mod.rs index bb67309f1e..570a990174 100644 --- a/crates/common/src/raindex_client/local_db/mod.rs +++ b/crates/common/src/raindex_client/local_db/mod.rs @@ -354,7 +354,7 @@ mod wasm_tests { wasm_bindgen_test_configure!(run_in_browser); - fn single_orderbook_settings_yaml() -> String { + fn single_raindex_settings_yaml() -> String { format!( r#" version: {version} @@ -377,7 +377,7 @@ local-db-sync: finality-depth: 12 bootstrap-block-threshold: 1000 sync-interval-ms: 5000 -orderbooks: +raindexes: ob-a: address: 0x00000000000000000000000000000000000000a1 network: anvil @@ -391,9 +391,9 @@ orderbooks: #[cfg(not(target_family = "wasm"))] async fn build_client() -> RaindexClient { - RaindexClient::new(vec![single_orderbook_settings_yaml()], None, None) + RaindexClient::new(vec![single_raindex_settings_yaml()], None, None) .await - .expect("valid orderbook yaml") + .expect("valid raindex yaml") } fn success_callback() -> js_sys::Function { diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/config.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/config.rs index 93708d6ece..9000b7b10b 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/config.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/config.rs @@ -109,7 +109,7 @@ local-db-sync: finality-depth: 24 bootstrap-block-threshold: 5000 sync-interval-ms: 5000 -orderbooks: +raindexes: ob-a: address: 0x00000000000000000000000000000000000000a1 network: network-a @@ -134,7 +134,7 @@ orderbooks: } #[test] - fn from_global_settings_filters_orderbooks_for_network() { + fn from_global_settings_filters_raindexes_for_network() { let global = parse_runner_settings(&sample_settings_yaml()).expect("valid yaml"); let config = NetworkRunnerConfig::from_global_settings(&global, "network-a").expect("config ok"); @@ -179,7 +179,7 @@ orderbooks: } #[test] - fn build_targets_single_orderbook_network() { + fn build_targets_single_raindex_network() { let global = parse_runner_settings(&sample_settings_yaml()).expect("valid yaml"); let config = NetworkRunnerConfig::from_global_settings(&global, "network-b").expect("config ok"); diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs index 9e92bdd043..bd7adc31b8 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs @@ -1001,7 +1001,7 @@ mod tests { HashMap::from([(remote, manifest)]) } - fn two_orderbooks_settings_yaml() -> String { + fn two_raindexes_settings_yaml() -> String { format!( r#" version: {version} @@ -1025,7 +1025,7 @@ local-db-sync: finality-depth: 12 bootstrap-block-threshold: 10000 sync-interval-ms: 5000 -orderbooks: +raindexes: ob-a: address: 0x00000000000000000000000000000000000000a1 network: anvil @@ -1043,7 +1043,7 @@ orderbooks: ) } - fn single_orderbook_settings_yaml() -> String { + fn single_raindex_settings_yaml() -> String { format!( r#" version: {version} @@ -1066,7 +1066,7 @@ local-db-sync: finality-depth: 12 bootstrap-block-threshold: 10000 sync-interval-ms: 5000 -orderbooks: +raindexes: ob-a: address: 0x00000000000000000000000000000000000000a1 network: anvil @@ -1198,7 +1198,7 @@ orderbooks: .collect() } - fn expect_orderbooks(report: &RunReport, expected: &[Address]) { + fn expect_raindexes(report: &RunReport, expected: &[Address]) { let outcomes = extract_outcomes(report); let mut addrs: Vec
= outcomes.iter().map(|o| o.raindex_id.raindex_address).collect(); addrs.sort(); @@ -1229,7 +1229,7 @@ orderbooks: #[test] fn default_environment_builds_engine_for_target() { - let settings = single_orderbook_settings_yaml(); + let settings = single_raindex_settings_yaml(); let runner = ClientRunner::new(settings).expect("runner builds with default env"); assert_eq!(runner.base_targets.len(), 1); @@ -1247,7 +1247,7 @@ orderbooks: let telemetry = Telemetry::default(); let environment = build_environment(manifest_for_both(), HashMap::new(), 1, 2, telemetry.clone()); - let settings = two_orderbooks_settings_yaml(); + let settings = two_raindexes_settings_yaml(); let mut runner = ClientRunner::with_environment(settings, environment, AlwaysLeadership).unwrap(); let db = RecordingDb::default(); @@ -1257,7 +1257,7 @@ orderbooks: let report = unwrap_report(outcome); let outcomes = extract_outcomes(&report); assert_eq!(outcomes.len(), 2); - expect_orderbooks(&report, &[RAINDEX_A, RAINDEX_B]); + expect_raindexes(&report, &[RAINDEX_A, RAINDEX_B]); assert!(runner.manifests_loaded); assert!(runner.has_provisioned_dumps); assert_eq!(telemetry.manifest_fetch_count(), 1); @@ -1285,7 +1285,7 @@ orderbooks: let telemetry = Telemetry::default(); let environment = build_environment(manifest_for_both(), HashMap::new(), 1, 2, telemetry.clone()); - let settings = two_orderbooks_settings_yaml(); + let settings = two_raindexes_settings_yaml(); let mut runner = ClientRunner::with_environment(settings, environment, AlwaysLeadership).unwrap(); @@ -1310,7 +1310,7 @@ orderbooks: let telemetry = Telemetry::default(); let environment = build_environment(manifest_for_both(), HashMap::new(), 1, 2, telemetry.clone()); - let settings = two_orderbooks_settings_yaml(); + let settings = two_raindexes_settings_yaml(); let leadership = CountingLeadership::new(); let mut runner = ClientRunner::with_environment(settings, environment, leadership.clone()).unwrap(); @@ -1335,7 +1335,7 @@ orderbooks: let telemetry = Telemetry::default(); let environment = build_environment(manifest_for_both(), HashMap::new(), 1, 2, telemetry.clone()); - let settings = two_orderbooks_settings_yaml(); + let settings = two_raindexes_settings_yaml(); let leadership = SequenceLeadership::new(vec![LeadershipAction::Skip]); let mut runner = ClientRunner::with_environment(settings, environment, leadership).unwrap(); @@ -1356,7 +1356,7 @@ orderbooks: let telemetry = Telemetry::default(); let environment = build_environment(manifest_for_both(), HashMap::new(), 1, 2, telemetry.clone()); - let settings = two_orderbooks_settings_yaml(); + let settings = two_raindexes_settings_yaml(); let leadership = SequenceLeadership::new(vec![LeadershipAction::Skip, LeadershipAction::Grant]); let mut runner = ClientRunner::with_environment(settings, environment, leadership).unwrap(); @@ -1385,7 +1385,7 @@ orderbooks: let telemetry = Telemetry::default(); let environment = build_environment(manifest_for_both(), HashMap::new(), 1, 2, telemetry.clone()); - let settings = two_orderbooks_settings_yaml(); + let settings = two_raindexes_settings_yaml(); let leadership = SequenceLeadership::new(vec![LeadershipAction::Fail("no leadership".into())]); let mut runner = ClientRunner::with_environment(settings, environment, leadership).unwrap(); @@ -1411,7 +1411,7 @@ orderbooks: 1, telemetry.clone(), ); - let settings = two_orderbooks_settings_yaml(); + let settings = two_raindexes_settings_yaml(); let mut runner = ClientRunner::with_environment(settings, environment, AlwaysLeadership).unwrap(); let db = RecordingDb::default(); @@ -1448,7 +1448,7 @@ orderbooks: let telemetry = Telemetry::default(); let environment = build_environment(ManifestMap::new(), HashMap::new(), 1, 0, telemetry.clone()); - let settings = single_orderbook_settings_yaml(); + let settings = single_raindex_settings_yaml(); let mut runner = ClientRunner::with_environment(settings, environment, AlwaysLeadership).unwrap(); runner.base_targets.clear(); @@ -1497,7 +1497,7 @@ orderbooks: }; let engine_builder = engine_builder_for_behaviors(telemetry.clone(), HashMap::new()); let environment = RunnerEnvironment::new(manifest_fetcher, dump_downloader, engine_builder); - let settings = single_orderbook_settings_yaml(); + let settings = single_raindex_settings_yaml(); let mut runner = ClientRunner::with_environment(settings, environment, AlwaysLeadership).unwrap(); @@ -1542,7 +1542,7 @@ orderbooks: let engine_builder = engine_builder_for_behaviors(telemetry.clone(), HashMap::new()); let environment = RunnerEnvironment::new(manifest_fetcher, dump_downloader, engine_builder); - let settings = single_orderbook_settings_yaml(); + let settings = single_raindex_settings_yaml(); let mut runner = ClientRunner::with_environment(settings, environment, AlwaysLeadership).unwrap(); @@ -1602,7 +1602,7 @@ orderbooks: let engine_builder = engine_builder_for_behaviors(telemetry.clone(), behaviors); let environment = RunnerEnvironment::new(manifest_fetcher, dump_downloader, engine_builder); - let settings = single_orderbook_settings_yaml(); + let settings = single_raindex_settings_yaml(); let mut runner = ClientRunner::with_environment(settings, environment, AlwaysLeadership).unwrap(); let db = RecordingDb::default(); @@ -1651,7 +1651,7 @@ orderbooks: let engine_builder = engine_builder_for_behaviors(telemetry.clone(), HashMap::new()); let environment = RunnerEnvironment::new(manifest_fetcher, dump_downloader, engine_builder); - let settings = two_orderbooks_settings_yaml(); + let settings = two_raindexes_settings_yaml(); let mut runner = ClientRunner::with_environment(settings, environment, AlwaysLeadership).unwrap(); let db = RecordingDb::default(); @@ -1679,7 +1679,7 @@ orderbooks: async fn engine_builder_error_is_propagated() { let telemetry = Telemetry::default(); let manifest = manifest_for_both(); - let settings = two_orderbooks_settings_yaml(); + let settings = two_raindexes_settings_yaml(); let behaviors = HashMap::from([(RAINDEX_KEY_B.to_string(), EngineBehavior::Success)]); let manifest_arc = Arc::new(manifest); @@ -1773,7 +1773,7 @@ orderbooks: behaviors.insert(RAINDEX_KEY_B.to_string(), EngineBehavior::Success); let environment = build_environment(manifest_for_both(), behaviors, 1, 2, telemetry.clone()); - let settings = two_orderbooks_settings_yaml(); + let settings = two_raindexes_settings_yaml(); let mut runner = ClientRunner::with_environment(settings, environment, AlwaysLeadership).unwrap(); let db = RecordingDb::default(); @@ -1800,7 +1800,7 @@ orderbooks: async fn engine_build_and_run_failures_are_both_reported() { let telemetry = Telemetry::default(); let manifest = manifest_for_both(); - let settings = two_orderbooks_settings_yaml(); + let settings = two_raindexes_settings_yaml(); let manifest_arc = Arc::new(manifest); let manifest_fetcher = { @@ -1861,7 +1861,7 @@ orderbooks: let telemetry = Telemetry::default(); let environment = build_environment(ManifestMap::new(), HashMap::new(), 1, 0, telemetry.clone()); - let settings = single_orderbook_settings_yaml(); + let settings = single_raindex_settings_yaml(); let mut runner = ClientRunner::with_environment(settings, environment, AlwaysLeadership).unwrap(); diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/native.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/native.rs index 4a7b7c9393..bb3d12fde5 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/native.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/native.rs @@ -386,7 +386,7 @@ mod tests { #[test] fn start_returns_error_for_empty_settings() { let settings = ParsedRunnerSettings { - orderbooks: HashMap::new(), + raindexes: HashMap::new(), syncs: HashMap::new(), }; let result = start( diff --git a/crates/common/src/raindex_client/local_db/pipeline/status/mod.rs b/crates/common/src/raindex_client/local_db/pipeline/status/mod.rs index 8664843acc..6af276d692 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/status/mod.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/status/mod.rs @@ -34,12 +34,12 @@ mod tests { "Computing sync window" ); assert_eq!( - SyncPhase::FetchingOrderbookLogs.to_message(), - "Fetching orderbook logs" + SyncPhase::FetchingRaindexLogs.to_message(), + "Fetching raindex logs" ); assert_eq!( - SyncPhase::DecodingOrderbookLogs.to_message(), - "Decoding orderbook logs" + SyncPhase::DecodingRaindexLogs.to_message(), + "Decoding raindex logs" ); assert_eq!( SyncPhase::FetchingStoreLogs.to_message(), @@ -69,7 +69,7 @@ mod tests { } #[test] - fn orderbook_sync_status_syncing_sets_correct_fields() { + fn raindex_sync_status_syncing_sets_correct_fields() { let ob_id = test_ob_id(); let status = RaindexSyncStatus::syncing(ob_id.clone(), SyncPhase::FetchingLatestBlock); @@ -84,7 +84,7 @@ mod tests { } #[test] - fn orderbook_sync_status_active_with_leader_sets_correct_fields() { + fn raindex_sync_status_active_with_leader_sets_correct_fields() { let ob_id = test_ob_id(); let status = RaindexSyncStatus::active(ob_id.clone(), SchedulerState::Leader); @@ -96,7 +96,7 @@ mod tests { } #[test] - fn orderbook_sync_status_active_with_not_leader_sets_correct_fields() { + fn raindex_sync_status_active_with_not_leader_sets_correct_fields() { let ob_id = test_ob_id(); let status = RaindexSyncStatus::active(ob_id.clone(), SchedulerState::NotLeader); @@ -108,7 +108,7 @@ mod tests { } #[test] - fn orderbook_sync_status_failure_sets_correct_fields() { + fn raindex_sync_status_failure_sets_correct_fields() { let ob_id = test_ob_id(); let error_msg = "RPC connection failed".to_string(); let status = RaindexSyncStatus::failure(ob_id.clone(), error_msg.clone()); @@ -121,7 +121,7 @@ mod tests { } #[test] - fn orderbook_sync_status_new_with_all_fields() { + fn raindex_sync_status_new_with_all_fields() { let ob_id = test_ob_id(); let status = RaindexSyncStatus::new( ob_id.clone(), diff --git a/crates/common/src/raindex_client/local_db/pipeline/status/native.rs b/crates/common/src/raindex_client/local_db/pipeline/status/native.rs index 90b386f04e..8cb21156c4 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/status/native.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/status/native.rs @@ -43,7 +43,7 @@ impl StatusBus for TracingStatusBus { tracing::debug!( chain_id = chain_id, - orderbook = %ob_addr, + raindex = %ob_addr, key = key, phase = %phase.to_message(), "sync phase" diff --git a/crates/common/src/raindex_client/local_db/query/fetch_order_trades.rs b/crates/common/src/raindex_client/local_db/query/fetch_order_trades.rs index 0343671b7b..e868080221 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_order_trades.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_order_trades.rs @@ -30,14 +30,14 @@ mod wasm_tests { #[wasm_bindgen_test] async fn wrapper_uses_builder_sql_exactly() { let chain_id = 111; - let orderbook = Address::from([0x77; 20]); + let raindex = Address::from([0x77; 20]); let order_hash = b256!("0x000000000000000000000000000000000000000000000000000000000000abcd"); let start = Some(100); let end = Some(200); let expected_stmt = build_fetch_order_trades_stmt( - &RaindexIdentifier::new(chain_id, orderbook), + &RaindexIdentifier::new(chain_id, raindex), order_hash.clone(), start, end, @@ -53,7 +53,7 @@ mod wasm_tests { let res = super::fetch_order_trades( &exec, - &RaindexIdentifier::new(chain_id, orderbook), + &RaindexIdentifier::new(chain_id, raindex), order_hash, start, end, diff --git a/crates/common/src/raindex_client/local_db/query/fetch_order_trades_count.rs b/crates/common/src/raindex_client/local_db/query/fetch_order_trades_count.rs index 3edb6fb739..7ee5dc9a3c 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_order_trades_count.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_order_trades_count.rs @@ -36,9 +36,9 @@ mod wasm_tests { let start = Some(10); let end = Some(20); - let orderbook = Address::from([0x88; 20]); + let raindex = Address::from([0x88; 20]); let expected_stmt = build_fetch_trade_count_stmt( - &RaindexIdentifier::new(1, orderbook), + &RaindexIdentifier::new(1, raindex), order_hash.clone(), start, end, @@ -56,7 +56,7 @@ mod wasm_tests { let res = super::fetch_order_trades_count( &exec, - &RaindexIdentifier::new(1, orderbook), + &RaindexIdentifier::new(1, raindex), order_hash, start, end, diff --git a/crates/common/src/raindex_client/local_db/query/fetch_order_vaults_volume.rs b/crates/common/src/raindex_client/local_db/query/fetch_order_vaults_volume.rs index 804d28f7e7..cfcef3325a 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_order_vaults_volume.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_order_vaults_volume.rs @@ -31,14 +31,14 @@ mod wasm_tests { #[wasm_bindgen_test] async fn wrapper_uses_builder_sql_exactly() { let chain_id = 111; - let orderbook = Address::from([0x77; 20]); + let raindex = Address::from([0x77; 20]); let order_hash = b256!("0x000000000000000000000000000000000000000000000000000000000000abcd"); let start = Some(100); let end = Some(200); let expected_stmt = build_fetch_order_vaults_volume_stmt( - &RaindexIdentifier::new(chain_id, orderbook), + &RaindexIdentifier::new(chain_id, raindex), order_hash, start, end, @@ -54,7 +54,7 @@ mod wasm_tests { let res = super::fetch_order_vaults_volume( &exec, - &RaindexIdentifier::new(chain_id, orderbook), + &RaindexIdentifier::new(chain_id, raindex), order_hash, start, end, diff --git a/crates/common/src/raindex_client/local_db/query/fetch_orders.rs b/crates/common/src/raindex_client/local_db/query/fetch_orders.rs index 955d173ce4..5169a01634 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_orders.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_orders.rs @@ -50,8 +50,8 @@ mod tests { fn from_get_orders_filters_builds_args() { let owner = Address::from_str("0x0123456789ABCDEF0123456789ABCDEF01234567").unwrap(); let token = Address::from_str("0x89ABCDEF0123456789ABCDEF0123456789ABCDEF").unwrap(); - let orderbook1 = address!("0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); - let orderbook2 = address!("0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"); + let raindex1 = address!("0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); + let raindex2 = address!("0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"); let filters = GetOrdersFilters { owners: vec![owner], active: Some(true), @@ -62,7 +62,7 @@ mod tests { inputs: Some(vec![token]), outputs: None, }), - raindex_addresses: Some(vec![orderbook1, orderbook2]), + raindex_addresses: Some(vec![raindex1, raindex2]), }; let args: FetchOrdersArgs = filters.into(); assert!(matches!(args.filter, FetchOrdersActiveFilter::Active)); @@ -82,8 +82,8 @@ mod tests { )) ); assert_eq!(args.raindex_addresses.len(), 2); - assert_eq!(args.raindex_addresses[0], orderbook1); - assert_eq!(args.raindex_addresses[1], orderbook2); + assert_eq!(args.raindex_addresses[0], raindex1); + assert_eq!(args.raindex_addresses[1], raindex2); } #[test] @@ -145,7 +145,7 @@ mod tests { "0x0000000000000000000000000000000000000000000000000000000000000001" )); args.chain_ids = vec![137]; - args.raindex_addresses = vec![orderbook()]; + args.raindex_addresses = vec![raindex()]; let expected_stmt = build_fetch_orders_stmt(&args).unwrap(); diff --git a/crates/common/src/raindex_client/local_db/query/fetch_store_addresses.rs b/crates/common/src/raindex_client/local_db/query/fetch_store_addresses.rs index c8a2788767..aac6249674 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_store_addresses.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_store_addresses.rs @@ -22,8 +22,8 @@ mod wasm_tests { #[wasm_bindgen_test] async fn wrapper_uses_raw_sql_exactly() { - let orderbook = Address::from([0x55; 20]); - let expected_stmt = fetch_store_addresses_stmt(&RaindexIdentifier::new(1, orderbook)); + let raindex = Address::from([0x55; 20]); + let expected_stmt = fetch_store_addresses_stmt(&RaindexIdentifier::new(1, raindex)); let store = Rc::new(RefCell::new(( String::new(), wasm_bindgen::JsValue::UNDEFINED, @@ -31,7 +31,7 @@ mod wasm_tests { let callback = create_sql_capturing_callback("[]", store.clone()); let exec = JsCallbackExecutor::from_ref(&callback); let res = - super::fetch_store_addresses(&exec, &RaindexIdentifier::new(1, orderbook)).await; + super::fetch_store_addresses(&exec, &RaindexIdentifier::new(1, raindex)).await; assert!(res.is_ok()); assert_eq!(store.borrow().clone().0, expected_stmt.sql); } diff --git a/crates/common/src/raindex_client/local_db/query/fetch_transaction_by_hash.rs b/crates/common/src/raindex_client/local_db/query/fetch_transaction_by_hash.rs index f263f87007..726cbad3bd 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_transaction_by_hash.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_transaction_by_hash.rs @@ -28,9 +28,9 @@ mod wasm_tests { #[wasm_bindgen_test] async fn wrapper_uses_builder_sql_exactly() { let tx_hash = b256!("0x0000000000000000000000000000000000000000000000000000000000000abc"); - let orderbook = Address::from([0x51; 20]); + let raindex = Address::from([0x51; 20]); let expected_stmt = - build_fetch_transaction_by_hash_stmt(&RaindexIdentifier::new(1, orderbook), tx_hash); + build_fetch_transaction_by_hash_stmt(&RaindexIdentifier::new(1, raindex), tx_hash); let store = Rc::new(RefCell::new((String::new(), JsValue::UNDEFINED))); let callback = create_sql_capturing_callback("[]", store.clone()); @@ -38,7 +38,7 @@ mod wasm_tests { let res = super::fetch_transaction_by_hash( &exec, - &RaindexIdentifier::new(1, orderbook), + &RaindexIdentifier::new(1, raindex), tx_hash, ) .await; @@ -49,10 +49,10 @@ mod wasm_tests { #[wasm_bindgen_test] async fn wrapper_returns_rows_when_present() { let tx_hash = b256!("0x0000000000000000000000000000000000000000000000000000000000000abc"); - let orderbook = address!("0x5151515151515151515151515151515151515151"); + let raindex = address!("0x5151515151515151515151515151515151515151"); let sender = address!("0x1111111111111111111111111111111111111111"); let expected_stmt = - build_fetch_transaction_by_hash_stmt(&RaindexIdentifier::new(1, orderbook), tx_hash); + build_fetch_transaction_by_hash_stmt(&RaindexIdentifier::new(1, raindex), tx_hash); let row_json = format!( r#"[{{ @@ -73,7 +73,7 @@ mod wasm_tests { let res = super::fetch_transaction_by_hash( &exec, - &RaindexIdentifier::new(1, orderbook), + &RaindexIdentifier::new(1, raindex), tx_hash, ) .await; diff --git a/crates/common/src/raindex_client/local_db/query/fetch_vault_balance_changes.rs b/crates/common/src/raindex_client/local_db/query/fetch_vault_balance_changes.rs index 2ab1f4664c..fe416409d3 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_vault_balance_changes.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_vault_balance_changes.rs @@ -37,10 +37,10 @@ mod wasm_tests { async fn wrapper_uses_builder_sql_exactly() { let vault_id = U256::from(1); let token = address!("0x00000000000000000000000000000000000000aa"); - let orderbook = Address::from([0x51; 20]); + let raindex = Address::from([0x51; 20]); let owner = address!("0x00000000000000000000000000000000000000f1"); let expected_stmt = build_fetch_balance_changes_stmt( - &RaindexIdentifier::new(1, orderbook), + &RaindexIdentifier::new(1, raindex), vault_id, token, owner, @@ -57,7 +57,7 @@ mod wasm_tests { let res = super::fetch_vault_balance_changes( &exec, - &RaindexIdentifier::new(1, orderbook), + &RaindexIdentifier::new(1, raindex), vault_id, token, owner, @@ -72,10 +72,10 @@ mod wasm_tests { async fn wrapper_returns_rows_when_present() { let vault_id = U256::from(1); let token = address!("0x00000000000000000000000000000000000000bb"); - let orderbook = Address::from([0x61; 20]); + let raindex = Address::from([0x61; 20]); let owner = address!("0x0000000000000000000000000000000000000011"); let expected_stmt = build_fetch_balance_changes_stmt( - &RaindexIdentifier::new(1, orderbook), + &RaindexIdentifier::new(1, raindex), vault_id, token, owner, @@ -105,7 +105,7 @@ mod wasm_tests { let res = super::fetch_vault_balance_changes( &exec, - &RaindexIdentifier::new(1, orderbook), + &RaindexIdentifier::new(1, raindex), vault_id, token, owner, @@ -122,7 +122,7 @@ mod wasm_tests { async fn wrapper_uses_builder_sql_with_filter_types() { let vault_id = U256::from(1); let token = address!("0x00000000000000000000000000000000000000aa"); - let orderbook = Address::from([0x51; 20]); + let raindex = Address::from([0x51; 20]); let owner = address!("0x00000000000000000000000000000000000000f1"); let filter_types = vec![ VaultBalanceChangeFilter::Deposit, @@ -130,7 +130,7 @@ mod wasm_tests { ]; let filter_kinds: Vec<_> = filter_types.iter().map(|f| f.to_kind()).collect(); let expected_stmt = build_fetch_balance_changes_stmt( - &RaindexIdentifier::new(1, orderbook), + &RaindexIdentifier::new(1, raindex), vault_id, token, owner, @@ -147,7 +147,7 @@ mod wasm_tests { let res = super::fetch_vault_balance_changes( &exec, - &RaindexIdentifier::new(1, orderbook), + &RaindexIdentifier::new(1, raindex), vault_id, token, owner, diff --git a/crates/common/src/raindex_client/local_db/query/fetch_vaults.rs b/crates/common/src/raindex_client/local_db/query/fetch_vaults.rs index a72a0188a7..8724d54a88 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_vaults.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_vaults.rs @@ -39,13 +39,13 @@ mod tests { fn from_filters_builds_args() { let owner = address!("0x0123456789ABCDEF0123456789ABCDEF01234567"); let token = address!("0x89ABCDEF0123456789ABCDEF0123456789ABCDEF"); - let orderbook1 = address!("0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); - let orderbook2 = address!("0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"); + let raindex1 = address!("0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); + let raindex2 = address!("0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"); let filters = GetVaultsFilters { owners: vec![owner], hide_zero_balance: true, tokens: Some(vec![token]), - raindex_addresses: Some(vec![orderbook1, orderbook2]), + raindex_addresses: Some(vec![raindex1, raindex2]), only_active_orders: false, }; let args = FetchVaultsArgs::from_filters(filters); @@ -59,8 +59,8 @@ mod tests { ); assert!(args.hide_zero_balance); assert_eq!(args.raindex_addresses.len(), 2); - assert_eq!(args.raindex_addresses[0], orderbook1); - assert_eq!(args.raindex_addresses[1], orderbook2); + assert_eq!(args.raindex_addresses[0], raindex1); + assert_eq!(args.raindex_addresses[1], raindex2); assert!(!args.only_active_orders); } diff --git a/crates/common/src/raindex_client/local_db/state.rs b/crates/common/src/raindex_client/local_db/state.rs index 2d3caf92d5..1fb71ae62c 100644 --- a/crates/common/src/raindex_client/local_db/state.rs +++ b/crates/common/src/raindex_client/local_db/state.rs @@ -414,7 +414,7 @@ local-db-sync: finality-depth: 12 bootstrap-block-threshold: 1000 sync-interval-ms: 5000 -orderbooks: +raindexes: ob-a: address: 0x00000000000000000000000000000000000000a1 network: anvil @@ -442,7 +442,7 @@ networks: chain-id: 42161 subgraphs: anvil: https://subgraph.example/anvil -orderbooks: +raindexes: ob-a: address: 0x00000000000000000000000000000000000000a1 network: anvil diff --git a/crates/common/src/raindex_client/mod.rs b/crates/common/src/raindex_client/mod.rs index 2aa5e45961..661d2117c2 100644 --- a/crates/common/src/raindex_client/mod.rs +++ b/crates/common/src/raindex_client/mod.rs @@ -24,8 +24,8 @@ use raindex_app_settings::{ }, }; use raindex_subgraph_client::{ - types::order_detail_traits::OrderDetailError, MultiSubgraphArgs, OrderbookSubgraphClient, - OrderbookSubgraphClientError, + types::order_detail_traits::OrderDetailError, MultiSubgraphArgs, RaindexSubgraphClient, + RaindexSubgraphClientError, }; use serde::{Deserialize, Serialize}; #[cfg(not(target_family = "wasm"))] @@ -259,11 +259,11 @@ impl RaindexClient { pub fn get_raindex_subgraph_client( &self, raindex_address: Address, - ) -> Result { + ) -> Result { let raindex = self .raindex_yaml .get_raindex_by_address(raindex_address)?; - Ok(OrderbookSubgraphClient::new(raindex.subgraph.url.clone())) + Ok(RaindexSubgraphClient::new(raindex.subgraph.url.clone())) } fn get_rpc_urls_for_chain(&self, chain_id: u32) -> Result, RaindexError> { @@ -382,7 +382,7 @@ pub enum RaindexError { #[error(transparent)] FromHexError(#[from] FromHexError), #[error(transparent)] - OrderbookSubgraphClientError(#[from] OrderbookSubgraphClientError), + RaindexSubgraphClientError(#[from] RaindexSubgraphClientError), #[error(transparent)] TryDecodeRainlangSourceError(#[from] TryDecodeRainlangSourceError), #[error(transparent)] @@ -416,7 +416,7 @@ pub enum RaindexError { #[error(transparent)] AddOrderArgsError(#[from] AddOrderArgsError), #[error(transparent)] - OrderbookQuoteError(#[from] raindex_quote::error::Error), + RaindexQuoteError(#[from] raindex_quote::error::Error), #[error("Missing subgraph {0} for order {1}")] SubgraphNotFound(String, String), #[error("Invalid vault balance change type: {0}")] @@ -537,7 +537,7 @@ impl RaindexError { err ) } - RaindexError::OrderbookSubgraphClientError(err) => { + RaindexError::RaindexSubgraphClientError(err) => { format!("Failed to query subgraph: {}. Check network connection and subgraph availability.", err) } RaindexError::TryDecodeRainlangSourceError(err) => { @@ -595,7 +595,7 @@ impl RaindexError { RaindexError::AddOrderArgsError(e) => { format!("Failed to prepare the add order calldata: {}", e) } - RaindexError::OrderbookQuoteError(err) => { + RaindexError::RaindexQuoteError(err) => { format!("Failed to get order quote: {}", err) } RaindexError::SubgraphNotFound(subgraph, order) => { diff --git a/crates/common/src/raindex_client/order_quotes.rs b/crates/common/src/raindex_client/order_quotes.rs index c83e532ede..e7dabd7d59 100644 --- a/crates/common/src/raindex_client/order_quotes.rs +++ b/crates/common/src/raindex_client/order_quotes.rs @@ -269,7 +269,7 @@ mod tests { mod quote_non_wasm_tests { use super::*; use crate::local_db::RaindexIdentifier; - use crate::raindex_client::tests::{get_test_yaml, CHAIN_ID_1_ORDERBOOK_ADDRESS}; + use crate::raindex_client::tests::{get_test_yaml, CHAIN_ID_1_RAINDEX_ADDRESS}; use alloy::hex::encode_prefixed; use alloy::primitives::{b256, Address, U256}; use alloy::{sol, sol_types::SolValue}; @@ -311,8 +311,8 @@ mod tests { "symbol": "sFLR", "decimals": "18" }, - "orderbook": { - "id": CHAIN_ID_1_ORDERBOOK_ADDRESS + "raindex": { + "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], @@ -332,16 +332,16 @@ mod tests { "symbol": "WFLR", "decimals": "18" }, - "orderbook": { - "id": CHAIN_ID_1_ORDERBOOK_ADDRESS + "raindex": { + "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] }, ], - "orderbook": { - "id": CHAIN_ID_1_ORDERBOOK_ADDRESS + "raindex": { + "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "active": true, "timestampAdded": "1739448802", @@ -410,7 +410,7 @@ mod tests { .get_order_by_hash( &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) @@ -510,7 +510,7 @@ mod tests { .get_order_by_hash( &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) @@ -578,7 +578,7 @@ mod tests { .get_order_by_hash( &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) @@ -671,7 +671,7 @@ mod tests { .get_order_by_hash( &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) diff --git a/crates/common/src/raindex_client/orders.rs b/crates/common/src/raindex_client/orders.rs index f5b508cd4c..70faec62ad 100644 --- a/crates/common/src/raindex_client/orders.rs +++ b/crates/common/src/raindex_client/orders.rs @@ -36,12 +36,12 @@ use rain_metadata::{KnownMagic, RainMetaDocumentV1Item}; use raindex_subgraph_client::{ types::{ common::{ - SgBigInt, SgBytes, SgOrder, SgOrderAsIO, SgOrderbook, SgOrdersListFilterArgs, + SgBigInt, SgBytes, SgOrder, SgOrderAsIO, SgRaindex, SgOrdersListFilterArgs, SgOrdersTokensFilterArgs, SgVault, }, Id, }, - MultiOrderbookSubgraphClient, OrderbookSubgraphClient, OrderbookSubgraphClientError, + MultiRaindexSubgraphClient, RaindexSubgraphClient, RaindexSubgraphClientError, SgPaginationArgs, }; use serde::{Deserialize, Serialize}; @@ -462,7 +462,7 @@ impl RaindexOrder { ClientRef::clone(&self.raindex_client) } #[wasm_export(skip)] - pub fn get_raindex_subgraph_client(&self) -> Result { + pub fn get_raindex_subgraph_client(&self) -> Result { self.raindex_client.get_raindex_subgraph_client(self.raindex) } #[wasm_export(skip)] @@ -1005,7 +1005,7 @@ impl OrdersDataSource for SubgraphOrders<'_> { let raindex_client = ClientRef::new(self.client.clone()); let multi_subgraph_args = self.client.get_multi_subgraph_args(chain_ids)?; - let client = MultiOrderbookSubgraphClient::new( + let client = MultiRaindexSubgraphClient::new( multi_subgraph_args.values().flatten().cloned().collect(), ); @@ -1066,7 +1066,7 @@ impl OrdersDataSource for SubgraphOrders<'_> { .await { Ok(order) => order, - Err(OrderbookSubgraphClientError::Empty) => return Ok(None), + Err(RaindexSubgraphClientError::Empty) => return Ok(None), Err(err) => return Err(err.into()), }; let order = RaindexOrder::try_from_sg_order(raindex_client, ob_id.chain_id, order, None)?; @@ -1328,7 +1328,7 @@ impl TryFrom for SgOrdersListFilterArgs { .order_hash .map(|order_hash| SgBytes(order_hash.to_string())), tokens: tokens.flatten(), - orderbooks: filters + raindexes: filters .raindex_addresses .map(|addrs| { addrs @@ -1485,7 +1485,7 @@ impl RaindexOrder { .into_iter() .map(|v| v.into_sg_vault()) .collect::, RaindexError>>()?, - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes(self.raindex().to_string()), }, active: self.active(), @@ -1537,7 +1537,7 @@ mod tests { ContentEncoding, ContentLanguage, ContentType, KnownMagic, RainMetaDocumentV1Item, }; use raindex_subgraph_client::types::common::{ - SgAddOrder, SgBigInt, SgBytes, SgErc20, SgOrderAsIO, SgOrderbook, SgTransaction, + SgAddOrder, SgBigInt, SgBytes, SgErc20, SgOrderAsIO, SgRaindex, SgTransaction, SgVault, }; use raindex_subgraph_client::utils::float::*; @@ -2044,7 +2044,7 @@ mod tests { "symbol": "sFLR", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "ordersAsOutput": [ @@ -2072,7 +2072,7 @@ mod tests { "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [], - "orderbook": { + "raindex": { "id": "0x0000000000000000000000000000000000000000" } } @@ -2090,7 +2090,7 @@ mod tests { "symbol": "WFLR", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "ordersAsOutput": [], @@ -2118,12 +2118,12 @@ mod tests { "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [], - "orderbook": { + "raindex": { "id": "0x0000000000000000000000000000000000000000" } } ], - "orderbook": { + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "active": true, @@ -2162,7 +2162,7 @@ mod tests { symbol: Some("sFLR".to_string()), decimals: Some(SgBigInt("18".to_string())), }, - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("0xcee8cd002f151a536394e564b84076c41bbbcd4d".to_string()), }, orders_as_output: vec![SgOrderAsIO { @@ -2188,7 +2188,7 @@ mod tests { orders_as_output: vec![], orders_as_input: vec![], balance_changes: vec![], - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("0x0000000000000000000000000000000000000000".to_string()), } }], @@ -2204,7 +2204,7 @@ mod tests { symbol: Some("WFLR".to_string()), decimals: Some(SgBigInt("18".to_string())), }, - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("0xcee8cd002f151a536394e564b84076c41bbbcd4d".to_string()), }, orders_as_output: vec![], @@ -2230,11 +2230,11 @@ mod tests { orders_as_output: vec![], orders_as_input: vec![], balance_changes: vec![], - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("0x0000000000000000000000000000000000000000".to_string()), } }], - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes(CHAIN_ID_1_RAINDEX_ADDRESS.to_string()), }, active: true, @@ -2293,7 +2293,7 @@ mod tests { "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [], - "orderbook": { + "raindex": { "id": "0x0000000000000000000000000000000000000000" } } @@ -2314,7 +2314,7 @@ mod tests { "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [], - "orderbook": { + "raindex": { "id": "0x0000000000000000000000000000000000000000" } } @@ -2332,7 +2332,7 @@ mod tests { ], "meta": null, "timestampAdded": "0", - "orderbook": { + "raindex": { "id": "0x0000000000000000000000000000000000000000" }, "trades": [], @@ -2647,7 +2647,7 @@ mod tests { "owner": "0xf08bcbce72f62c95dcb7c07dcb5ed26acfcfbc11", "outputs": [], "inputs": [], - "orderbook": { + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "active": true, @@ -2874,7 +2874,7 @@ mod tests { ], "meta": null, "timestampAdded": "0", - "orderbook": { + "raindex": { "id": "0x0987654321098765432109876543210987654321" }, "trades": [], @@ -2991,7 +2991,7 @@ mod tests { "id": "0x557147dd0daa80d5beff0023fe6a3505469b2b8c4406ce1ab873e1a652572dd4", "orderHash": "0x557147dd0daa80d5beff0023fe6a3505469b2b8c4406ce1ab873e1a652572dd4" }, - "orderbook": { + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "inputVaultBalanceChange": { @@ -3007,7 +3007,7 @@ mod tests { "timestamp": "1632000000", "blockNumber": "0" }, - "orderbook": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "vault": { "id": "0x1d80c49bbbcd1c0911346656b529df9e5c2f783d", "vaultId": "0x1234", @@ -3038,7 +3038,7 @@ mod tests { "timestamp": "1632000000", "blockNumber": "0" }, - "orderbook": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "vault": { "id": "0x12e605bc104e93b45e1ad99f9e555f659051c2bb", "vaultId": "0x5678", @@ -3386,7 +3386,7 @@ mod tests { fn make_test_calldata_result() -> TakeOrdersCalldataResult { use crate::raindex_client::take_orders::result::TakeOrdersInfoData; - let orderbook = Address::from([0x11u8; 20]); + let raindex = Address::from([0x11u8; 20]); let calldata = Bytes::from(vec![0x01, 0x02, 0x03, 0x04]); let effective_price = Float::parse("1.5".to_string()).unwrap(); let prices = vec![ @@ -3397,7 +3397,7 @@ mod tests { let max_sell_cap = Float::parse("200".to_string()).unwrap(); TakeOrdersCalldataResult::ready(TakeOrdersInfoData { - orderbook, + raindex, calldata, effective_price, prices, diff --git a/crates/common/src/raindex_client/orders_list.rs b/crates/common/src/raindex_client/orders_list.rs index e3478181e0..dda1bff8fd 100644 --- a/crates/common/src/raindex_client/orders_list.rs +++ b/crates/common/src/raindex_client/orders_list.rs @@ -51,7 +51,7 @@ impl RaindexOrders { mod tests { use super::*; use crate::local_db::RaindexIdentifier; - use crate::raindex_client::tests::{get_test_yaml, CHAIN_ID_1_ORDERBOOK_ADDRESS}; + use crate::raindex_client::tests::{get_test_yaml, CHAIN_ID_1_RAINDEX_ADDRESS}; use alloy::primitives::{b256, Address}; use httpmock::MockServer; use serde_json::json; @@ -78,7 +78,7 @@ mod tests { "address": "0x12e605bc104e93b45e1ad99f9e555f659051c2bb", "name": "sFLR", "symbol": "sFLR", "decimals": "18" }, - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] }], "inputs": [{ @@ -91,10 +91,10 @@ mod tests { "address": "0x1d80c49bbbcd1c0911346656b529df9e5c2f783d", "name": "WFLR", "symbol": "WFLR", "decimals": "18" }, - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] }], - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "active": true, "timestampAdded": "0", "meta": null, "addEvents": [], "trades": [], "removeEvents": [] }] @@ -118,7 +118,7 @@ mod tests { .get_order_by_hash( &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) diff --git a/crates/common/src/raindex_client/remove_orders.rs b/crates/common/src/raindex_client/remove_orders.rs index cc893b5426..996696ce20 100644 --- a/crates/common/src/raindex_client/remove_orders.rs +++ b/crates/common/src/raindex_client/remove_orders.rs @@ -140,8 +140,8 @@ impl RaindexClient { .await { Ok(orders) => orders, - Err(RaindexError::OrderbookSubgraphClientError( - raindex_subgraph_client::OrderbookSubgraphClientError::Empty, + Err(RaindexError::RaindexSubgraphClientError( + raindex_subgraph_client::RaindexSubgraphClientError::Empty, )) => return Err(PollError::Empty), Err(e) => return Err(PollError::Inner(e)), }; @@ -175,10 +175,10 @@ impl RaindexClient { #[wasm_export] impl RaindexOrder { - /// Generates ABI-encoded calldata for the `removeOrder2()` function on the orderbook contract + /// Generates ABI-encoded calldata for the `removeOrder2()` function on the raindex contract /// /// Takes an existing order from the subgraph and creates the transaction calldata needed - /// to remove it from the orderbook. The order must be active and owned by the caller. + /// to remove it from the raindex. The order must be active and owned by the caller. /// /// ## Examples /// @@ -230,7 +230,7 @@ mod tests { local_db::RaindexIdentifier, raindex_client::local_db::LocalDb, raindex_client::tests::{ - get_test_yaml, new_with_local_db, CHAIN_ID_1_ORDERBOOK_ADDRESS, + get_test_yaml, new_with_local_db, CHAIN_ID_1_RAINDEX_ADDRESS, }, }; use alloy::primitives::{b256, Address, Bytes, U256}; @@ -319,7 +319,7 @@ mod tests { "symbol": "sFLR", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "ordersAsOutput": [ @@ -346,7 +346,7 @@ mod tests { "symbol": "WFLR", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "ordersAsOutput": [], @@ -360,7 +360,7 @@ mod tests { "balanceChanges": [] } ], - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "active": true, @@ -409,7 +409,7 @@ mod tests { let res = raindex_client .get_remove_orders_for_transaction( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), None, None, @@ -577,8 +577,8 @@ mod tests { "owner": "0xf08bcbce72f62c95dcb7c07dcb5ed26acfcfbc11", "outputs": [], "inputs": [], - "orderbook": { - "id": CHAIN_ID_1_ORDERBOOK_ADDRESS + "raindex": { + "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "active": true, "timestampAdded": "1739448802", @@ -617,7 +617,7 @@ mod tests { .get_order_by_hash( &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) @@ -655,7 +655,7 @@ mod tests { let res = raindex_client .get_remove_orders_for_transaction( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), Some(DEFAULT_REMOVE_ORDER_POLL_ATTEMPTS), Some(10), @@ -690,7 +690,7 @@ mod tests { let err = raindex_client .get_remove_orders_for_transaction( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), Some(DEFAULT_REMOVE_ORDER_POLL_ATTEMPTS), Some(10), diff --git a/crates/common/src/raindex_client/take_orders/approval.rs b/crates/common/src/raindex_client/take_orders/approval.rs index a47ffd71c5..8f2c8c9153 100644 --- a/crates/common/src/raindex_client/take_orders/approval.rs +++ b/crates/common/src/raindex_client/take_orders/approval.rs @@ -28,14 +28,14 @@ pub async fn check_approval_needed( let required_u256 = max_sell_cap.to_fixed_decimal_lossy(decimals)?.0; let allowance_result = - check_taker_allowance(&erc20, params.taker, params.orderbook, required_u256) + check_taker_allowance(&erc20, params.taker, params.raindex, required_u256) .await .map_err(|e| RaindexError::PreflightError(e.to_string()))?; if allowance_result.needs_approval { Ok(Some(build_approval_result( params.sell_token, - params.orderbook, + params.raindex, max_sell_cap, decimals, )?)) @@ -181,7 +181,7 @@ mod local_evm_tests { let token = local_evm .deploy_new_token("TestToken", "TT", 18, U256::MAX, owner) .await; - let orderbook = *local_evm.orderbook.address(); + let raindex = *local_evm.raindex.address(); token .transfer( @@ -202,7 +202,7 @@ mod local_evm_tests { rpc_urls: vec![rpc_url], sell_token: *token.address(), taker, - orderbook, + raindex, mode: make_mode(TakeOrdersMode::SpendUpTo, "100"), price_cap: Float::parse("2".to_string()).unwrap(), }; @@ -227,8 +227,8 @@ mod local_evm_tests { ); assert_eq!( approval_info.spender(), - orderbook, - "spender should be orderbook" + raindex, + "spender should be raindex" ); assert!( !approval_info.calldata().is_empty(), @@ -244,7 +244,7 @@ mod local_evm_tests { let token = local_evm .deploy_new_token("TestToken", "TT", 18, U256::MAX, owner) .await; - let orderbook = *local_evm.orderbook.address(); + let raindex = *local_evm.raindex.address(); token .transfer( @@ -260,7 +260,7 @@ mod local_evm_tests { .unwrap(); token - .approve(orderbook, U256::MAX) + .approve(raindex, U256::MAX) .from(taker) .send() .await @@ -275,7 +275,7 @@ mod local_evm_tests { rpc_urls: vec![rpc_url], sell_token: *token.address(), taker, - orderbook, + raindex, mode: make_mode(TakeOrdersMode::SpendUpTo, "100"), price_cap: Float::parse("2".to_string()).unwrap(), }; @@ -296,7 +296,7 @@ mod local_evm_tests { let token = local_evm .deploy_new_token("USDC", "USDC", 6, U256::MAX, owner) .await; - let orderbook = *local_evm.orderbook.address(); + let raindex = *local_evm.raindex.address(); token .transfer( @@ -317,7 +317,7 @@ mod local_evm_tests { rpc_urls: vec![rpc_url], sell_token: *token.address(), taker, - orderbook, + raindex, mode: make_mode(TakeOrdersMode::SpendUpTo, "1.57126799999999998"), price_cap: Float::parse("1".to_string()).unwrap(), }; @@ -338,7 +338,7 @@ mod local_evm_tests { let token = local_evm .deploy_new_token("TestToken", "TT", 18, U256::MAX, owner) .await; - let orderbook = *local_evm.orderbook.address(); + let raindex = *local_evm.raindex.address(); token .transfer( @@ -355,7 +355,7 @@ mod local_evm_tests { token .approve( - orderbook, + raindex, U256::from(150u64) * U256::from(10).pow(U256::from(18)), ) .from(taker) @@ -372,7 +372,7 @@ mod local_evm_tests { rpc_urls: vec![rpc_url], sell_token: *token.address(), taker, - orderbook, + raindex, mode: make_mode(TakeOrdersMode::BuyUpTo, "100"), price_cap: Float::parse("2".to_string()).unwrap(), }; diff --git a/crates/common/src/raindex_client/take_orders/e2e_tests.rs b/crates/common/src/raindex_client/take_orders/e2e_tests.rs index d173bb673b..ddc73a1eaa 100644 --- a/crates/common/src/raindex_client/take_orders/e2e_tests.rs +++ b/crates/common/src/raindex_client/take_orders/e2e_tests.rs @@ -4,17 +4,17 @@ use crate::raindex_client::RaindexClient; use crate::raindex_client::RaindexError; use crate::take_orders::TakeOrdersMode; use crate::test_helpers::dotrain::{ - create_dotrain_config_for_orderbook, create_dotrain_config_with_params, + create_dotrain_config_for_raindex, create_dotrain_config_with_params, create_dotrain_config_with_vault_and_ratio, }; use crate::test_helpers::local_evm::{ - approve_taker, create_vault, create_vault_for_orderbook, deposit_to_orderbook, - fund_and_approve_taker, fund_and_approve_taker_multi_orderbook, fund_standard_two_token_vault, - fund_taker, setup_multi_orderbook_test, setup_test as base_setup_test, standard_deposit_amount, + approve_taker, create_vault, create_vault_for_raindex, deposit_to_raindex, + fund_and_approve_taker, fund_and_approve_taker_multi_raindex, fund_standard_two_token_vault, + fund_taker, setup_multi_raindex_test, setup_test as base_setup_test, standard_deposit_amount, }; -use crate::test_helpers::orders::deploy::{deploy_order, deploy_order_to_orderbook}; +use crate::test_helpers::orders::deploy::{deploy_order, deploy_order_to_raindex}; use crate::test_helpers::subgraph::{ - create_sg_order_json, create_sg_order_json_with_orderbook, get_minimal_yaml_for_chain, + create_sg_order_json, create_sg_order_json_with_raindex, get_minimal_yaml_for_chain, get_multi_raindex_yaml, }; use alloy::network::TransactionBuilder; @@ -214,7 +214,7 @@ async fn test_get_take_orders_calldata_happy_path_returns_valid_config() { assert_eq!( result.raindex(), setup.raindex, - "Orderbook address should match" + "Raindex address should match" ); let decoded = takeOrders4Call::abi_decode(result.calldata()).expect("Should decode calldata"); @@ -858,7 +858,7 @@ async fn test_maximum_io_ratio_enforcement_with_worsened_on_chain_price() { let withdraw_tx = setup .local_evm - .orderbook + .raindex .withdraw4(setup.token2, vault_id_2, withdraw_amount, vec![]) .from(setup.owner) .into_transaction_request(); @@ -948,20 +948,20 @@ async fn test_maximum_io_ratio_enforcement_with_worsened_on_chain_price() { } #[tokio::test] -async fn test_cross_orderbook_selection_picks_best_book() { - let setup = setup_multi_orderbook_test().await; +async fn test_cross_raindex_selection_picks_best_book() { + let setup = setup_multi_raindex_test().await; let sg_server = MockServer::start_async().await; assert_ne!( setup.raindex_a, setup.raindex_b, - "Orderbook addresses should be different" + "Raindex addresses should be different" ); let vault_id_a = B256::from(U256::from(1u64)); let vault_id_b = B256::from(U256::from(2u64)); let deposit_amount = U256::from(10).pow(U256::from(22)); - deposit_to_orderbook( + deposit_to_raindex( &setup, setup.raindex_a, setup.token2, @@ -969,7 +969,7 @@ async fn test_cross_orderbook_selection_picks_best_book() { vault_id_a, ) .await; - deposit_to_orderbook( + deposit_to_raindex( &setup, setup.raindex_b, setup.token2, @@ -979,25 +979,25 @@ async fn test_cross_orderbook_selection_picks_best_book() { .await; let dotrain_a = - create_dotrain_config_for_orderbook(&setup, setup.raindex_a, "0x01", "5", "2"); + create_dotrain_config_for_raindex(&setup, setup.raindex_a, "0x01", "5", "2"); let (order_bytes_a, order_hash_a, _order_v4_a) = - deploy_order_to_orderbook(&setup, setup.raindex_a, dotrain_a).await; + deploy_order_to_raindex(&setup, setup.raindex_a, dotrain_a).await; let dotrain_b = - create_dotrain_config_for_orderbook(&setup, setup.raindex_b, "0x02", "8", "2"); + create_dotrain_config_for_raindex(&setup, setup.raindex_b, "0x02", "8", "2"); let (order_bytes_b, order_hash_b, order_v4_b) = - deploy_order_to_orderbook(&setup, setup.raindex_b, dotrain_b).await; + deploy_order_to_raindex(&setup, setup.raindex_b, dotrain_b).await; let vault_a_input = - create_vault_for_orderbook(vault_id_a, &setup, setup.raindex_a, &setup.token1_sg); + create_vault_for_raindex(vault_id_a, &setup, setup.raindex_a, &setup.token1_sg); let vault_a_output = - create_vault_for_orderbook(vault_id_a, &setup, setup.raindex_a, &setup.token2_sg); + create_vault_for_raindex(vault_id_a, &setup, setup.raindex_a, &setup.token2_sg); let vault_b_input = - create_vault_for_orderbook(vault_id_b, &setup, setup.raindex_b, &setup.token1_sg); + create_vault_for_raindex(vault_id_b, &setup, setup.raindex_b, &setup.token1_sg); let vault_b_output = - create_vault_for_orderbook(vault_id_b, &setup, setup.raindex_b, &setup.token2_sg); + create_vault_for_raindex(vault_id_b, &setup, setup.raindex_b, &setup.token2_sg); - let sg_order_a = create_sg_order_json_with_orderbook( + let sg_order_a = create_sg_order_json_with_raindex( &setup, setup.raindex_a, &order_bytes_a, @@ -1005,7 +1005,7 @@ async fn test_cross_orderbook_selection_picks_best_book() { vec![vault_a_input], vec![vault_a_output], ); - let sg_order_b = create_sg_order_json_with_orderbook( + let sg_order_b = create_sg_order_json_with_raindex( &setup, setup.raindex_b, &order_bytes_b, @@ -1034,7 +1034,7 @@ async fn test_cross_orderbook_selection_picks_best_book() { let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let taker = setup.local_evm.signer_wallets[1].default_signer().address(); - fund_and_approve_taker_multi_orderbook( + fund_and_approve_taker_multi_raindex( &setup, setup.token1, taker, @@ -1055,7 +1055,7 @@ async fn test_cross_orderbook_selection_picks_best_book() { price_cap: high_price_cap(), }) .await - .expect("Should succeed with orders from multiple orderbooks"); + .expect("Should succeed with orders from multiple raindexes"); assert!(result.is_ready(), "Expected Ready variant"); let result = result.take_orders_info().unwrap(); @@ -1065,30 +1065,30 @@ async fn test_cross_orderbook_selection_picks_best_book() { assert_eq!( result.raindex(), setup.raindex_b, - "Should select orderbook B (max_output=8 > max_output=5)" + "Should select raindex B (max_output=8 > max_output=5)" ); assert!( !config.orders.is_empty(), - "Should have at least one order from the winning orderbook" + "Should have at least one order from the winning raindex" ); for config_item in &config.orders { let config_order = &config_item.order; assert_eq!( config_order.owner, order_v4_b.owner, - "All orders should be from orderbook B" + "All orders should be from raindex B" ); assert_eq!( config_order.evaluable.bytecode, order_v4_b.evaluable.bytecode, - "All order bytecodes should match orderbook B's order" + "All order bytecodes should match raindex B's order" ); } let expected_ratio = Float::parse("2".to_string()).unwrap(); assert!( result.prices()[0].eq(expected_ratio).unwrap(), - "Price should be 2 (orderbook B's ratio)" + "Price should be 2 (raindex B's ratio)" ); let tolerance = Float::parse("0.0001".to_string()).unwrap(); @@ -1105,15 +1105,15 @@ async fn test_cross_orderbook_selection_picks_best_book() { } #[tokio::test] -async fn test_cross_orderbook_selection_flips_when_economics_flip() { - let setup = setup_multi_orderbook_test().await; +async fn test_cross_raindex_selection_flips_when_economics_flip() { + let setup = setup_multi_raindex_test().await; let sg_server = MockServer::start_async().await; let vault_id_a = B256::from(U256::from(1u64)); let vault_id_b = B256::from(U256::from(2u64)); let deposit_amount = U256::from(10).pow(U256::from(22)); - deposit_to_orderbook( + deposit_to_raindex( &setup, setup.raindex_a, setup.token2, @@ -1121,7 +1121,7 @@ async fn test_cross_orderbook_selection_flips_when_economics_flip() { vault_id_a, ) .await; - deposit_to_orderbook( + deposit_to_raindex( &setup, setup.raindex_b, setup.token2, @@ -1131,25 +1131,25 @@ async fn test_cross_orderbook_selection_flips_when_economics_flip() { .await; let dotrain_a = - create_dotrain_config_for_orderbook(&setup, setup.raindex_a, "0x01", "10", "2"); + create_dotrain_config_for_raindex(&setup, setup.raindex_a, "0x01", "10", "2"); let (order_bytes_a, order_hash_a, order_v4_a) = - deploy_order_to_orderbook(&setup, setup.raindex_a, dotrain_a).await; + deploy_order_to_raindex(&setup, setup.raindex_a, dotrain_a).await; let dotrain_b = - create_dotrain_config_for_orderbook(&setup, setup.raindex_b, "0x02", "3", "2"); + create_dotrain_config_for_raindex(&setup, setup.raindex_b, "0x02", "3", "2"); let (order_bytes_b, order_hash_b, _order_v4_b) = - deploy_order_to_orderbook(&setup, setup.raindex_b, dotrain_b).await; + deploy_order_to_raindex(&setup, setup.raindex_b, dotrain_b).await; let vault_a_input = - create_vault_for_orderbook(vault_id_a, &setup, setup.raindex_a, &setup.token1_sg); + create_vault_for_raindex(vault_id_a, &setup, setup.raindex_a, &setup.token1_sg); let vault_a_output = - create_vault_for_orderbook(vault_id_a, &setup, setup.raindex_a, &setup.token2_sg); + create_vault_for_raindex(vault_id_a, &setup, setup.raindex_a, &setup.token2_sg); let vault_b_input = - create_vault_for_orderbook(vault_id_b, &setup, setup.raindex_b, &setup.token1_sg); + create_vault_for_raindex(vault_id_b, &setup, setup.raindex_b, &setup.token1_sg); let vault_b_output = - create_vault_for_orderbook(vault_id_b, &setup, setup.raindex_b, &setup.token2_sg); + create_vault_for_raindex(vault_id_b, &setup, setup.raindex_b, &setup.token2_sg); - let sg_order_a = create_sg_order_json_with_orderbook( + let sg_order_a = create_sg_order_json_with_raindex( &setup, setup.raindex_a, &order_bytes_a, @@ -1157,7 +1157,7 @@ async fn test_cross_orderbook_selection_flips_when_economics_flip() { vec![vault_a_input], vec![vault_a_output], ); - let sg_order_b = create_sg_order_json_with_orderbook( + let sg_order_b = create_sg_order_json_with_raindex( &setup, setup.raindex_b, &order_bytes_b, @@ -1186,7 +1186,7 @@ async fn test_cross_orderbook_selection_flips_when_economics_flip() { let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let taker = setup.local_evm.signer_wallets[1].default_signer().address(); - fund_and_approve_taker_multi_orderbook( + fund_and_approve_taker_multi_raindex( &setup, setup.token1, taker, @@ -1214,7 +1214,7 @@ async fn test_cross_orderbook_selection_flips_when_economics_flip() { assert_eq!( result.raindex(), setup.raindex_a, - "Should select orderbook A (max_output=10 > max_output=3)" + "Should select raindex A (max_output=10 > max_output=3)" ); let decoded = takeOrders4Call::abi_decode(result.calldata()).expect("Should decode calldata"); @@ -1222,18 +1222,18 @@ async fn test_cross_orderbook_selection_flips_when_economics_flip() { assert!( !config.orders.is_empty(), - "Should have at least one order from the winning orderbook" + "Should have at least one order from the winning raindex" ); for config_item in &config.orders { let config_order = &config_item.order; assert_eq!( config_order.owner, order_v4_a.owner, - "All orders should be from orderbook A" + "All orders should be from raindex A" ); assert_eq!( config_order.evaluable.bytecode, order_v4_a.evaluable.bytecode, - "All order bytecodes should match orderbook A's order" + "All order bytecodes should match raindex A's order" ); } @@ -1241,21 +1241,21 @@ async fn test_cross_orderbook_selection_flips_when_economics_flip() { let min_expected = Float::parse("10".to_string()).unwrap(); assert!( actual_max_input.gte(min_expected).unwrap(), - "maximumIO should be at least 10 (orderbook A's max_output), got: {:?}", + "maximumIO should be at least 10 (raindex A's max_output), got: {:?}", actual_max_input.format() ); } #[tokio::test] -async fn test_cross_orderbook_economic_selection_prefers_best_yield() { - let setup = setup_multi_orderbook_test().await; +async fn test_cross_raindex_economic_selection_prefers_best_yield() { + let setup = setup_multi_raindex_test().await; let sg_server = MockServer::start_async().await; let vault_id_a = B256::from(U256::from(1u64)); let vault_id_b = B256::from(U256::from(2u64)); let deposit_amount = U256::from(10).pow(U256::from(22)); - deposit_to_orderbook( + deposit_to_raindex( &setup, setup.raindex_a, setup.token2, @@ -1263,7 +1263,7 @@ async fn test_cross_orderbook_economic_selection_prefers_best_yield() { vault_id_a, ) .await; - deposit_to_orderbook( + deposit_to_raindex( &setup, setup.raindex_b, setup.token2, @@ -1273,25 +1273,25 @@ async fn test_cross_orderbook_economic_selection_prefers_best_yield() { .await; let dotrain_a = - create_dotrain_config_for_orderbook(&setup, setup.raindex_a, "0x01", "5", "1"); + create_dotrain_config_for_raindex(&setup, setup.raindex_a, "0x01", "5", "1"); let (order_bytes_a, order_hash_a, order_v4_a) = - deploy_order_to_orderbook(&setup, setup.raindex_a, dotrain_a).await; + deploy_order_to_raindex(&setup, setup.raindex_a, dotrain_a).await; let dotrain_b = - create_dotrain_config_for_orderbook(&setup, setup.raindex_b, "0x02", "8", "1.5"); + create_dotrain_config_for_raindex(&setup, setup.raindex_b, "0x02", "8", "1.5"); let (order_bytes_b, order_hash_b, _order_v4_b) = - deploy_order_to_orderbook(&setup, setup.raindex_b, dotrain_b).await; + deploy_order_to_raindex(&setup, setup.raindex_b, dotrain_b).await; let vault_a_input = - create_vault_for_orderbook(vault_id_a, &setup, setup.raindex_a, &setup.token1_sg); + create_vault_for_raindex(vault_id_a, &setup, setup.raindex_a, &setup.token1_sg); let vault_a_output = - create_vault_for_orderbook(vault_id_a, &setup, setup.raindex_a, &setup.token2_sg); + create_vault_for_raindex(vault_id_a, &setup, setup.raindex_a, &setup.token2_sg); let vault_b_input = - create_vault_for_orderbook(vault_id_b, &setup, setup.raindex_b, &setup.token1_sg); + create_vault_for_raindex(vault_id_b, &setup, setup.raindex_b, &setup.token1_sg); let vault_b_output = - create_vault_for_orderbook(vault_id_b, &setup, setup.raindex_b, &setup.token2_sg); + create_vault_for_raindex(vault_id_b, &setup, setup.raindex_b, &setup.token2_sg); - let sg_order_a = create_sg_order_json_with_orderbook( + let sg_order_a = create_sg_order_json_with_raindex( &setup, setup.raindex_a, &order_bytes_a, @@ -1299,7 +1299,7 @@ async fn test_cross_orderbook_economic_selection_prefers_best_yield() { vec![vault_a_input], vec![vault_a_output], ); - let sg_order_b = create_sg_order_json_with_orderbook( + let sg_order_b = create_sg_order_json_with_raindex( &setup, setup.raindex_b, &order_bytes_b, @@ -1328,7 +1328,7 @@ async fn test_cross_orderbook_economic_selection_prefers_best_yield() { let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let taker = setup.local_evm.signer_wallets[1].default_signer().address(); - fund_and_approve_taker_multi_orderbook( + fund_and_approve_taker_multi_raindex( &setup, setup.token1, taker, @@ -1349,13 +1349,13 @@ async fn test_cross_orderbook_economic_selection_prefers_best_yield() { price_cap: high_price_cap(), }) .await - .expect("Should succeed with orders from multiple orderbooks"); + .expect("Should succeed with orders from multiple raindexes"); assert!(result.is_ready(), "Expected Ready variant"); let result = result.take_orders_info().unwrap(); assert_eq!( result.raindex(), setup.raindex_a, - "Should select orderbook A (can fill 5 buy at ratio 1.0) over B (can fill 5 buy but at worse price 1.5)" + "Should select raindex A (can fill 5 buy at ratio 1.0) over B (can fill 5 buy but at worse price 1.5)" ); let decoded = takeOrders4Call::abi_decode(result.calldata()).expect("Should decode calldata"); @@ -1363,30 +1363,30 @@ async fn test_cross_orderbook_economic_selection_prefers_best_yield() { assert!( !config.orders.is_empty(), - "Should have at least one order from the winning orderbook" + "Should have at least one order from the winning raindex" ); for config_item in &config.orders { let config_order = &config_item.order; assert_eq!( config_order.owner, order_v4_a.owner, - "All orders should be from orderbook A" + "All orders should be from raindex A" ); assert_eq!( config_order.evaluable.bytecode, order_v4_a.evaluable.bytecode, - "All order bytecodes should match orderbook A's order" + "All order bytecodes should match raindex A's order" ); } assert_eq!( result.prices().len(), 1, - "Should have exactly one price (from orderbook A only)" + "Should have exactly one price (from raindex A only)" ); let expected_ratio = Float::parse("1".to_string()).unwrap(); assert!( result.prices()[0].eq(expected_ratio).unwrap(), - "Price should be 1.0 (orderbook A's ratio), got: {:?}", + "Price should be 1.0 (raindex A's ratio), got: {:?}", result.prices()[0].format() ); @@ -1672,7 +1672,7 @@ async fn test_spend_up_to_mode_happy_path() { assert_eq!( result.raindex(), setup.raindex, - "Orderbook address should match" + "Raindex address should match" ); let decoded = takeOrders4Call::abi_decode(result.calldata()).expect("Should decode calldata"); @@ -2056,15 +2056,15 @@ async fn test_spend_mode_max_sell_cap_equals_spend_budget() { } #[tokio::test] -async fn test_spend_mode_cross_orderbook_selection() { - let setup = setup_multi_orderbook_test().await; +async fn test_spend_mode_cross_raindex_selection() { + let setup = setup_multi_raindex_test().await; let sg_server = MockServer::start_async().await; let vault_id_a = B256::from(U256::from(1u64)); let vault_id_b = B256::from(U256::from(2u64)); let deposit_amount = U256::from(10).pow(U256::from(22)); - deposit_to_orderbook( + deposit_to_raindex( &setup, setup.raindex_a, setup.token2, @@ -2072,7 +2072,7 @@ async fn test_spend_mode_cross_orderbook_selection() { vault_id_a, ) .await; - deposit_to_orderbook( + deposit_to_raindex( &setup, setup.raindex_b, setup.token2, @@ -2082,25 +2082,25 @@ async fn test_spend_mode_cross_orderbook_selection() { .await; let dotrain_a = - create_dotrain_config_for_orderbook(&setup, setup.raindex_a, "0x01", "50", "2"); + create_dotrain_config_for_raindex(&setup, setup.raindex_a, "0x01", "50", "2"); let (order_bytes_a, order_hash_a, _order_v4_a) = - deploy_order_to_orderbook(&setup, setup.raindex_a, dotrain_a).await; + deploy_order_to_raindex(&setup, setup.raindex_a, dotrain_a).await; let dotrain_b = - create_dotrain_config_for_orderbook(&setup, setup.raindex_b, "0x02", "80", "2"); + create_dotrain_config_for_raindex(&setup, setup.raindex_b, "0x02", "80", "2"); let (order_bytes_b, order_hash_b, order_v4_b) = - deploy_order_to_orderbook(&setup, setup.raindex_b, dotrain_b).await; + deploy_order_to_raindex(&setup, setup.raindex_b, dotrain_b).await; let vault_a_input = - create_vault_for_orderbook(vault_id_a, &setup, setup.raindex_a, &setup.token1_sg); + create_vault_for_raindex(vault_id_a, &setup, setup.raindex_a, &setup.token1_sg); let vault_a_output = - create_vault_for_orderbook(vault_id_a, &setup, setup.raindex_a, &setup.token2_sg); + create_vault_for_raindex(vault_id_a, &setup, setup.raindex_a, &setup.token2_sg); let vault_b_input = - create_vault_for_orderbook(vault_id_b, &setup, setup.raindex_b, &setup.token1_sg); + create_vault_for_raindex(vault_id_b, &setup, setup.raindex_b, &setup.token1_sg); let vault_b_output = - create_vault_for_orderbook(vault_id_b, &setup, setup.raindex_b, &setup.token2_sg); + create_vault_for_raindex(vault_id_b, &setup, setup.raindex_b, &setup.token2_sg); - let sg_order_a = create_sg_order_json_with_orderbook( + let sg_order_a = create_sg_order_json_with_raindex( &setup, setup.raindex_a, &order_bytes_a, @@ -2108,7 +2108,7 @@ async fn test_spend_mode_cross_orderbook_selection() { vec![vault_a_input], vec![vault_a_output], ); - let sg_order_b = create_sg_order_json_with_orderbook( + let sg_order_b = create_sg_order_json_with_raindex( &setup, setup.raindex_b, &order_bytes_b, @@ -2137,7 +2137,7 @@ async fn test_spend_mode_cross_orderbook_selection() { let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let taker = setup.local_evm.signer_wallets[1].default_signer().address(); - fund_and_approve_taker_multi_orderbook( + fund_and_approve_taker_multi_raindex( &setup, setup.token1, taker, @@ -2157,7 +2157,7 @@ async fn test_spend_mode_cross_orderbook_selection() { price_cap: high_price_cap(), }) .await - .expect("Should succeed with spend mode across multiple orderbooks"); + .expect("Should succeed with spend mode across multiple raindexes"); assert!(result.is_ready(), "Expected Ready variant"); let result = result.take_orders_info().unwrap(); @@ -2172,14 +2172,14 @@ async fn test_spend_mode_cross_orderbook_selection() { assert_eq!( result.raindex(), setup.raindex_b, - "Should select orderbook B (can spend more: 80*2=160 vs 50*2=100)" + "Should select raindex B (can spend more: 80*2=160 vs 50*2=100)" ); for config_item in &config.orders { let config_order = &config_item.order; assert_eq!( config_order.owner, order_v4_b.owner, - "All orders should be from orderbook B" + "All orders should be from raindex B" ); } } @@ -2260,7 +2260,7 @@ async fn test_get_take_orders_calldata_returns_approval_when_no_allowance() { assert_eq!( approval.spender(), setup.raindex, - "Approval spender should be orderbook" + "Approval spender should be raindex" ); assert!( !approval.calldata().is_empty(), @@ -2354,7 +2354,7 @@ async fn test_get_take_orders_calldata_returns_approval_when_insufficient_allowa assert_eq!( approval.spender(), setup.raindex, - "Approval spender should be orderbook" + "Approval spender should be raindex" ); } @@ -2442,7 +2442,7 @@ async fn test_get_take_orders_calldata_returns_take_orders_when_sufficient_allow assert_eq!( take_orders.raindex(), setup.raindex, - "Orderbook address should match" + "Raindex address should match" ); assert!( !take_orders.calldata().is_empty(), diff --git a/crates/common/src/raindex_client/take_orders/mod.rs b/crates/common/src/raindex_client/take_orders/mod.rs index 99ab49afec..3faee065e2 100644 --- a/crates/common/src/raindex_client/take_orders/mod.rs +++ b/crates/common/src/raindex_client/take_orders/mod.rs @@ -111,7 +111,7 @@ impl RaindexClient { rpc_urls: rpc_urls.clone(), sell_token: req.sell_token, taker: req.taker, - orderbook: best_raindex, + raindex: best_raindex, mode: req.mode, price_cap: req.price_cap, }; diff --git a/crates/common/src/raindex_client/take_orders/result.rs b/crates/common/src/raindex_client/take_orders/result.rs index a8a4c1042b..256ec54266 100644 --- a/crates/common/src/raindex_client/take_orders/result.rs +++ b/crates/common/src/raindex_client/take_orders/result.rs @@ -204,7 +204,7 @@ impl std::fmt::Debug for TakeOrdersCalldataResult { .finish(), TakeOrdersCalldataResultInner::Ready(data) => f .debug_struct("TakeOrdersCalldataResult::Ready") - .field("orderbook", &data.raindex) + .field("raindex", &data.raindex) .finish(), } } diff --git a/crates/common/src/raindex_client/take_orders/single.rs b/crates/common/src/raindex_client/take_orders/single.rs index e42beb2503..b4d0e27634 100644 --- a/crates/common/src/raindex_client/take_orders/single.rs +++ b/crates/common/src/raindex_client/take_orders/single.rs @@ -216,7 +216,7 @@ pub async fn execute_single_take( let sim_result = simulate_take_orders( &provider, - orderbook, + raindex_addr, execution_params.taker, &built.config, rpc_context.block_number, @@ -225,7 +225,7 @@ pub async fn execute_single_take( match sim_result { Ok(()) => build_calldata_result( - orderbook, + raindex_addr, built, execution_params.mode, execution_params.price_cap, @@ -238,7 +238,7 @@ pub async fn execute_single_take( ))) } else if let Some(_failing_idx) = find_failing_order_index( &provider, - orderbook, + raindex_addr, execution_params.taker, &built.config, rpc_context.block_number, @@ -349,7 +349,7 @@ mod tests { let quote = make_quote(0, 0, Some(make_quote_value(max_output, ratio)), false); use crate::local_db::RaindexIdentifier; - use crate::raindex_client::tests::{get_test_yaml, CHAIN_ID_1_ORDERBOOK_ADDRESS}; + use crate::raindex_client::tests::{get_test_yaml, CHAIN_ID_1_RAINDEX_ADDRESS}; use alloy::primitives::Address; use std::str::FromStr; @@ -382,7 +382,7 @@ mod tests { "symbol": "sFLR", "decimals": "18" }, - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] @@ -399,12 +399,12 @@ mod tests { "symbol": "WFLR", "decimals": "18" }, - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] }], - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "active": true, "timestampAdded": "1739448802", "meta": null, @@ -433,7 +433,7 @@ mod tests { .get_order_by_hash( &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) @@ -450,7 +450,7 @@ mod tests { let quote = make_quote(0, 0, None, true); use crate::local_db::RaindexIdentifier; - use crate::raindex_client::tests::{get_test_yaml, CHAIN_ID_1_ORDERBOOK_ADDRESS}; + use crate::raindex_client::tests::{get_test_yaml, CHAIN_ID_1_RAINDEX_ADDRESS}; use alloy::primitives::Address; use std::str::FromStr; @@ -483,7 +483,7 @@ mod tests { "symbol": "sFLR", "decimals": "18" }, - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] @@ -500,12 +500,12 @@ mod tests { "symbol": "WFLR", "decimals": "18" }, - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] }], - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "active": true, "timestampAdded": "1739448802", "meta": null, @@ -534,7 +534,7 @@ mod tests { .get_order_by_hash( &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) @@ -553,7 +553,7 @@ mod tests { let quote = make_quote(0, 0, Some(make_quote_value(max_output, ratio)), true); use crate::local_db::RaindexIdentifier; - use crate::raindex_client::tests::{get_test_yaml, CHAIN_ID_1_ORDERBOOK_ADDRESS}; + use crate::raindex_client::tests::{get_test_yaml, CHAIN_ID_1_RAINDEX_ADDRESS}; use alloy::primitives::Address; use std::str::FromStr; @@ -586,7 +586,7 @@ mod tests { "symbol": "sFLR", "decimals": "18" }, - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] @@ -603,12 +603,12 @@ mod tests { "symbol": "WFLR", "decimals": "18" }, - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] }], - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "active": true, "timestampAdded": "1739448802", "meta": null, @@ -637,7 +637,7 @@ mod tests { .get_order_by_hash( &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) diff --git a/crates/common/src/raindex_client/trades.rs b/crates/common/src/raindex_client/trades.rs index 4bbe1990f0..0952003a26 100644 --- a/crates/common/src/raindex_client/trades.rs +++ b/crates/common/src/raindex_client/trades.rs @@ -284,7 +284,7 @@ impl RaindexTrade { trade.output_vault_balance_change, )?, timestamp: U256::from_str(&trade.timestamp.0)?, - raindex: Address::from_str(&trade.orderbook.id.0)?, + raindex: Address::from_str(&trade.raindex.id.0)?, }) } @@ -791,7 +791,7 @@ mod test_helpers { "symbol": "sFLR", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "ordersAsOutput": [ @@ -819,7 +819,7 @@ mod test_helpers { "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [], - "orderbook": { + "raindex": { "id": "0x0000000000000000000000000000000000000000" } } @@ -837,7 +837,7 @@ mod test_helpers { "symbol": "WFLR", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "ordersAsOutput": [], @@ -865,12 +865,12 @@ mod test_helpers { "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [], - "orderbook": { + "raindex": { "id": "0x0000000000000000000000000000000000000000" } } ], - "orderbook": { + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "active": true, @@ -927,7 +927,7 @@ mod test_helpers { "blockNumber": "0", "timestamp": "1700000000" }, - "orderbook": { + "raindex": { "id": "0x1234567890abcdef1234567890abcdef12345678" }, "trade": { @@ -964,7 +964,7 @@ mod test_helpers { "blockNumber": "0", "timestamp": "1700000000" }, - "orderbook": { + "raindex": { "id": "0x1234567890abcdef1234567890abcdef12345678" }, "trade": { @@ -974,7 +974,7 @@ mod test_helpers { } }, "timestamp": "0", - "orderbook": { + "raindex": { "id": "0x1234567890abcdef1234567890abcdef12345678" } }) @@ -1017,7 +1017,7 @@ mod test_helpers { "blockNumber": "0", "timestamp": "1700086400" }, - "orderbook": { + "raindex": { "id": "0x1234567890abcdef1234567890abcdef12345679" }, "trade": { @@ -1054,7 +1054,7 @@ mod test_helpers { "blockNumber": "0", "timestamp": "1700086400" }, - "orderbook": { + "raindex": { "id": "0x1234567890abcdef1234567890abcdef12345679" }, "trade": { @@ -1064,7 +1064,7 @@ mod test_helpers { } }, "timestamp": "1700086400", - "orderbook": { + "raindex": { "id": "0x1234567890abcdef1234567890abcdef12345679" } } diff --git a/crates/common/src/raindex_client/transactions.rs b/crates/common/src/raindex_client/transactions.rs index 3c5c95350c..6c02be744e 100644 --- a/crates/common/src/raindex_client/transactions.rs +++ b/crates/common/src/raindex_client/transactions.rs @@ -8,7 +8,7 @@ use alloy::primitives::{Address, B256, U256}; #[cfg(target_family = "wasm")] use gloo_timers::future::TimeoutFuture; use raindex_subgraph_client::types::{common::SgTransaction, Id}; -use raindex_subgraph_client::OrderbookSubgraphClientError; +use raindex_subgraph_client::RaindexSubgraphClientError; use serde::{Deserialize, Serialize}; #[cfg(not(target_family = "wasm"))] use std::time::Duration; @@ -200,7 +200,7 @@ impl RaindexClient { Ok(transaction) => { return transaction.try_into(); } - Err(OrderbookSubgraphClientError::Empty) => { + Err(RaindexSubgraphClientError::Empty) => { if attempt < attempts { sleep_ms(interval_ms).await; continue; diff --git a/crates/common/src/raindex_client/vaults.rs b/crates/common/src/raindex_client/vaults.rs index ef9c9081b9..7cbc71bb2c 100644 --- a/crates/common/src/raindex_client/vaults.rs +++ b/crates/common/src/raindex_client/vaults.rs @@ -29,13 +29,13 @@ use raindex_subgraph_client::{ performance::vol::{VaultVolume, VolumeDetails}, types::{ common::{ - SgBigInt, SgBytes, SgErc20, SgOrderAsIO, SgOrderbook, SgTradeVaultBalanceChange, + SgBigInt, SgBytes, SgErc20, SgOrderAsIO, SgRaindex, SgTradeVaultBalanceChange, SgVault, SgVaultBalanceChangeType, SgVaultBalanceChangeUnwrapped, SgVaultsListFilterArgs, }, Id, }, - MultiOrderbookSubgraphClient, OrderbookSubgraphClient, OrderbookSubgraphClientError, + MultiRaindexSubgraphClient, RaindexSubgraphClient, RaindexSubgraphClientError, SgPaginationArgs, }; use std::str::FromStr; @@ -320,7 +320,7 @@ impl RaindexVaultToken { #[wasm_export] impl RaindexVault { #[wasm_export(skip)] - pub fn get_raindex_subgraph_client(&self) -> Result { + pub fn get_raindex_subgraph_client(&self) -> Result { self.raindex_client.get_raindex_subgraph_client(self.raindex) } @@ -850,7 +850,7 @@ impl RaindexVaultBalanceChange { formatted_old_balance, timestamp: U256::from_str(&balance_change.timestamp.0)?, transaction: RaindexTransaction::try_from(balance_change.transaction)?, - raindex: Address::from_str(&balance_change.orderbook.id.0)?, + raindex: Address::from_str(&balance_change.raindex.id.0)?, }) } } @@ -888,7 +888,7 @@ impl RaindexVaultBalanceChange { formatted_old_balance, timestamp: U256::from_str(&balance_change.timestamp.0)?, transaction: RaindexTransaction::try_from(balance_change.transaction)?, - raindex: Address::from_str(&balance_change.orderbook.id.0)?, + raindex: Address::from_str(&balance_change.raindex.id.0)?, }) } } @@ -917,7 +917,7 @@ impl RaindexVaultBalanceChange { formatted_old_balance: old_balance.format()?, timestamp: U256::from_str(&deposit.timestamp.0)?, transaction: RaindexTransaction::try_from(deposit.transaction)?, - raindex: Address::from_str(&deposit.orderbook.id.0)?, + raindex: Address::from_str(&deposit.raindex.id.0)?, }) } SgVaultBalanceChangeType::Withdrawal(withdrawal) => { @@ -938,7 +938,7 @@ impl RaindexVaultBalanceChange { formatted_old_balance: old_balance.format()?, timestamp: U256::from_str(&withdrawal.timestamp.0)?, transaction: RaindexTransaction::try_from(withdrawal.transaction)?, - raindex: Address::from_str(&withdrawal.orderbook.id.0)?, + raindex: Address::from_str(&withdrawal.raindex.id.0)?, }) } SgVaultBalanceChangeType::TradeVaultBalanceChange(trade_change) => { @@ -962,7 +962,7 @@ impl RaindexVaultBalanceChange { formatted_old_balance: old_balance.format()?, timestamp: U256::from_str(&bounty.timestamp.0)?, transaction: RaindexTransaction::try_from(bounty.transaction)?, - raindex: Address::from_str(&bounty.orderbook.id.0)?, + raindex: Address::from_str(&bounty.raindex.id.0)?, }) } SgVaultBalanceChangeType::Unknown => Err(RaindexError::InvalidVaultBalanceChangeType( @@ -1476,7 +1476,7 @@ impl VaultsDataSource for SubgraphVaults<'_> { ) -> Result, RaindexError> { let raindex_client = ClientRef::new(self.client.clone()); let multi_subgraph_args = self.client.get_multi_subgraph_args(chain_ids)?; - let client = MultiOrderbookSubgraphClient::new( + let client = MultiRaindexSubgraphClient::new( multi_subgraph_args.values().flatten().cloned().collect(), ); @@ -1525,7 +1525,7 @@ impl VaultsDataSource for SubgraphVaults<'_> { let client = self.client.get_raindex_subgraph_client(ob_id.raindex_address)?; let vault = match client.vault_detail(Id::new(vault_id.to_string())).await { Ok(vault) => vault, - Err(OrderbookSubgraphClientError::Empty) => return Ok(None), + Err(RaindexSubgraphClientError::Empty) => return Ok(None), Err(err) => return Err(err.into()), }; @@ -1576,7 +1576,7 @@ impl VaultsDataSource for SubgraphVaults<'_> { chain_ids: Option>, ) -> Result, RaindexError> { let multi_subgraph_args = self.client.get_multi_subgraph_args(chain_ids)?; - let client = MultiOrderbookSubgraphClient::new( + let client = MultiRaindexSubgraphClient::new( multi_subgraph_args.values().flatten().cloned().collect(), ); @@ -1632,7 +1632,7 @@ impl TryFrom for SgVaultsListFilterArgs { .collect() }) .unwrap_or_default(), - orderbooks: filters + raindexes: filters .raindex_addresses .map(|addrs| { addrs @@ -1668,7 +1668,7 @@ impl RaindexVault { balance, formatted_balance, token, - raindex: Address::from_str(&vault.orderbook.id.0)?, + raindex: Address::from_str(&vault.raindex.id.0)?, orders_as_inputs: vault .orders_as_input .iter() @@ -1706,7 +1706,7 @@ impl RaindexVault { balance: SgBytes(self.balance.as_hex()), owner: SgBytes(self.owner.to_string()), token: self.token.try_into()?, - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes(self.raindex.to_string()), }, orders_as_input: self @@ -2348,7 +2348,7 @@ mod tests { "symbol": "TKN1", "decimals": "18" }, - "orderbook": { + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], @@ -2370,7 +2370,7 @@ mod tests { "symbol": "TKN2", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0x0000000000000000000000000000000000000000" }, "ordersAsOutput": [], @@ -2531,7 +2531,7 @@ mod tests { "symbol": "TKN1", "decimals": null // Missing decimals }, - "orderbook": { + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], @@ -2628,7 +2628,7 @@ mod tests { "blockNumber": "34407047", "timestamp": "1734054063" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" } } @@ -2722,7 +2722,7 @@ mod tests { "symbol": "USDC", "decimals": "6" }, - "orderbook": { + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], @@ -2810,7 +2810,7 @@ mod tests { "blockNumber": "34407047", "timestamp": "1734054063" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" } } @@ -2908,7 +2908,7 @@ mod tests { "blockNumber": "34407047", "timestamp": "1734054063" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" } } diff --git a/crates/common/src/raindex_client/vaults_list.rs b/crates/common/src/raindex_client/vaults_list.rs index a691277598..07e7621eac 100644 --- a/crates/common/src/raindex_client/vaults_list.rs +++ b/crates/common/src/raindex_client/vaults_list.rs @@ -1,6 +1,6 @@ use alloy::{primitives::Bytes, sol_types::SolCall}; use rain_math_float::Float; -use raindex_bindings::OrderBook::multicallCall; +use raindex_bindings::Raindex::multicallCall; use serde::{Deserialize, Serialize}; use thiserror::Error; use wasm_bindgen_utils::prelude::*; @@ -210,7 +210,7 @@ pub enum VaultsListError { WithdrawMulticallError(String), #[error("No withdrawable vaults available")] NoWithdrawableVaults, - #[error("All vaults must share the same orderbook for batch withdrawal")] + #[error("All vaults must share the same raindex for batch withdrawal")] MultipleRaindexesUsed, } @@ -222,7 +222,7 @@ impl VaultsListError { } VaultsListError::NoWithdrawableVaults => "No withdrawable vaults available".to_string(), VaultsListError::MultipleRaindexesUsed => { - "All vaults must share the same orderbook for batch withdrawal".to_string() + "All vaults must share the same raindex for batch withdrawal".to_string() } } } @@ -267,7 +267,7 @@ mod tests { "symbol": "TKN1", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0x0000000000000000000000000000000000000000" }, "ordersAsOutput": [], @@ -289,7 +289,7 @@ mod tests { "symbol": "TKN2", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0x0000000000000000000000000000000000000000" }, "ordersAsOutput": [], diff --git a/crates/common/src/remove_order.rs b/crates/common/src/remove_order.rs index 98b08d8f2f..0c39be66b0 100644 --- a/crates/common/src/remove_order.rs +++ b/crates/common/src/remove_order.rs @@ -81,7 +81,7 @@ mod tests { use alloy::primitives::Address; use raindex_bindings::IRaindexV6::removeOrder3Call; use raindex_subgraph_client::types::common::{ - SgBigInt, SgBytes, SgErc20, SgOrderbook, SgVault, + SgBigInt, SgBytes, SgErc20, SgRaindex, SgVault, }; use raindex_subgraph_client::utils::float::*; @@ -110,7 +110,7 @@ mod tests { symbol: Some("WFLR".to_string()), decimals: Some(SgBigInt("18".to_string())), }, - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("0xcee8cd002f151a536394e564b84076c41bbbcd4d".to_string()), }, orders_as_output: vec![], @@ -119,7 +119,7 @@ mod tests { }, ], inputs: vec![], - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("0xcee8cd002f151a536394e564b84076c41bbbcd4d".to_string()), }, active: true, diff --git a/crates/common/src/subgraph.rs b/crates/common/src/subgraph.rs index b295f95759..8cbb89f1db 100644 --- a/crates/common/src/subgraph.rs +++ b/crates/common/src/subgraph.rs @@ -1,4 +1,4 @@ -use raindex_subgraph_client::OrderbookSubgraphClient; +use raindex_subgraph_client::RaindexSubgraphClient; use serde::{Deserialize, Serialize}; use url::{ParseError, Url}; @@ -8,8 +8,8 @@ pub struct SubgraphArgs { } impl SubgraphArgs { - pub fn to_subgraph_client(&self) -> Result { - Ok(OrderbookSubgraphClient::new(Url::parse(self.url.as_str())?)) + pub fn to_subgraph_client(&self) -> Result { + Ok(RaindexSubgraphClient::new(Url::parse(self.url.as_str())?)) } } diff --git a/crates/common/src/take_orders/candidates.rs b/crates/common/src/take_orders/candidates.rs index 03a62cd8a7..82cbf4e516 100644 --- a/crates/common/src/take_orders/candidates.rs +++ b/crates/common/src/take_orders/candidates.rs @@ -45,11 +45,11 @@ pub struct TakeOrderCandidate { fn get_raindex_address(order: &RaindexOrder) -> Result { #[cfg(target_family = "wasm")] { - Ok(Address::from_str(&order.orderbook())?) + Ok(Address::from_str(&order.raindex())?) } #[cfg(not(target_family = "wasm"))] { - Ok(order.orderbook()) + Ok(order.raindex()) } } diff --git a/crates/common/src/test_helpers.rs b/crates/common/src/test_helpers.rs index 50ed8b156e..ead17c7f72 100644 --- a/crates/common/src/test_helpers.rs +++ b/crates/common/src/test_helpers.rs @@ -179,7 +179,7 @@ pub mod local_evm { use alloy::primitives::{Address, B256, U256}; use rain_math_float::Float; use raindex_subgraph_client::types::common::{ - SgBigInt, SgBytes, SgErc20, SgOrderbook, SgVault, + SgBigInt, SgBytes, SgErc20, SgRaindex, SgVault, }; use raindex_test_fixtures::LocalEvm; @@ -466,7 +466,7 @@ pub mod local_evm { balance: SgBytes(Float::parse(balance.to_string()).unwrap().as_hex()), vault_id: SgBytes(vault_id.to_string()), owner: SgBytes(owner.to_string()), - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes(raindex.to_string()), }, orders_as_input: vec![], @@ -910,7 +910,7 @@ pub mod subgraph { use alloy::primitives::{Address, B256}; use raindex_app_settings::spec_version::SpecVersion; use raindex_subgraph_client::types::common::{ - SgBigInt, SgBytes, SgOrder, SgOrderbook, SgVault, + SgBigInt, SgBytes, SgOrder, SgRaindex, SgVault, }; use serde_json::json; @@ -925,7 +925,7 @@ pub mod subgraph { ) -> SgOrder { SgOrder { id: SgBytes(order_hash.to_string()), - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes(setup.raindex.to_string()), }, order_bytes: SgBytes(order_bytes), @@ -958,7 +958,7 @@ pub mod subgraph { "symbol": v.token.symbol.clone().unwrap_or_default(), "decimals": v.token.decimals.clone().map(|d| d.0).unwrap_or_default() }, - "orderbook": { "id": raindex.to_string() }, + "raindex": { "id": raindex.to_string() }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] @@ -1020,7 +1020,7 @@ pub mod subgraph { "owner": owner.to_string(), "outputs": outputs_json, "inputs": inputs_json, - "orderbook": { "id": raindex.to_string() }, + "raindex": { "id": raindex.to_string() }, "active": true, "timestampAdded": "1739448802", "meta": null, diff --git a/crates/common/src/types/order_detail_extended.rs b/crates/common/src/types/order_detail_extended.rs index e9e221c185..a182feaebe 100644 --- a/crates/common/src/types/order_detail_extended.rs +++ b/crates/common/src/types/order_detail_extended.rs @@ -37,7 +37,7 @@ mod tests { use super::*; use crate::meta::TryDecodeRainlangSourceError; use raindex_subgraph_client::types::common::{ - SgAddOrder, SgBigInt, SgBytes, SgErc20, SgOrderStructPartialTrade, SgOrderbook, + SgAddOrder, SgBigInt, SgBytes, SgErc20, SgOrderStructPartialTrade, SgRaindex, SgRemoveOrder, SgTransaction, SgVault, }; use std::convert::TryInto; @@ -46,7 +46,7 @@ mod tests { let default_sg_bytes = SgBytes(format!("default_{}", id_str)); let default_big_int = SgBigInt("0".to_string()); - let orderbook = SgOrderbook { + let raindex = SgRaindex { id: default_sg_bytes.clone(), }; @@ -64,7 +64,7 @@ mod tests { vault_id: default_sg_bytes.clone(), balance: default_sg_bytes.clone(), token: token.clone(), - orderbook: orderbook.clone(), + raindex: raindex.clone(), orders_as_output: vec![], orders_as_input: vec![], balance_changes: vec![], @@ -84,7 +84,7 @@ mod tests { owner: default_sg_bytes.clone(), outputs: vec![vault.clone()], inputs: vec![vault.clone()], - orderbook, + raindex, active: true, timestamp_added: default_big_int.clone(), meta: meta_option, diff --git a/crates/common/src/types/order_takes_list_flattened.rs b/crates/common/src/types/order_takes_list_flattened.rs index 870b306a2f..76a7b0d01e 100644 --- a/crates/common/src/types/order_takes_list_flattened.rs +++ b/crates/common/src/types/order_takes_list_flattened.rs @@ -60,7 +60,7 @@ mod tests { use super::*; use rain_math_float::FloatError; use raindex_subgraph_client::types::common::{ - SgBigInt, SgBytes, SgErc20, SgOrderbook, SgTrade, SgTradeEvent, SgTradeStructPartialOrder, + SgBigInt, SgBytes, SgErc20, SgRaindex, SgTrade, SgTradeEvent, SgTradeStructPartialOrder, SgTradeVaultBalanceChange, SgTransaction, SgVaultBalanceChangeVault, }; use raindex_subgraph_client::utils::float::*; @@ -107,7 +107,7 @@ mod tests { block_number: SgBigInt("1000".to_string()), timestamp: SgBigInt("1678886400".to_string()), }, - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("raindexVBCIn001".to_string()), }, trade: SgTradeRef { @@ -140,7 +140,7 @@ mod tests { block_number: SgBigInt("1000".to_string()), timestamp: SgBigInt("1678886400".to_string()), }, - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("raindexVBCOut001".to_string()), }, trade: SgTradeRef { @@ -149,7 +149,7 @@ mod tests { }, }, }, - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("mainRaindex001".to_string()), }, } diff --git a/crates/common/src/types/orders_list_flattened.rs b/crates/common/src/types/orders_list_flattened.rs index d9ece1541b..e223aa0818 100644 --- a/crates/common/src/types/orders_list_flattened.rs +++ b/crates/common/src/types/orders_list_flattened.rs @@ -92,7 +92,7 @@ mod tests { }; use raindex_bindings::IRaindexV6::{EvaluableV4, OrderV4, IOV2}; use raindex_subgraph_client::types::common::{ - SgAddOrder, SgBigInt, SgBytes, SgErc20, SgOrderStructPartialTrade, SgOrderbook, + SgAddOrder, SgBigInt, SgBytes, SgErc20, SgOrderStructPartialTrade, SgRaindex, SgTransaction, SgVault, }; use std::str::FromStr; @@ -144,7 +144,7 @@ mod tests { symbol: Some("TOUT".into()), decimals: Some(SgBigInt("18".into())), }, - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("ob-id".into()), }, orders_as_output: vec![], @@ -163,14 +163,14 @@ mod tests { symbol: Some("TIN".into()), decimals: Some(SgBigInt("18".into())), }, - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("ob-id".into()), }, orders_as_output: vec![], orders_as_input: vec![], balance_changes: vec![], }], - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("ob-id".into()), }, active: true, @@ -241,7 +241,7 @@ mod tests { id: SgBytes("vault-in-id-2".into()), owner: SgBytes("vault-owner-2".into()), balance: SgBytes("1000".into()), - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("ob-id".into()), }, orders_as_output: vec![], @@ -260,7 +260,7 @@ mod tests { id: SgBytes("vault-out-id-2".into()), owner: SgBytes("vault-owner-2".into()), balance: SgBytes("1000".into()), - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("ob-id".into()), }, orders_as_output: vec![], @@ -352,7 +352,7 @@ mod tests { id: SgBytes("vault-in-id".into()), owner: SgBytes("vault-owner".into()), balance: SgBytes("1000".into()), - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("ob-id".into()), }, orders_as_output: vec![], @@ -371,7 +371,7 @@ mod tests { id: SgBytes("vault-out-id".into()), owner: SgBytes("vault-owner".into()), balance: SgBytes("1000".into()), - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("ob-id".into()), }, vault_id: SgBytes("222".into()), diff --git a/crates/common/src/types/token_vault_flattened.rs b/crates/common/src/types/token_vault_flattened.rs index de4e1d4711..add614c8c2 100644 --- a/crates/common/src/types/token_vault_flattened.rs +++ b/crates/common/src/types/token_vault_flattened.rs @@ -45,7 +45,7 @@ impl TryIntoCsv for Vec {} mod tests { use super::*; use raindex_subgraph_client::types::common::{ - SgBigInt, SgBytes, SgErc20, SgOrderAsIO, SgOrderbook, SgVault, SgVaultBalanceChangeType, + SgBigInt, SgBytes, SgErc20, SgOrderAsIO, SgRaindex, SgVault, SgVaultBalanceChangeType, }; use raindex_subgraph_client::utils::float::*; @@ -73,7 +73,7 @@ mod tests { symbol: token_symbol.map(String::from), decimals: token_decimals_str.map(|s| SgBigInt(s.into())), }, - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("default_raindex_id".into()), }, orders_as_output: Vec::::new(), diff --git a/crates/common/src/types/vault_balance_change_flattened.rs b/crates/common/src/types/vault_balance_change_flattened.rs index 58e808fb82..7fe14203a3 100644 --- a/crates/common/src/types/vault_balance_change_flattened.rs +++ b/crates/common/src/types/vault_balance_change_flattened.rs @@ -78,7 +78,7 @@ mod tests { use crate::utils::timestamp::format_bigint_timestamp_display; use rain_math_float::FloatError; use raindex_subgraph_client::types::common::{ - SgBigInt, SgBytes, SgErc20, SgOrderbook, SgTransaction, SgVaultBalanceChangeUnwrapped, + SgBigInt, SgBytes, SgErc20, SgRaindex, SgTransaction, SgVaultBalanceChangeUnwrapped, SgVaultBalanceChangeVault, }; use raindex_subgraph_client::utils::float::*; @@ -114,7 +114,7 @@ mod tests { decimals: decimals_val.map(|s| SgBigInt(s.to_string())), }, }, - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("0xraindexid".to_string()), }, } diff --git a/crates/quote/src/cli/mod.rs b/crates/quote/src/cli/mod.rs index 86d9c0449a..819bd67b5d 100644 --- a/crates/quote/src/cli/mod.rs +++ b/crates/quote/src/cli/mod.rs @@ -355,7 +355,7 @@ mod tests { }, "balance": "0", "vaultId": order.validOutputs[0].vaultId.to_string(), - "orderbook": { "id": encode_prefixed(B256::random()) }, + "raindex": { "id": encode_prefixed(B256::random()) }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] @@ -372,12 +372,12 @@ mod tests { }, "balance": "0", "vaultId": order.validInputs[0].vaultId.to_string(), - "orderbook": { "id": encode_prefixed(B256::random()) }, + "raindex": { "id": encode_prefixed(B256::random()) }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] }], - "orderbook": { "id": encode_prefixed(B256::random()) }, + "raindex": { "id": encode_prefixed(B256::random()) }, "active": true, "addEvents": [{ "transaction": { diff --git a/crates/quote/src/order_quotes.rs b/crates/quote/src/order_quotes.rs index 7b49331c81..034cd4a24b 100644 --- a/crates/quote/src/order_quotes.rs +++ b/crates/quote/src/order_quotes.rs @@ -63,7 +63,7 @@ pub async fn get_order_quotes( for order in &orders { let order_struct: OrderV4 = order.clone().try_into()?; - let raindex = Address::from_str(&order.orderbook.id.0)?; + let raindex = Address::from_str(&order.raindex.id.0)?; let oracle_url = crate::oracle::extract_oracle_url(order); for (input_index, input) in order_struct.validInputs.iter().enumerate() { @@ -212,7 +212,7 @@ mod tests { use raindex_app_settings::spec_version::SpecVersion; use raindex_common::{add_order::AddOrderArgs, dotrain_order::DotrainOrder}; use raindex_subgraph_client::types::{ - common::{SgBigInt, SgBytes, SgErc20, SgOrderbook, SgVault}, + common::{SgBigInt, SgBytes, SgErc20, SgRaindex, SgVault}, order_detail_traits::OrderDetailError, }; use raindex_subgraph_client::utils::float::*; @@ -236,7 +236,7 @@ mod tests { let token2 = local_evm .deploy_new_token("Token2", "Token2", 18, U256::MAX, owner) .await; - let raindex = *local_evm.orderbook.address(); + let raindex = *local_evm.raindex.address(); TestSetup { local_evm, @@ -358,7 +358,7 @@ amount price: 2 3; balance: SgBytes(F6.as_hex()), vault_id: SgBytes(vault_id.to_string()), owner: SgBytes(setup.local_evm.anvil.addresses()[0].to_string()), - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes(setup.raindex.to_string()), }, orders_as_input: vec![], @@ -375,7 +375,7 @@ amount price: 2 3; ) -> SgOrder { SgOrder { id: SgBytes(B256::random().to_string()), - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes(setup.raindex.to_string()), }, order_bytes: SgBytes(order_bytes), @@ -507,7 +507,7 @@ amount price: 2 3; // Test invalid raindex address let mut invalid_order = create_sg_order(&setup, order.clone(), vec![], vec![]); - invalid_order.orderbook.id = SgBytes("invalid_address".to_string()); + invalid_order.raindex.id = SgBytes("invalid_address".to_string()); let err = get_order_quotes(vec![invalid_order], None, vec![setup.local_evm.url()], None) .await diff --git a/crates/quote/src/quote.rs b/crates/quote/src/quote.rs index 885d6c24d6..c78e211068 100644 --- a/crates/quote/src/quote.rs +++ b/crates/quote/src/quote.rs @@ -363,7 +363,7 @@ mod tests { }, "balance": "0", "vaultId": order.validOutputs[0].vaultId.to_string(), - "orderbook": { "id": encode_prefixed(B256::random()) }, + "raindex": { "id": encode_prefixed(B256::random()) }, "ordersAsOutput": [{ "id": encode_prefixed(B256::random()), "orderHash": encode_prefixed(B256::random()), @@ -398,7 +398,7 @@ mod tests { "timestamp": "0", "from": encode_prefixed(Address::random()) }, - "orderbook": { "id": encode_prefixed(B256::random()) } + "raindex": { "id": encode_prefixed(B256::random()) } }], }], "inputs": [{ @@ -413,7 +413,7 @@ mod tests { }, "balance": "0", "vaultId": order.validInputs[0].vaultId.to_string(), - "orderbook": { "id": encode_prefixed(B256::random()) }, + "raindex": { "id": encode_prefixed(B256::random()) }, "ordersAsOutput": [{ "id": encode_prefixed(B256::random()), "orderHash": encode_prefixed(B256::random()), @@ -448,10 +448,10 @@ mod tests { "timestamp": "0", "from": encode_prefixed(Address::random()) }, - "orderbook": { "id": encode_prefixed(B256::random()) } + "raindex": { "id": encode_prefixed(B256::random()) } }], }], - "orderbook": { "id": encode_prefixed(B256::random()) }, + "raindex": { "id": encode_prefixed(B256::random()) }, "active": true, "addEvents": [{ "transaction": { @@ -689,7 +689,7 @@ mod tests { "orderBytes": encode_prefixed(order.abi_encode()), "orderHash": encode_prefixed(B256::random()), "owner": encode_prefixed(order.owner), - "orderbook": { "id": encode_prefixed(B256::random()) }, + "raindex": { "id": encode_prefixed(B256::random()) }, "active": true, "addEvents": [], "meta": null, diff --git a/crates/quote/src/quote_debug.rs b/crates/quote/src/quote_debug.rs index a77564d60f..e4e3fbd99e 100644 --- a/crates/quote/src/quote_debug.rs +++ b/crates/quote/src/quote_debug.rs @@ -99,7 +99,7 @@ mod tests { async fn test_quote_debugger() { let local_evm = LocalEvm::new_with_tokens(2).await; - let raindex = &local_evm.orderbook; + let raindex = &local_evm.raindex; let token1_holder = local_evm.signer_wallets[0].default_signer().address(); let token1 = local_evm.tokens[0].clone(); let token2 = local_evm.tokens[1].clone(); @@ -224,7 +224,7 @@ amount price: 16 52; async fn test_quote_debugger_partial() { let local_evm = LocalEvm::new_with_tokens(2).await; - let raindex = &local_evm.orderbook; + let raindex = &local_evm.raindex; let token1_holder = local_evm.signer_wallets[0].default_signer().address(); let token1 = local_evm.tokens[0].clone(); let token2 = local_evm.tokens[1].clone(); @@ -361,7 +361,7 @@ _: 1; async fn test_quote_debugger_debug_err() { let local_evm = LocalEvm::new_with_tokens(2).await; - let raindex = &local_evm.orderbook; + let raindex = &local_evm.raindex; let token1_holder = local_evm.signer_wallets[0].default_signer().address(); let token1 = local_evm.tokens[0].clone(); let token2 = local_evm.tokens[1].clone(); diff --git a/crates/rest_api/src/routes/take_orders.rs b/crates/rest_api/src/routes/take_orders.rs index d88cbaa84b..9aece4aba9 100644 --- a/crates/rest_api/src/routes/take_orders.rs +++ b/crates/rest_api/src/routes/take_orders.rs @@ -192,7 +192,7 @@ async fn execute_take_orders( })?; Ok(TakeOrdersApiResponse::Ready(TakeOrdersReadyResponse { - raindex: take_orders_info.orderbook().to_string(), + raindex: take_orders_info.raindex().to_string(), calldata: take_orders_info.calldata().to_string(), effective_price, prices: prices?, diff --git a/crates/test_fixtures/src/lib.rs b/crates/test_fixtures/src/lib.rs index c083cba536..61726134b4 100644 --- a/crates/test_fixtures/src/lib.rs +++ b/crates/test_fixtures/src/lib.rs @@ -362,7 +362,7 @@ impl LocalEvm { .get_inner(); let tx = self - .orderbook + .raindex .deposit4(token, vault_id, raw_deposit_amount, vec![]) .from(from) .into_transaction_request(); From cf927518aa0bad5de7294a228cb47bbf62e3a8bb Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Tue, 31 Mar 2026 16:37:37 +0400 Subject: [PATCH 20/69] Rename OrderBook to Raindex in packages/raindex test assertions Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/raindex/test/js_api/gui.test.ts | 4 +- .../raindex/test/js_api/raindexClient.test.ts | 90 +++++++++---------- 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/packages/raindex/test/js_api/gui.test.ts b/packages/raindex/test/js_api/gui.test.ts index 37071e4bde..f4f42eb6e3 100644 --- a/packages/raindex/test/js_api/gui.test.ts +++ b/packages/raindex/test/js_api/gui.test.ts @@ -1957,7 +1957,7 @@ ${dotrainWithoutVaultIds}`; ); assert.equal(result.approvals[0].symbol, 'T2'); assert.equal(result.deploymentCalldata.length, 3594); - assert.equal(result.orderbookAddress, '0xc95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a6'); + assert.equal(result.raindexAddress, '0xc95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a6'); assert.equal(result.chainId, 123); const emitMetaCall = result.emitMetaCall; @@ -1982,7 +1982,7 @@ ${dotrainWithoutVaultIds}`; assert.equal(result.approvals.length, 0); assert.equal(result.deploymentCalldata.length, 2954); - assert.equal(result.orderbookAddress, '0xc95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a6'); + assert.equal(result.raindexAddress, '0xc95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a6'); assert.equal(result.chainId, 123); const emitMetaCallAfterUnset = result.emitMetaCall; diff --git a/packages/raindex/test/js_api/raindexClient.test.ts b/packages/raindex/test/js_api/raindexClient.test.ts index 81219f292f..5508bd65c6 100644 --- a/packages/raindex/test/js_api/raindexClient.test.ts +++ b/packages/raindex/test/js_api/raindexClient.test.ts @@ -159,7 +159,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun ordersAsOutput: [], ordersAsInput: [], balanceChanges: [], - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS } }, @@ -178,7 +178,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun ordersAsOutput: [], ordersAsInput: [], balanceChanges: [], - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS } } @@ -199,7 +199,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun ordersAsOutput: [], ordersAsInput: [], balanceChanges: [], - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS } }, @@ -218,7 +218,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun ordersAsOutput: [], ordersAsInput: [], balanceChanges: [], - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS } } @@ -236,7 +236,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun ], meta: '0xff0a89c674ee7874a3005902252f2a20302e2063616c63756c6174652d696f202a2f200a7573696e672d776f7264732d66726f6d203078466532343131434461313933443945346538334135633233344337466433323031303138383361430a616d743a203130302c0a696f3a2063616c6c3c323e28293b0a0a2f2a20312e2068616e646c652d696f202a2f200a3a63616c6c3c333e28292c0a3a656e7375726528657175616c2d746f286f75747075742d7661756c742d64656372656173652829203130302920226d7573742074616b652066756c6c20616d6f756e7422293b0a0a2f2a20322e206765742d696f2d726174696f2d6e6f77202a2f200a656c61707365643a2063616c6c3c343e28292c0a696f3a2073617475726174696e672d73756228302e3031373733353620646976286d756c28656c61707365642073756228302e3031373733353620302e30313733383434292920363029293b0a0a2f2a20332e206f6e652d73686f74202a2f200a3a656e737572652869732d7a65726f286765742868617368286f726465722d68617368282920226861732d657865637574656422292929202268617320657865637574656422292c0a3a7365742868617368286f726465722d68617368282920226861732d657865637574656422292031293b0a0a2f2a20342e206765742d656c6170736564202a2f200a5f3a20737562286e6f772829206765742868617368286f726465722d68617368282920226465706c6f792d74696d65222929293b011bff13109e41336ff20278186170706c69636174696f6e2f6f637465742d73747265616d', timestampAdded: '0', - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS }, trades: [], @@ -265,7 +265,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun ordersAsOutput: [], ordersAsInput: [], balanceChanges: [], - orderbook: { + raindex: { id: CHAIN_ID_2_RAINDEX_ADDRESS } } @@ -286,7 +286,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun ordersAsOutput: [], ordersAsInput: [], balanceChanges: [], - orderbook: { + raindex: { id: CHAIN_ID_2_RAINDEX_ADDRESS } } @@ -304,7 +304,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun ], meta: null, timestampAdded: '0', - orderbook: { + raindex: { id: CHAIN_ID_2_RAINDEX_ADDRESS }, trades: [], @@ -338,7 +338,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun ordersAsOutput: [], ordersAsInput: [], balanceChanges: [], - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS } } @@ -359,7 +359,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun ordersAsOutput: [], ordersAsInput: [], balanceChanges: [], - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS } } @@ -377,7 +377,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun ], meta: null, timestampAdded: '0', - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS }, trades: [], @@ -421,7 +421,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun timestamp: '1632000000', blockNumber: '0' }, - orderbook: { id: CHAIN_ID_1_RAINDEX_ADDRESS }, + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS }, trade: { tradeEvent: { __typename: 'TakeOrder' } } }, order: { @@ -452,10 +452,10 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun timestamp: '1632000000', blockNumber: '0' }, - orderbook: { id: CHAIN_ID_1_RAINDEX_ADDRESS }, + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS }, trade: { tradeEvent: { __typename: 'TakeOrder' } } }, - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS } } @@ -498,7 +498,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun timestamp: '1632000000', blockNumber: '0' }, - orderbook: { id: CHAIN_ID_1_RAINDEX_ADDRESS }, + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS }, trade: { tradeEvent: { __typename: 'TakeOrder' } } }, order: { @@ -529,10 +529,10 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun timestamp: '1632000000', blockNumber: '0' }, - orderbook: { id: CHAIN_ID_1_RAINDEX_ADDRESS }, + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS }, trade: { tradeEvent: { __typename: 'TakeOrder' } } }, - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS } } @@ -554,7 +554,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun } }, timestamp: '0', - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS }, outputVaultBalanceChange: { @@ -581,7 +581,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun blockNumber: '0', timestamp: '0' }, - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS }, trade: { tradeEvent: { __typename: 'TakeOrder' } } @@ -610,7 +610,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun blockNumber: '0', timestamp: '0' }, - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS }, trade: { tradeEvent: { __typename: 'TakeOrder' } } @@ -650,7 +650,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun ); assert.equal(typeof order, 'object'); assert.equal(order.id, order1.id); - assert.equal(order.orderbook, order1.orderbook.id); + assert.equal(order.raindex, order1.raindex.id); assert.equal(order.owner, order1.owner); assert.equal(order.active, order1.active); assert.equal(order.timestampAdded, order1.timestampAdded); @@ -812,7 +812,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun // const expected: OrderPerformance = { // orderId: '0x0123', // orderHash: '0x0123', - // orderbook: CHAIN_ID_1_RAINDEX_ADDRESS, + // raindex: CHAIN_ID_1_RAINDEX_ADDRESS, // denominatedPerformance: { // token: { // id: '0x0234', @@ -1032,7 +1032,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun assert.equal(result[0].id, mockOrderTradesList[0].id); assert.equal(result[0].orderHash, mockOrderTradesList[0].order.orderHash); assert.equal(result[0].timestamp, BigInt(mockOrderTradesList[0].timestamp)); - assert.equal(result[0].orderbook, mockOrderTradesList[0].orderbook.id.toLowerCase()); + assert.equal(result[0].raindex, mockOrderTradesList[0].raindex.id.toLowerCase()); assert.equal( result[0].outputVaultBalanceChange.amount, mockOrderTradesList[0].outputVaultBalanceChange.amount @@ -1186,7 +1186,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun result.transaction.timestamp, BigInt(mockTrade.tradeEvent.transaction.timestamp) ); - assert.equal(result.orderbook, mockTrade.orderbook.id.toLowerCase()); + assert.equal(result.raindex, mockTrade.raindex.id.toLowerCase()); }); it('should get trade count', async function () { @@ -1253,7 +1253,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun symbol: 'sFLR', decimals: '18' }, - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS }, ordersAsOutput: [ @@ -1294,7 +1294,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun blockNumber: '37432554', timestamp: '1739448802' }, - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS } } @@ -1328,7 +1328,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun blockNumber: '37439233', timestamp: '1739460802' }, - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS } } @@ -1362,7 +1362,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun blockNumber: '37439219', timestamp: '1739460777' }, - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS } } @@ -1396,7 +1396,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun blockNumber: '37439068', timestamp: '1739460481' }, - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS } } @@ -1418,7 +1418,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun symbol: 'WFLR', decimals: '18' }, - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS }, ordersAsOutput: [], @@ -1459,7 +1459,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun blockNumber: '37439221', timestamp: '1739460781' }, - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS } } @@ -1493,7 +1493,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun blockNumber: '37439034', timestamp: '1739460415' }, - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS } } @@ -1527,7 +1527,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun blockNumber: '37439143', timestamp: '1739460627' }, - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS } } @@ -1561,7 +1561,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun blockNumber: '37438849', timestamp: '1739460078' }, - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS } } @@ -1569,7 +1569,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun ] } ], - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS }, active: true, @@ -1607,7 +1607,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun ); assert.equal(result[0].id, mockAddOrder.order.id); assert.equal(result[0].chainId, BigInt(1)); - assert.equal(result[0].orderbook, mockAddOrder.order.orderbook.id); + assert.equal(result[0].raindex, mockAddOrder.order.raindex.id); assert.equal(result[0].transaction?.id, mockAddOrder.transaction.id); }); @@ -1626,7 +1626,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun ); assert.equal(result[0].id, mockRemoveOrder.order.id); assert.equal(result[0].chainId, BigInt(1)); - assert.equal(result[0].orderbook, mockRemoveOrder.order.orderbook.id); + assert.equal(result[0].raindex, mockRemoveOrder.order.raindex.id); assert.equal(result[0].transaction?.id, mockRemoveOrder.transaction.id); }); }); @@ -1644,7 +1644,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun symbol: 'TKN1', decimals: '18' }, - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS }, ordersAsOutput: [], @@ -1663,7 +1663,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun symbol: 'TKN2', decimals: '18' }, - orderbook: { + raindex: { id: CHAIN_ID_2_RAINDEX_ADDRESS }, ordersAsOutput: [], @@ -1726,7 +1726,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun assert.equal(result.token.name, vault1.token.name); assert.equal(result.token.symbol, vault1.token.symbol); assert.equal(result.token.decimals, BigInt(vault1.token.decimals ?? 0)); - assert.equal(result.orderbook, vault1.orderbook.id); + assert.equal(result.raindex, vault1.raindex.id); }); it('should fetch vault balance changes', async () => { @@ -1755,7 +1755,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun blockNumber: '34407047', timestamp: '1734054063' }, - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS } } @@ -1787,7 +1787,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun assert.equal(result[0].transaction.from, '0x7177b9d00bB5dbcaaF069CC63190902763783b09'); assert.equal(result[0].transaction.blockNumber, BigInt('34407047')); assert.equal(result[0].transaction.timestamp, BigInt('1734054063')); - assert.equal(result[0].orderbook, CHAIN_ID_1_RAINDEX_ADDRESS); + assert.equal(result[0].raindex, CHAIN_ID_1_RAINDEX_ADDRESS); }); const order = { @@ -1812,7 +1812,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun ordersAsOutput: [], ordersAsInput: [], balanceChanges: [], - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS } } @@ -1833,7 +1833,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun ordersAsOutput: [], ordersAsInput: [], balanceChanges: [], - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS } } @@ -1851,7 +1851,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async fun ], meta: null, timestampAdded: '0', - orderbook: { + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS }, trades: [], From 05ff975792ddab471bf8924377c5c443c21ef42a Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Tue, 31 Mar 2026 16:39:04 +0400 Subject: [PATCH 21/69] Rename orderbook to raindex in test resource JSON fixtures Co-Authored-By: Claude Opus 4.6 (1M context) --- .../example-subgraph-order-res1.json | 8 +- .../example-subgraph-orders-res1.json | 300 +++++++++--------- 2 files changed, 154 insertions(+), 154 deletions(-) diff --git a/test-resources/example-subgraph-order-res1.json b/test-resources/example-subgraph-order-res1.json index 4713c7afb1..f2470246e2 100644 --- a/test-resources/example-subgraph-order-res1.json +++ b/test-resources/example-subgraph-order-res1.json @@ -18,7 +18,7 @@ "symbol": "sFLR", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "ordersAsOutput": [ @@ -54,7 +54,7 @@ "blockNumber": "41639973", "timestamp": "1747395764" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" } } @@ -74,7 +74,7 @@ "symbol": "cysFLR", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "ordersAsOutput": [], @@ -88,7 +88,7 @@ "balanceChanges": [] } ], - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "active": true, diff --git a/test-resources/example-subgraph-orders-res1.json b/test-resources/example-subgraph-orders-res1.json index c9cc14f043..f7c26cf756 100644 --- a/test-resources/example-subgraph-orders-res1.json +++ b/test-resources/example-subgraph-orders-res1.json @@ -19,7 +19,7 @@ "symbol": "NST", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "ordersAsOutput": [ @@ -61,7 +61,7 @@ "blockNumber": "334540334", "timestamp": "1746709013" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" } }, @@ -89,7 +89,7 @@ "blockNumber": "336196423", "timestamp": "1747125140" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -122,7 +122,7 @@ "blockNumber": "335296669", "timestamp": "1746898967" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -155,7 +155,7 @@ "blockNumber": "334859834", "timestamp": "1746789030" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -188,7 +188,7 @@ "blockNumber": "336391727", "timestamp": "1747174470" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -221,7 +221,7 @@ "blockNumber": "334940670", "timestamp": "1746809370" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -254,7 +254,7 @@ "blockNumber": "336400851", "timestamp": "1747176775" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -287,7 +287,7 @@ "blockNumber": "335915708", "timestamp": "1747054375" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -320,7 +320,7 @@ "blockNumber": "334657304", "timestamp": "1746738314" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -353,7 +353,7 @@ "blockNumber": "335588899", "timestamp": "1746972274" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -386,7 +386,7 @@ "blockNumber": "335029437", "timestamp": "1746831755" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -419,7 +419,7 @@ "blockNumber": "336187596", "timestamp": "1747122921" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -452,7 +452,7 @@ "blockNumber": "334563045", "timestamp": "1746714697" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -485,7 +485,7 @@ "blockNumber": "336331535", "timestamp": "1747159259" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -518,7 +518,7 @@ "blockNumber": "334592618", "timestamp": "1746722095" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -551,7 +551,7 @@ "blockNumber": "334858727", "timestamp": "1746788754" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -584,7 +584,7 @@ "blockNumber": "336620712", "timestamp": "1747232203" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -617,7 +617,7 @@ "blockNumber": "334826798", "timestamp": "1746780768" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -650,7 +650,7 @@ "blockNumber": "334541615", "timestamp": "1746709336" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" } }, @@ -678,7 +678,7 @@ "blockNumber": "334620743", "timestamp": "1746729138" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -711,7 +711,7 @@ "blockNumber": "334940533", "timestamp": "1746809335" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -744,7 +744,7 @@ "blockNumber": "335281539", "timestamp": "1746895163" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -777,7 +777,7 @@ "blockNumber": "335002471", "timestamp": "1746824965" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -810,7 +810,7 @@ "blockNumber": "336384756", "timestamp": "1747172703" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -843,7 +843,7 @@ "blockNumber": "335612009", "timestamp": "1746978048" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -876,7 +876,7 @@ "blockNumber": "334688703", "timestamp": "1746746182" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -909,7 +909,7 @@ "blockNumber": "335865638", "timestamp": "1747041825" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -942,7 +942,7 @@ "blockNumber": "335864795", "timestamp": "1747041614" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -975,7 +975,7 @@ "blockNumber": "334819137", "timestamp": "1746778854" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1008,7 +1008,7 @@ "blockNumber": "335926287", "timestamp": "1747057021" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1041,7 +1041,7 @@ "blockNumber": "334540382", "timestamp": "1746709025" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1074,7 +1074,7 @@ "blockNumber": "336578385", "timestamp": "1747221545" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1097,7 +1097,7 @@ "symbol": "BO", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "ordersAsOutput": [ @@ -1139,7 +1139,7 @@ "blockNumber": "334940670", "timestamp": "1746809370" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1172,7 +1172,7 @@ "blockNumber": "334540382", "timestamp": "1746709025" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1205,7 +1205,7 @@ "blockNumber": "336620712", "timestamp": "1747232203" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1238,7 +1238,7 @@ "blockNumber": "334563045", "timestamp": "1746714697" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1271,7 +1271,7 @@ "blockNumber": "334858727", "timestamp": "1746788754" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1304,7 +1304,7 @@ "blockNumber": "336187596", "timestamp": "1747122921" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1337,7 +1337,7 @@ "blockNumber": "334859834", "timestamp": "1746789030" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1370,7 +1370,7 @@ "blockNumber": "334688703", "timestamp": "1746746182" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1403,7 +1403,7 @@ "blockNumber": "335029437", "timestamp": "1746831755" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1436,7 +1436,7 @@ "blockNumber": "334541709", "timestamp": "1746709358" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" } }, @@ -1464,7 +1464,7 @@ "blockNumber": "335612009", "timestamp": "1746978048" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1497,7 +1497,7 @@ "blockNumber": "334620743", "timestamp": "1746729138" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1530,7 +1530,7 @@ "blockNumber": "336196423", "timestamp": "1747125140" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1563,7 +1563,7 @@ "blockNumber": "334819137", "timestamp": "1746778854" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1596,7 +1596,7 @@ "blockNumber": "334540274", "timestamp": "1746708998" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" } }, @@ -1624,7 +1624,7 @@ "blockNumber": "336400851", "timestamp": "1747176775" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1657,7 +1657,7 @@ "blockNumber": "335588899", "timestamp": "1746972274" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1690,7 +1690,7 @@ "blockNumber": "335865638", "timestamp": "1747041825" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1723,7 +1723,7 @@ "blockNumber": "335864795", "timestamp": "1747041614" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1756,7 +1756,7 @@ "blockNumber": "336331535", "timestamp": "1747159259" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1789,7 +1789,7 @@ "blockNumber": "336391727", "timestamp": "1747174470" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1822,7 +1822,7 @@ "blockNumber": "334592618", "timestamp": "1746722095" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1855,7 +1855,7 @@ "blockNumber": "334657304", "timestamp": "1746738314" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1888,7 +1888,7 @@ "blockNumber": "335002471", "timestamp": "1746824965" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1921,7 +1921,7 @@ "blockNumber": "336578385", "timestamp": "1747221545" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1954,7 +1954,7 @@ "blockNumber": "335915708", "timestamp": "1747054375" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -1987,7 +1987,7 @@ "blockNumber": "336384756", "timestamp": "1747172703" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2020,7 +2020,7 @@ "blockNumber": "334940533", "timestamp": "1746809335" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2053,7 +2053,7 @@ "blockNumber": "335296669", "timestamp": "1746898967" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2086,7 +2086,7 @@ "blockNumber": "335281539", "timestamp": "1746895163" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2119,7 +2119,7 @@ "blockNumber": "334826798", "timestamp": "1746780768" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2152,7 +2152,7 @@ "blockNumber": "335926287", "timestamp": "1747057021" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2177,7 +2177,7 @@ "symbol": "NST", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "ordersAsOutput": [ @@ -2219,7 +2219,7 @@ "blockNumber": "334540334", "timestamp": "1746709013" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" } }, @@ -2247,7 +2247,7 @@ "blockNumber": "336196423", "timestamp": "1747125140" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2280,7 +2280,7 @@ "blockNumber": "335296669", "timestamp": "1746898967" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2313,7 +2313,7 @@ "blockNumber": "334859834", "timestamp": "1746789030" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2346,7 +2346,7 @@ "blockNumber": "336391727", "timestamp": "1747174470" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2379,7 +2379,7 @@ "blockNumber": "334940670", "timestamp": "1746809370" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2412,7 +2412,7 @@ "blockNumber": "336400851", "timestamp": "1747176775" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2445,7 +2445,7 @@ "blockNumber": "335915708", "timestamp": "1747054375" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2478,7 +2478,7 @@ "blockNumber": "334657304", "timestamp": "1746738314" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2511,7 +2511,7 @@ "blockNumber": "335588899", "timestamp": "1746972274" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2544,7 +2544,7 @@ "blockNumber": "335029437", "timestamp": "1746831755" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2577,7 +2577,7 @@ "blockNumber": "336187596", "timestamp": "1747122921" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2610,7 +2610,7 @@ "blockNumber": "334563045", "timestamp": "1746714697" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2643,7 +2643,7 @@ "blockNumber": "336331535", "timestamp": "1747159259" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2676,7 +2676,7 @@ "blockNumber": "334592618", "timestamp": "1746722095" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2709,7 +2709,7 @@ "blockNumber": "334858727", "timestamp": "1746788754" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2742,7 +2742,7 @@ "blockNumber": "336620712", "timestamp": "1747232203" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2775,7 +2775,7 @@ "blockNumber": "334826798", "timestamp": "1746780768" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2808,7 +2808,7 @@ "blockNumber": "334541615", "timestamp": "1746709336" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" } }, @@ -2836,7 +2836,7 @@ "blockNumber": "334620743", "timestamp": "1746729138" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2869,7 +2869,7 @@ "blockNumber": "334940533", "timestamp": "1746809335" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2902,7 +2902,7 @@ "blockNumber": "335281539", "timestamp": "1746895163" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2935,7 +2935,7 @@ "blockNumber": "335002471", "timestamp": "1746824965" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -2968,7 +2968,7 @@ "blockNumber": "336384756", "timestamp": "1747172703" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3001,7 +3001,7 @@ "blockNumber": "335612009", "timestamp": "1746978048" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3034,7 +3034,7 @@ "blockNumber": "334688703", "timestamp": "1746746182" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3067,7 +3067,7 @@ "blockNumber": "335865638", "timestamp": "1747041825" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3100,7 +3100,7 @@ "blockNumber": "335864795", "timestamp": "1747041614" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3133,7 +3133,7 @@ "blockNumber": "334819137", "timestamp": "1746778854" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3166,7 +3166,7 @@ "blockNumber": "335926287", "timestamp": "1747057021" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3199,7 +3199,7 @@ "blockNumber": "334540382", "timestamp": "1746709025" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3232,7 +3232,7 @@ "blockNumber": "336578385", "timestamp": "1747221545" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3255,7 +3255,7 @@ "symbol": "BO", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "ordersAsOutput": [ @@ -3297,7 +3297,7 @@ "blockNumber": "334940670", "timestamp": "1746809370" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3330,7 +3330,7 @@ "blockNumber": "334540382", "timestamp": "1746709025" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3363,7 +3363,7 @@ "blockNumber": "336620712", "timestamp": "1747232203" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3396,7 +3396,7 @@ "blockNumber": "334563045", "timestamp": "1746714697" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3429,7 +3429,7 @@ "blockNumber": "334858727", "timestamp": "1746788754" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3462,7 +3462,7 @@ "blockNumber": "336187596", "timestamp": "1747122921" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3495,7 +3495,7 @@ "blockNumber": "334859834", "timestamp": "1746789030" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3528,7 +3528,7 @@ "blockNumber": "334688703", "timestamp": "1746746182" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3561,7 +3561,7 @@ "blockNumber": "335029437", "timestamp": "1746831755" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3594,7 +3594,7 @@ "blockNumber": "334541709", "timestamp": "1746709358" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" } }, @@ -3622,7 +3622,7 @@ "blockNumber": "335612009", "timestamp": "1746978048" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3655,7 +3655,7 @@ "blockNumber": "334620743", "timestamp": "1746729138" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3688,7 +3688,7 @@ "blockNumber": "336196423", "timestamp": "1747125140" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3721,7 +3721,7 @@ "blockNumber": "334819137", "timestamp": "1746778854" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3754,7 +3754,7 @@ "blockNumber": "334540274", "timestamp": "1746708998" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" } }, @@ -3782,7 +3782,7 @@ "blockNumber": "336400851", "timestamp": "1747176775" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3815,7 +3815,7 @@ "blockNumber": "335588899", "timestamp": "1746972274" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3848,7 +3848,7 @@ "blockNumber": "335865638", "timestamp": "1747041825" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3881,7 +3881,7 @@ "blockNumber": "335864795", "timestamp": "1747041614" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3914,7 +3914,7 @@ "blockNumber": "336331535", "timestamp": "1747159259" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3947,7 +3947,7 @@ "blockNumber": "336391727", "timestamp": "1747174470" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -3980,7 +3980,7 @@ "blockNumber": "334592618", "timestamp": "1746722095" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -4013,7 +4013,7 @@ "blockNumber": "334657304", "timestamp": "1746738314" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -4046,7 +4046,7 @@ "blockNumber": "335002471", "timestamp": "1746824965" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -4079,7 +4079,7 @@ "blockNumber": "336578385", "timestamp": "1747221545" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -4112,7 +4112,7 @@ "blockNumber": "335915708", "timestamp": "1747054375" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -4145,7 +4145,7 @@ "blockNumber": "336384756", "timestamp": "1747172703" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -4178,7 +4178,7 @@ "blockNumber": "334940533", "timestamp": "1746809335" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -4211,7 +4211,7 @@ "blockNumber": "335296669", "timestamp": "1746898967" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -4244,7 +4244,7 @@ "blockNumber": "335281539", "timestamp": "1746895163" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -4277,7 +4277,7 @@ "blockNumber": "334826798", "timestamp": "1746780768" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -4310,7 +4310,7 @@ "blockNumber": "335926287", "timestamp": "1747057021" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -4322,7 +4322,7 @@ ] } ], - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "active": true, @@ -4450,7 +4450,7 @@ "symbol": "NST", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "ordersAsOutput": [ @@ -4492,7 +4492,7 @@ "blockNumber": "334536266", "timestamp": "1746707996" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -4525,7 +4525,7 @@ "blockNumber": "334536033", "timestamp": "1746707938" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" } }, @@ -4553,7 +4553,7 @@ "blockNumber": "334536376", "timestamp": "1746708024" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" } } @@ -4571,7 +4571,7 @@ "symbol": "Boop", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "ordersAsOutput": [ @@ -4613,7 +4613,7 @@ "blockNumber": "334536183", "timestamp": "1746707975" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" } }, @@ -4641,7 +4641,7 @@ "blockNumber": "334536426", "timestamp": "1746708036" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" } }, @@ -4669,7 +4669,7 @@ "blockNumber": "334536266", "timestamp": "1746707996" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -4694,7 +4694,7 @@ "symbol": "NST", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "ordersAsOutput": [ @@ -4736,7 +4736,7 @@ "blockNumber": "334536266", "timestamp": "1746707996" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -4769,7 +4769,7 @@ "blockNumber": "334536033", "timestamp": "1746707938" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" } }, @@ -4797,7 +4797,7 @@ "blockNumber": "334536376", "timestamp": "1746708024" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" } } @@ -4815,7 +4815,7 @@ "symbol": "Boop", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "ordersAsOutput": [ @@ -4857,7 +4857,7 @@ "blockNumber": "334536183", "timestamp": "1746707975" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" } }, @@ -4885,7 +4885,7 @@ "blockNumber": "334536426", "timestamp": "1746708036" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" } }, @@ -4913,7 +4913,7 @@ "blockNumber": "334536266", "timestamp": "1746707996" }, - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "trade": { @@ -4925,7 +4925,7 @@ ] } ], - "orderbook": { + "raindex": { "id": "0x550878091b2b1506069f61ae59e3a5484bca9166" }, "active": true, From d8586a2b2c56fc63084e79cc0c1bc1bcfe31c3bc Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Tue, 31 Mar 2026 16:40:37 +0400 Subject: [PATCH 22/69] Rename OrderBook to Raindex in build scripts and README Co-Authored-By: Claude Opus 4.6 (1M context) --- README.md | 2 +- prep-all.sh | 2 +- prep-webapp.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 59a6afb2e9..5f650dc2cd 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Raindex -Raindex is an open source, permissionless orderbook system with no fees or admin keys. +Raindex is an open source, permissionless onchain order system with no fees or admin keys. ## Repository Structure diff --git a/prep-all.sh b/prep-all.sh index f804953b75..39747db048 100755 --- a/prep-all.sh +++ b/prep-all.sh @@ -33,7 +33,7 @@ echo "Setting up UI components..." nix develop -i ${keep[@]} -c ob-ui-components-prelude echo "Building packages..." -nix develop -i ${keep[@]} -c bash -c '(npm run build -w @rainlanguage/orderbook)' +nix develop -i ${keep[@]} -c bash -c '(npm run build -w @rainlanguage/raindex)' nix develop -i ${keep[@]} -c bash -c '(npm run build -w @rainlanguage/ui-components && npm run build -w @rainlanguage/webapp)' # Temporarily disable command echoing diff --git a/prep-webapp.sh b/prep-webapp.sh index 0fd52e7a26..2b212165a5 100755 --- a/prep-webapp.sh +++ b/prep-webapp.sh @@ -32,7 +32,7 @@ echo "Preparing base setup..." rm -rf target || true echo "Building packages..." -nix develop -i ${keep[@]} -c bash -c '(npm run build -w @rainlanguage/orderbook)' +nix develop -i ${keep[@]} -c bash -c '(npm run build -w @rainlanguage/raindex)' rm -rf target || true From edaa3e93a1d2eedccdc8220d004144d877cb1a98 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Tue, 31 Mar 2026 16:44:08 +0400 Subject: [PATCH 23/69] Remove stale OrderBook rename note from foundry.toml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RaindexV6 confirmed at 23,437 bytes — identical to pre-rename. Co-Authored-By: Claude Opus 4.6 (1M context) --- foundry.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/foundry.toml b/foundry.toml index 3212810d14..57fc4ef680 100644 --- a/foundry.toml +++ b/foundry.toml @@ -20,8 +20,6 @@ optimizer = true # Lowered from 1000000 → 1000 → 800 to stay under the EIP-170 24KB contract # size limit. At 1000 runs RaindexV6 was 24,650 bytes (74 over); at 800 it # is 23,437 bytes (1,139 under). -# NOTE: the size was measured when the contract was named OrderBookV6; -# after the rename to RaindexV6 the bytecode is identical. optimizer_runs = 800 bytecode_hash = "none" From 85ed352fb516837db0afec798a9d0bce9f58931b Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Tue, 31 Mar 2026 16:51:01 +0400 Subject: [PATCH 24/69] Regenerate package-lock.json for raindex package rename Co-Authored-By: Claude Opus 4.6 (1M context) --- package-lock.json | 112 +++++++++++++++++++++++++++++++--------------- 1 file changed, 75 insertions(+), 37 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1373c977af..bc267ef199 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ ], "dependencies": { "@fast-check/vitest": "0.2.0", - "@rainlanguage/orderbook": "workspace:*", + "@rainlanguage/raindex": "workspace:*", "@rainlanguage/sqlite-web": "^0.0.2", "@rainlanguage/ui-components": "workspace:*", "@reown/appkit": "1.6.4", @@ -2980,8 +2980,8 @@ "node": ">=22" } }, - "node_modules/@rainlanguage/orderbook": { - "resolved": "packages/orderbook", + "node_modules/@rainlanguage/raindex": { + "resolved": "packages/raindex", "link": true }, "node_modules/@rainlanguage/sqlite-web": { @@ -8281,9 +8281,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.5.tgz", - "integrity": "sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -10470,12 +10470,12 @@ } }, "node_modules/foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "license": "ISC", "dependencies": { - "cross-spawn": "^7.0.0", + "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" }, "engines": { @@ -17675,8 +17675,8 @@ } } }, - "packages/orderbook": { - "name": "@rainlanguage/orderbook", + "packages/raindex": { + "name": "@rainlanguage/raindex", "version": "0.0.1-alpha.229", "license": "LicenseRef-DCL-1.0", "dependencies": { @@ -17690,22 +17690,50 @@ "node": ">=22" } }, - "packages/orderbook/node_modules/brace-expansion": { - "version": "2.0.1", + "packages/raindex/node_modules/@isaacs/cliui": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz", + "integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "packages/raindex/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "packages/raindex/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" } }, - "packages/orderbook/node_modules/glob": { - "version": "11.0.0", + "packages/raindex/node_modules/glob": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", + "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^4.0.1", - "minimatch": "^10.0.0", + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" @@ -17720,12 +17748,14 @@ "url": "https://github.com/sponsors/isaacs" } }, - "packages/orderbook/node_modules/jackspeak": { - "version": "4.0.2", + "packages/raindex/node_modules/jackspeak": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.2.3.tgz", + "integrity": "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { - "@isaacs/cliui": "^8.0.2" + "@isaacs/cliui": "^9.0.0" }, "engines": { "node": "20 || >=22" @@ -17734,30 +17764,36 @@ "url": "https://github.com/sponsors/isaacs" } }, - "packages/orderbook/node_modules/lru-cache": { - "version": "11.0.2", + "packages/raindex/node_modules/lru-cache": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "engines": { "node": "20 || >=22" } }, - "packages/orderbook/node_modules/minimatch": { - "version": "10.0.1", + "packages/raindex/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^5.0.5" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "packages/orderbook/node_modules/path-scurry": { - "version": "2.0.0", + "packages/raindex/node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -17765,14 +17801,16 @@ "minipass": "^7.1.2" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "packages/orderbook/node_modules/rimraf": { + "packages/raindex/node_modules/rimraf": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", + "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", "dev": true, "license": "ISC", "dependencies": { @@ -17798,7 +17836,7 @@ "@fontsource/dm-sans": "5.1.0", "@imask/svelte": "7.6.1", "@observablehq/plot": "0.6.16", - "@rainlanguage/orderbook": "0.0.1-alpha.229", + "@rainlanguage/raindex": "0.0.1-alpha.229", "@reown/appkit": "1.6.4", "@reown/appkit-adapter-wagmi": "1.6.4", "@sentry/sveltekit": "7.120.0", From a8218c6c49011e9d3e31bf57c3e8e61d4cc049d4 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Tue, 31 Mar 2026 19:31:13 +0400 Subject: [PATCH 25/69] Regenerate sub-parser pointers for raindex word rename MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rainlang word "orderbook" is now "raindex" — this is a breaking change for existing rainlang expressions. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/generated/RaindexV6SubParser.pointers.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/generated/RaindexV6SubParser.pointers.sol b/src/generated/RaindexV6SubParser.pointers.sol index cf544a70f1..8c3ae22b2b 100644 --- a/src/generated/RaindexV6SubParser.pointers.sol +++ b/src/generated/RaindexV6SubParser.pointers.sol @@ -10,22 +10,22 @@ pragma solidity ^0.8.25; // file needs the contract to exist so that it can be compiled. /// @dev Hash of the known bytecode. -bytes32 constant BYTECODE_HASH = bytes32(0xbaa5fe0edc004259f0f5e3e5e8a11fab9ae8325b4be2f644cc5f287900a99c44); +bytes32 constant BYTECODE_HASH = bytes32(0x78d0f0b8b03d9e9e6cd09a013754032a57cb688a13a98cb130df43d282ead580); /// @dev The deterministic deploy address of the contract when deployed via /// the Zoltu factory. -address constant DEPLOYED_ADDRESS = address(0xC17693a98370970D8Ec2d47d0cc37E847f035710); +address constant DEPLOYED_ADDRESS = address(0x6E81D70fD7801Cf21DD177f82c2e5BCffb86321E); /// @dev The creation bytecode of the contract. bytes constant CREATION_CODE = - hex"6080604052348015600e575f80fd5b506125798061001c5f395ff3fe608060405234801561000f575f80fd5b506004361061007a575f3560e01c80636f5aa28d116100585780636f5aa28d146100dd578063c6c0cbb61461010b578063ccf4477514610135578063d6d8c9a814610148575f80fd5b806301ffc9a71461007e578063336284d4146100a6578063570c7a63146100bb575b5f80fd5b61009161008c366004612159565b610150565b60405190151581526020015b60405180910390f35b6100ae6101d7565b60405161009d91906121b5565b6100ce6100c93660046121db565b610b58565b60405161009d93929190612285565b6040517f339d2c0f76e1042e14b7e006217f629d71d489d753712f95756f882f3779757c815260200161009d565b61011e6101193660046121db565b610c9c565b60408051921515835260208301919091520161009d565b60408051602081019091525f81526100ae565b6100ae610cd4565b5f6001600160e01b031982166391ccb1d560e01b148061018057506001600160e01b03198216636f5aa28d60e01b145b8061019b57506001600160e01b03198216631a2c8edd60e01b145b806101b657506001600160e01b03198216630cd8a13560e21b145b806101d157506301ffc9a760e01b6001600160e01b03198316145b92915050565b60605f6101e6600460016122f6565b6101f19060026122f6565b6101fc9060016122f6565b6102079060016122f6565b6001600160401b0381111561021e5761021e6121c7565b60405190808252806020026020018201604052801561025157816020015b606081526020019060019003908161023c5790505b50604080516002808252606082019092529192505f9190816020015b61214f81526020019060019003908161026d5790505090506115f2815f8151811061029a5761029a612309565b60200260200101906001600160401b031690816001600160401b03168152505061160f816001815181106102d0576102d0612309565b6001600160401b039290921660209283029190910190910152604080516003808252608082019092525f91816020015b61214f81526020019060019003908161030057905050905061161e815f8151811061032d5761032d612309565b60200260200101906001600160401b031690816001600160401b03168152505061162d8160018151811061036357610363612309565b60200260200101906001600160401b031690816001600160401b03168152505061163c8160028151811061039957610399612309565b6001600160401b039290921660209283029190910190910152604080516002808252606082019092525f91816020015b61214f8152602001906001900390816103c957905050905061164c815f815181106103f6576103f6612309565b60200260200101906001600160401b031690816001600160401b03168152505061165b8160018151811061042c5761042c612309565b6001600160401b03929092166020928302919091019091015260408051600580825260c082019092525f91816020015b61214f81526020019060019003908161045c57905050905061166b815f8151811061048957610489612309565b60200260200101906001600160401b031690816001600160401b03168152505061167a816001815181106104bf576104bf612309565b60200260200101906001600160401b031690816001600160401b03168152505061168a816002815181106104f5576104f5612309565b60200260200101906001600160401b031690816001600160401b03168152505061169a8160038151811061052b5761052b612309565b60200260200101906001600160401b031690816001600160401b0316815250506116a98160048151811061056157610561612309565b6001600160401b03929092166020928302919091019091015260408051600580825260c082019092525f91816020015b61214f8152602001906001900390816105915790505090506116b9815f815181106105be576105be612309565b60200260200101906001600160401b031690816001600160401b0316815250506116c8816001815181106105f4576105f4612309565b60200260200101906001600160401b031690816001600160401b0316815250506116d88160028151811061062a5761062a612309565b60200260200101906001600160401b031690816001600160401b0316815250506116e88160038151811061066057610660612309565b60200260200101906001600160401b031690816001600160401b0316815250506116f88160048151811061069657610696612309565b6001600160401b0392909216602092830291909101909101526040805160018082528183019092525f91816020015b61214f8152602001906001900390816106c5579050509050611707815f815181106106f2576106f2612309565b6001600160401b0392909216602092830291909101909101526040805160018082528183019092525f91816020015b61214f815260200190600190039081610721579050509050611716815f8151811061074e5761074e612309565b60200260200101906001600160401b031690816001600160401b03168152505086885f8151811061078157610781612309565b602002602001018190525085886001815181106107a0576107a0612309565b602002602001018190525084886002815181106107bf576107bf612309565b602002602001018190525083886003815181106107de576107de612309565b602002602001018190525082886004815181106107fd576107fd612309565b6020026020010181905250818860058151811061081c5761081c612309565b6020026020010181905250808860068151811061083b5761083b612309565b602090810291909101015260408051600580825260c082019092525f91816020015b61214f81526020019060019003908161085d5790505090506115f2815f8151811061088a5761088a612309565b60200260200101906001600160401b031690816001600160401b03168152505061161e816001815181106108c0576108c0612309565b60200260200101906001600160401b031690816001600160401b03168152505061162d816002815181106108f6576108f6612309565b60200260200101906001600160401b031690816001600160401b03168152505061163c8160038151811061092c5761092c612309565b60200260200101906001600160401b031690816001600160401b03168152505061174b8160048151811061096257610962612309565b6001600160401b03909216602092830291909101909101528089610988600660016122f6565b8151811061099857610998612309565b602090810291909101015260408051600680825260e082019092525f91816020015b61214f8152602001906001900390816109ba5790505090506115f2815f815181106109e7576109e7612309565b60200260200101906001600160401b031690816001600160401b03168152505061161e81600181518110610a1d57610a1d612309565b60200260200101906001600160401b031690816001600160401b03168152505061162d81600281518110610a5357610a53612309565b60200260200101906001600160401b031690816001600160401b03168152505061163c81600381518110610a8957610a89612309565b60200260200101906001600160401b031690816001600160401b03168152505061174b81600481518110610abf57610abf612309565b60200260200101906001600160401b031690816001600160401b03168152505061175b81600581518110610af557610af5612309565b6001600160401b0390921660209283029190910190910152808a610b1b600660026122f6565b81518110610b2b57610b2b612309565b602090810291909101015289610b48610b438261176b565b6117cd565b9b50505050505050505050505090565b5f6060805f805f610b7887610b6b61185c565b610b7361187c565b61189c565b9250925092505f610b8e82610220015160200190565b90505f8261022001515182610ba391906122f6565b90505f610bc183836f07fffffe0000000003ff20000000000061198d565b80925081945050505f80610bda86610240015184611a29565b915091508115610c6f575f610bef8783611b00565b905061214f5f610bfd611b2f565b90505f60028251610c0e9190612331565b9050808510610c3f576040516303bdd1b160e51b815260048101869052602481018290526044015b60405180910390fd5b6001850160020282015161ffff169250610c588c8c8686565b9e509e509e50505050505050505050505050610c95565b5050604080515f80825281830190925260208101828152919a5090985096505050505050505b9193909250565b5f805f805f610cc4866002810151815160228084019461ffff93909316840101920160200190565b505f988998509650505050505050565b60605f610ce3600460016122f6565b610cee9060026122f6565b610cf99060016122f6565b610d049060016122f6565b6001600160401b03811115610d1b57610d1b6121c7565b604051908082528060200260200182016040528015610d4e57816020015b6060815260200190600190039081610d395790505b50604080516002808252606082019092529192505f9190816020015b61214f815260200190600190039081610d6a579050509050611b4f815f81518110610d9757610d97612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600181518110610dcd57610dcd612309565b6001600160401b039290921660209283029190910190910152604080516003808252608082019092525f91816020015b61214f815260200190600190039081610dfd579050509050611b4f815f81518110610e2a57610e2a612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600181518110610e6057610e60612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600281518110610e9657610e96612309565b6001600160401b039290921660209283029190910190910152604080516002808252606082019092525f91816020015b61214f815260200190600190039081610ec6579050509050611b4f815f81518110610ef357610ef3612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600181518110610f2957610f29612309565b6001600160401b03929092166020928302919091019091015260408051600580825260c082019092525f91816020015b61214f815260200190600190039081610f59579050509050611b4f815f81518110610f8657610f86612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600181518110610fbc57610fbc612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600281518110610ff257610ff2612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160038151811061102857611028612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160048151811061105e5761105e612309565b6001600160401b03929092166020928302919091019091015260408051600580825260c082019092525f91816020015b61214f81526020019060019003908161108e579050509050611b4f815f815181106110bb576110bb612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f816001815181106110f1576110f1612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160028151811061112757611127612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160038151811061115d5761115d612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160048151811061119357611193612309565b6001600160401b0392909216602092830291909101909101526040805160018082528183019092525f91816020015b61214f8152602001906001900390816111c2579050509050611b78815f815181106111ef576111ef612309565b6001600160401b0392909216602092830291909101909101526040805160018082528183019092525f91816020015b61214f81526020019060019003908161121e579050509050611c14815f8151811061124b5761124b612309565b60200260200101906001600160401b031690816001600160401b03168152505086885f8151811061127e5761127e612309565b6020026020010181905250858860018151811061129d5761129d612309565b602002602001018190525084886002815181106112bc576112bc612309565b602002602001018190525083886003815181106112db576112db612309565b602002602001018190525082886004815181106112fa576112fa612309565b6020026020010181905250818860058151811061131957611319612309565b6020026020010181905250808860068151811061133857611338612309565b602090810291909101015260408051600580825260c082019092525f91816020015b61214f81526020019060019003908161135a579050509050611b4f815f8151811061138757611387612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f816001815181106113bd576113bd612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f816002815181106113f3576113f3612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160038151811061142957611429612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160048151811061145f5761145f612309565b6001600160401b03909216602092830291909101909101528089611485600660016122f6565b8151811061149557611495612309565b602090810291909101015260408051600680825260e082019092525f91816020015b61214f8152602001906001900390816114b7579050509050611b4f815f815181106114e4576114e4612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160018151811061151a5761151a612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160028151811061155057611550612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160038151811061158657611586612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f816004815181106115bc576115bc612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600581518110610af557610af5612309565b5f6060806116005f80611ccc565b92509250925093509350939050565b5f6060806116005f6001611ccc565b5f60608061160060015f611ccc565b5f606080611600600180611ccc565b5f60608061160060016002611ccc565b5f60608061160060025f611ccc565b5f60608061160060026001611ccc565b5f60608061160060035f611ccc565b5f60608061160060036001611ccc565b5f60608061160060036002611ccc565b5f606080611600600380611ccc565b5f60608061160060036004611ccc565b5f60608061160060045f611ccc565b5f60608061160060046001611ccc565b5f60608061160060046002611ccc565b5f60608061160060046003611ccc565b5f606080611600600480611ccc565b5f606080611600600585611ccc565b5f60608060ff80851690600886901c1661173a6117348360066122f6565b82611ccc565b945094509450505093509350939050565b5f60608061160060016003611ccc565b5f60608061160060016004611ccc565b60605f61177783611d4e565b9050606060405190506020820260200181016040528181526020840160208551028101602083015b818310156117c257602083515102806020855101835e602093909301920161179f565b509195945050505050565b60605f82516002026001600160401b038111156117ec576117ec6121c7565b6040519080825280601f01601f191660200182016040528015611816576020820181803683370190505b50905061ffff80196020850160208651028101600285015b818310156118505780518351861690851617815260209092019160020161182e565b50939695505050505050565b60606040518060c00160405280609a81526020016124a3609a9139905090565b60606040518060600160405280603c8152602001612467603c9139905090565b5f8061192b6040518061026001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f80191681526020015f81526020015f81526020015f81526020015f81526020015f81526020015f80191681526020016060815260200160608152602001606081526020015f815260200160608152602001606081525090565b606061ffff600288015116935060ff600388015116925061ffff60058801511660058801975080885260208101880191505061197787878760405180602001604052805f815250611d7c565b915080826101e001819052505093509350939050565b5f8080600181878703602081116119a457806119a7565b60205b915050875192505b8519600184841a1b161581831016156119cd576001820191506119af565b9681019660208290036008810293841c90931b92611a185760408051602081018590520160408051601f198184030181529082905263e47fe8b760e01b8252610c36916004016121b5565b50869350909150505b935093915050565b600182810180515f928392600560ff93909316602102870192830192909101835b81831015611aee5760018301516021909301805190935f90819060ff168180611a73838e611f2d565b915091508186165f03611a95575f809b509b5050505050505050505050611af9565b5f87611aa5600185038916611f58565b016004028b015195505062ffffff9081169350841683039150611ad99050575060019750601c1a9550611af9945050505050565b611ae283611f58565b84019350505050611a4a565b5f8095509550505050505b9250929050565b6101c08201516002828102820101516101e08401515f9261ffff9092169190611b269083565b95945050505050565b60606040518060600160405280603c815260200161253d603c9139905090565b5f81515f14611b71576040516304f8b58160e51b815260040160405180910390fd5b505f919050565b5f8151600103611bd5575060208101516001600160e01b038116601b0b60e082901d5f611ba6838383612011565b905061ffff811115611bcb57604051631e4e01d760e21b815260040160405180910390fd5b9250611c0f915050565b81515f03611bf657604051630f16066b60e41b815260040160405180910390fd5b604051630358cd2160e31b815260040160405180910390fd5b919050565b5f8151600203611ca957602082015160408301516001600160e01b038216601b0b60e083901d5f611c46838383612011565b6001600160e01b038516601b0b935060e085901d925090505f611c6a848483612011565b905060ff821180611c7b575060ff81115b15611c9957604051631e4e01d760e21b815260040160405180910390fd5b60081b179450611c0f9350505050565b600282511015611bf657604051630f16066b60e41b815260040160405180910390fd5b5f60608060ff851180611cdf575060ff84115b15611d0757604051639b0f326160e01b81526004810186905260248101859052604401610c36565b6040805160248101909152600386602383015385602283015360106021830153806020830153506004815260408051602081019091525f8152600197919650945092505050565b5f60208201602083510281015b80821015611d755781515183019250602082019150611d5b565b5050919050565b611e096040518061026001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f80191681526020015f81526020015f81526020015f81526020015f81526020015f81526020015f80191681526020016060815260200160608152602001606081526020015f815260200160608152602001606081525090565b5f6040518061026001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f801b81526020015f8152602001600481526020015f81526020015f81526020015f81526020015f801b815260200184815260200185815260200160046001600160401b03811115611e8e57611e8e6121c7565b604051908082528060200260200182016040528015611eb7578160200160208202803683370190505b5081525f602080830182905260408084018b905260609384018a90528051601f01601f19168281528083018252835161ffff191681178452855290840182905283018190529082018190526080820181905260a08201819052610120820181905261014082018190526102008201529050611b26565b5f80825f528360205360215f2090506001815f1a1b915062ffffff8116611af9575060019250929050565b5f5f198203611f6a5750610100919050565b507f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f7f5555555555555555555555555555555555555555555555555555555555555555600183901c16909103600281901c7f3333333333333333333333333333333333333333333333333333333333333333908116911601600481901c01167f01010101010101010101010101010101010101010101010101010101010101010260f81c90565b5f805f61201f868686612053565b915091508061204a5760405162bc8ecf60e31b81526004810187905260248101869052604401610c36565b50949350505050565b5f805f85121561208057604051634a7d166b60e01b81526004810186905260248101859052604401610c36565b845f0361209257505f90506001611a21565b8460ff84168501858112156120c45760405163d556b11160e01b81526004810188905260248101879052604401610c36565b5f805f83121561211057604c198312156120e7575f809550955050505050611a21565b825f03600a0a91508184816120fe576120fe61231d565b0495505084029091149150611a219050565b5f83131561213f5761212383600a612430565b915061212f828561243b565b955060019450611a219350505050565b8360019550955050505050611a21565b612157612452565b565b5f60208284031215612169575f80fd5b81356001600160e01b031981168114612180575f80fd5b9392505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6121806020830184612187565b634e487b7160e01b5f52604160045260245ffd5b5f602082840312156121eb575f80fd5b81356001600160401b0380821115612201575f80fd5b818401915084601f830112612214575f80fd5b813581811115612226576122266121c7565b604051601f8201601f19908116603f0116810190838211818310171561224e5761224e6121c7565b81604052828152876020848701011115612266575f80fd5b826020860160208301375f928101602001929092525095945050505050565b83151581525f6020606060208401526122a16060840186612187565b8381036040850152845180825260208087019201905f5b818110156122d4578351835292840192918401916001016122b8565b509098975050505050505050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156101d1576101d16122e2565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601260045260245ffd5b5f8261234b57634e487b7160e01b5f52601260045260245ffd5b500490565b600181815b8085111561238a57815f1904821115612370576123706122e2565b8085161561237d57918102915b93841c9390800290612355565b509250929050565b5f826123a0575060016101d1565b816123ac57505f6101d1565b81600181146123c257600281146123cc576123e8565b60019150506101d1565b60ff8411156123dd576123dd6122e2565b50506001821b6101d1565b5060208310610133831016604e8410600b841016171561240b575081810a6101d1565b6124158383612350565b805f1904821115612428576124286122e2565b029392505050565b5f6121808383612392565b80820281158282048414176101d1576101d16122e2565b634e487b7160e01b5f52605160045260245ffdfe1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b781c141b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f0101080010800082000100010480300038412a001800080010020004200004002018038ff54900cc66c60616592209895f0b16fec9301a02e0920c5bfe561c216092011c4c610b1974270f844db208bcd3bf1d989376111049db13b93430190ae9a00af82a7805c138f40d28083f0742ef2104d561fd1415a13317716a6118d260cc107b9bfc0eec7ade15cba2891b6b14a512792bdb02e0f14715f2160f161e162d163c164c165b166b167a168a169a16a916b916c816d816e816f81707171615f2161e162d163c174b15f2161e162d163c174b175b"; + hex"6080604052348015600e575f80fd5b506125798061001c5f395ff3fe608060405234801561000f575f80fd5b506004361061007a575f3560e01c80636f5aa28d116100585780636f5aa28d146100dd578063c6c0cbb61461010b578063ccf4477514610135578063d6d8c9a814610148575f80fd5b806301ffc9a71461007e578063336284d4146100a6578063570c7a63146100bb575b5f80fd5b61009161008c366004612159565b610150565b60405190151581526020015b60405180910390f35b6100ae6101d7565b60405161009d91906121b5565b6100ce6100c93660046121db565b610b58565b60405161009d93929190612285565b6040517fdc6156fd1b9fda1ce642d416969c2f632029b10b9e3864fbde264f391c51bdee815260200161009d565b61011e6101193660046121db565b610c9c565b60408051921515835260208301919091520161009d565b60408051602081019091525f81526100ae565b6100ae610cd4565b5f6001600160e01b031982166391ccb1d560e01b148061018057506001600160e01b03198216636f5aa28d60e01b145b8061019b57506001600160e01b03198216631a2c8edd60e01b145b806101b657506001600160e01b03198216630cd8a13560e21b145b806101d157506301ffc9a760e01b6001600160e01b03198316145b92915050565b60605f6101e6600460016122f6565b6101f19060026122f6565b6101fc9060016122f6565b6102079060016122f6565b6001600160401b0381111561021e5761021e6121c7565b60405190808252806020026020018201604052801561025157816020015b606081526020019060019003908161023c5790505b50604080516002808252606082019092529192505f9190816020015b61214f81526020019060019003908161026d5790505090506115f2815f8151811061029a5761029a612309565b60200260200101906001600160401b031690816001600160401b03168152505061160f816001815181106102d0576102d0612309565b6001600160401b039290921660209283029190910190910152604080516003808252608082019092525f91816020015b61214f81526020019060019003908161030057905050905061161e815f8151811061032d5761032d612309565b60200260200101906001600160401b031690816001600160401b03168152505061162d8160018151811061036357610363612309565b60200260200101906001600160401b031690816001600160401b03168152505061163c8160028151811061039957610399612309565b6001600160401b039290921660209283029190910190910152604080516002808252606082019092525f91816020015b61214f8152602001906001900390816103c957905050905061164c815f815181106103f6576103f6612309565b60200260200101906001600160401b031690816001600160401b03168152505061165b8160018151811061042c5761042c612309565b6001600160401b03929092166020928302919091019091015260408051600580825260c082019092525f91816020015b61214f81526020019060019003908161045c57905050905061166b815f8151811061048957610489612309565b60200260200101906001600160401b031690816001600160401b03168152505061167a816001815181106104bf576104bf612309565b60200260200101906001600160401b031690816001600160401b03168152505061168a816002815181106104f5576104f5612309565b60200260200101906001600160401b031690816001600160401b03168152505061169a8160038151811061052b5761052b612309565b60200260200101906001600160401b031690816001600160401b0316815250506116a98160048151811061056157610561612309565b6001600160401b03929092166020928302919091019091015260408051600580825260c082019092525f91816020015b61214f8152602001906001900390816105915790505090506116b9815f815181106105be576105be612309565b60200260200101906001600160401b031690816001600160401b0316815250506116c8816001815181106105f4576105f4612309565b60200260200101906001600160401b031690816001600160401b0316815250506116d88160028151811061062a5761062a612309565b60200260200101906001600160401b031690816001600160401b0316815250506116e88160038151811061066057610660612309565b60200260200101906001600160401b031690816001600160401b0316815250506116f88160048151811061069657610696612309565b6001600160401b0392909216602092830291909101909101526040805160018082528183019092525f91816020015b61214f8152602001906001900390816106c5579050509050611707815f815181106106f2576106f2612309565b6001600160401b0392909216602092830291909101909101526040805160018082528183019092525f91816020015b61214f815260200190600190039081610721579050509050611716815f8151811061074e5761074e612309565b60200260200101906001600160401b031690816001600160401b03168152505086885f8151811061078157610781612309565b602002602001018190525085886001815181106107a0576107a0612309565b602002602001018190525084886002815181106107bf576107bf612309565b602002602001018190525083886003815181106107de576107de612309565b602002602001018190525082886004815181106107fd576107fd612309565b6020026020010181905250818860058151811061081c5761081c612309565b6020026020010181905250808860068151811061083b5761083b612309565b602090810291909101015260408051600580825260c082019092525f91816020015b61214f81526020019060019003908161085d5790505090506115f2815f8151811061088a5761088a612309565b60200260200101906001600160401b031690816001600160401b03168152505061161e816001815181106108c0576108c0612309565b60200260200101906001600160401b031690816001600160401b03168152505061162d816002815181106108f6576108f6612309565b60200260200101906001600160401b031690816001600160401b03168152505061163c8160038151811061092c5761092c612309565b60200260200101906001600160401b031690816001600160401b03168152505061174b8160048151811061096257610962612309565b6001600160401b03909216602092830291909101909101528089610988600660016122f6565b8151811061099857610998612309565b602090810291909101015260408051600680825260e082019092525f91816020015b61214f8152602001906001900390816109ba5790505090506115f2815f815181106109e7576109e7612309565b60200260200101906001600160401b031690816001600160401b03168152505061161e81600181518110610a1d57610a1d612309565b60200260200101906001600160401b031690816001600160401b03168152505061162d81600281518110610a5357610a53612309565b60200260200101906001600160401b031690816001600160401b03168152505061163c81600381518110610a8957610a89612309565b60200260200101906001600160401b031690816001600160401b03168152505061174b81600481518110610abf57610abf612309565b60200260200101906001600160401b031690816001600160401b03168152505061175b81600581518110610af557610af5612309565b6001600160401b0390921660209283029190910190910152808a610b1b600660026122f6565b81518110610b2b57610b2b612309565b602090810291909101015289610b48610b438261176b565b6117cd565b9b50505050505050505050505090565b5f6060805f805f610b7887610b6b61185c565b610b7361187c565b61189c565b9250925092505f610b8e82610220015160200190565b90505f8261022001515182610ba391906122f6565b90505f610bc183836f07fffffe0000000003ff20000000000061198d565b80925081945050505f80610bda86610240015184611a29565b915091508115610c6f575f610bef8783611b00565b905061214f5f610bfd611b2f565b90505f60028251610c0e9190612331565b9050808510610c3f576040516303bdd1b160e51b815260048101869052602481018290526044015b60405180910390fd5b6001850160020282015161ffff169250610c588c8c8686565b9e509e509e50505050505050505050505050610c95565b5050604080515f80825281830190925260208101828152919a5090985096505050505050505b9193909250565b5f805f805f610cc4866002810151815160228084019461ffff93909316840101920160200190565b505f988998509650505050505050565b60605f610ce3600460016122f6565b610cee9060026122f6565b610cf99060016122f6565b610d049060016122f6565b6001600160401b03811115610d1b57610d1b6121c7565b604051908082528060200260200182016040528015610d4e57816020015b6060815260200190600190039081610d395790505b50604080516002808252606082019092529192505f9190816020015b61214f815260200190600190039081610d6a579050509050611b4f815f81518110610d9757610d97612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600181518110610dcd57610dcd612309565b6001600160401b039290921660209283029190910190910152604080516003808252608082019092525f91816020015b61214f815260200190600190039081610dfd579050509050611b4f815f81518110610e2a57610e2a612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600181518110610e6057610e60612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600281518110610e9657610e96612309565b6001600160401b039290921660209283029190910190910152604080516002808252606082019092525f91816020015b61214f815260200190600190039081610ec6579050509050611b4f815f81518110610ef357610ef3612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600181518110610f2957610f29612309565b6001600160401b03929092166020928302919091019091015260408051600580825260c082019092525f91816020015b61214f815260200190600190039081610f59579050509050611b4f815f81518110610f8657610f86612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600181518110610fbc57610fbc612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600281518110610ff257610ff2612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160038151811061102857611028612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160048151811061105e5761105e612309565b6001600160401b03929092166020928302919091019091015260408051600580825260c082019092525f91816020015b61214f81526020019060019003908161108e579050509050611b4f815f815181106110bb576110bb612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f816001815181106110f1576110f1612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160028151811061112757611127612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160038151811061115d5761115d612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160048151811061119357611193612309565b6001600160401b0392909216602092830291909101909101526040805160018082528183019092525f91816020015b61214f8152602001906001900390816111c2579050509050611b78815f815181106111ef576111ef612309565b6001600160401b0392909216602092830291909101909101526040805160018082528183019092525f91816020015b61214f81526020019060019003908161121e579050509050611c14815f8151811061124b5761124b612309565b60200260200101906001600160401b031690816001600160401b03168152505086885f8151811061127e5761127e612309565b6020026020010181905250858860018151811061129d5761129d612309565b602002602001018190525084886002815181106112bc576112bc612309565b602002602001018190525083886003815181106112db576112db612309565b602002602001018190525082886004815181106112fa576112fa612309565b6020026020010181905250818860058151811061131957611319612309565b6020026020010181905250808860068151811061133857611338612309565b602090810291909101015260408051600580825260c082019092525f91816020015b61214f81526020019060019003908161135a579050509050611b4f815f8151811061138757611387612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f816001815181106113bd576113bd612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f816002815181106113f3576113f3612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160038151811061142957611429612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160048151811061145f5761145f612309565b6001600160401b03909216602092830291909101909101528089611485600660016122f6565b8151811061149557611495612309565b602090810291909101015260408051600680825260e082019092525f91816020015b61214f8152602001906001900390816114b7579050509050611b4f815f815181106114e4576114e4612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160018151811061151a5761151a612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160028151811061155057611550612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160038151811061158657611586612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f816004815181106115bc576115bc612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600581518110610af557610af5612309565b5f6060806116005f80611ccc565b92509250925093509350939050565b5f6060806116005f6001611ccc565b5f60608061160060015f611ccc565b5f606080611600600180611ccc565b5f60608061160060016002611ccc565b5f60608061160060025f611ccc565b5f60608061160060026001611ccc565b5f60608061160060035f611ccc565b5f60608061160060036001611ccc565b5f60608061160060036002611ccc565b5f606080611600600380611ccc565b5f60608061160060036004611ccc565b5f60608061160060045f611ccc565b5f60608061160060046001611ccc565b5f60608061160060046002611ccc565b5f60608061160060046003611ccc565b5f606080611600600480611ccc565b5f606080611600600585611ccc565b5f60608060ff80851690600886901c1661173a6117348360066122f6565b82611ccc565b945094509450505093509350939050565b5f60608061160060016003611ccc565b5f60608061160060016004611ccc565b60605f61177783611d4e565b9050606060405190506020820260200181016040528181526020840160208551028101602083015b818310156117c257602083515102806020855101835e602093909301920161179f565b509195945050505050565b60605f82516002026001600160401b038111156117ec576117ec6121c7565b6040519080825280601f01601f191660200182016040528015611816576020820181803683370190505b50905061ffff80196020850160208651028101600285015b818310156118505780518351861690851617815260209092019160020161182e565b50939695505050505050565b60606040518060c00160405280609a8152602001612467609a9139905090565b60606040518060600160405280603c8152602001612501603c9139905090565b5f8061192b6040518061026001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f80191681526020015f81526020015f81526020015f81526020015f81526020015f81526020015f80191681526020016060815260200160608152602001606081526020015f815260200160608152602001606081525090565b606061ffff600288015116935060ff600388015116925061ffff60058801511660058801975080885260208101880191505061197787878760405180602001604052805f815250611d7c565b915080826101e001819052505093509350939050565b5f8080600181878703602081116119a457806119a7565b60205b915050875192505b8519600184841a1b161581831016156119cd576001820191506119af565b9681019660208290036008810293841c90931b92611a185760408051602081018590520160408051601f198184030181529082905263e47fe8b760e01b8252610c36916004016121b5565b50869350909150505b935093915050565b600182810180515f928392600560ff93909316602102870192830192909101835b81831015611aee5760018301516021909301805190935f90819060ff168180611a73838e611f2d565b915091508186165f03611a95575f809b509b5050505050505050505050611af9565b5f87611aa5600185038916611f58565b016004028b015195505062ffffff9081169350841683039150611ad99050575060019750601c1a9550611af9945050505050565b611ae283611f58565b84019350505050611a4a565b5f8095509550505050505b9250929050565b6101c08201516002828102820101516101e08401515f9261ffff9092169190611b269083565b95945050505050565b60606040518060600160405280603c815260200161253d603c9139905090565b5f81515f14611b71576040516304f8b58160e51b815260040160405180910390fd5b505f919050565b5f8151600103611bd5575060208101516001600160e01b038116601b0b60e082901d5f611ba6838383612011565b905061ffff811115611bcb57604051631e4e01d760e21b815260040160405180910390fd5b9250611c0f915050565b81515f03611bf657604051630f16066b60e41b815260040160405180910390fd5b604051630358cd2160e31b815260040160405180910390fd5b919050565b5f8151600203611ca957602082015160408301516001600160e01b038216601b0b60e083901d5f611c46838383612011565b6001600160e01b038516601b0b935060e085901d925090505f611c6a848483612011565b905060ff821180611c7b575060ff81115b15611c9957604051631e4e01d760e21b815260040160405180910390fd5b60081b179450611c0f9350505050565b600282511015611bf657604051630f16066b60e41b815260040160405180910390fd5b5f60608060ff851180611cdf575060ff84115b15611d0757604051639b0f326160e01b81526004810186905260248101859052604401610c36565b6040805160248101909152600386602383015385602283015360106021830153806020830153506004815260408051602081019091525f8152600197919650945092505050565b5f60208201602083510281015b80821015611d755781515183019250602082019150611d5b565b5050919050565b611e096040518061026001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f80191681526020015f81526020015f81526020015f81526020015f81526020015f81526020015f80191681526020016060815260200160608152602001606081526020015f815260200160608152602001606081525090565b5f6040518061026001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f801b81526020015f8152602001600481526020015f81526020015f81526020015f81526020015f801b815260200184815260200185815260200160046001600160401b03811115611e8e57611e8e6121c7565b604051908082528060200260200182016040528015611eb7578160200160208202803683370190505b5081525f602080830182905260408084018b905260609384018a90528051601f01601f19168281528083018252835161ffff191681178452855290840182905283018190529082018190526080820181905260a08201819052610120820181905261014082018190526102008201529050611b26565b5f80825f528360205360215f2090506001815f1a1b915062ffffff8116611af9575060019250929050565b5f5f198203611f6a5750610100919050565b507f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f7f5555555555555555555555555555555555555555555555555555555555555555600183901c16909103600281901c7f3333333333333333333333333333333333333333333333333333333333333333908116911601600481901c01167f01010101010101010101010101010101010101010101010101010101010101010260f81c90565b5f805f61201f868686612053565b915091508061204a5760405162bc8ecf60e31b81526004810187905260248101869052604401610c36565b50949350505050565b5f805f85121561208057604051634a7d166b60e01b81526004810186905260248101859052604401610c36565b845f0361209257505f90506001611a21565b8460ff84168501858112156120c45760405163d556b11160e01b81526004810188905260248101879052604401610c36565b5f805f83121561211057604c198312156120e7575f809550955050505050611a21565b825f03600a0a91508184816120fe576120fe61231d565b0495505084029091149150611a219050565b5f83131561213f5761212383600a612430565b915061212f828561243b565b955060019450611a219350505050565b8360019550955050505050611a21565b612157612452565b565b5f60208284031215612169575f80fd5b81356001600160e01b031981168114612180575f80fd5b9392505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6121806020830184612187565b634e487b7160e01b5f52604160045260245ffd5b5f602082840312156121eb575f80fd5b81356001600160401b0380821115612201575f80fd5b818401915084601f830112612214575f80fd5b813581811115612226576122266121c7565b604051601f8201601f19908116603f0116810190838211818310171561224e5761224e6121c7565b81604052828152876020848701011115612266575f80fd5b826020860160208301375f928101602001929092525095945050505050565b83151581525f6020606060208401526122a16060840186612187565b8381036040850152845180825260208087019201905f5b818110156122d4578351835292840192918401916001016122b8565b509098975050505050505050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156101d1576101d16122e2565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601260045260245ffd5b5f8261234b57634e487b7160e01b5f52601260045260245ffd5b500490565b600181815b8085111561238a57815f1904821115612370576123706122e2565b8085161561237d57918102915b93841c9390800290612355565b509250929050565b5f826123a0575060016101d1565b816123ac57505f6101d1565b81600181146123c257600281146123cc576123e8565b60019150506101d1565b60ff8411156123dd576123dd6122e2565b50506001821b6101d1565b5060208310610133831016604e8410600b841016171561240b575081810a6101d1565b6124158383612350565b805f1904821115612428576124286122e2565b029392505050565b5f6121808383612392565b80820281158282048414176101d1576101d16122e2565b634e487b7160e01b5f52605160045260245ffdfe0101080010800082000100010480300038412a001810000010020004200004002018038ff54900cc66c60616592209895f0b16fec9301a02e0920c5bfe561c21609201e959460b1974270f844db208bcd3bf1d989376111049db13b93430190ae9a00af82a7805c138f40d28083f0742ef2104d561fd1415a13317716a6118d260cc107b9bfc0eec7ade15cba2891b6b14a512792bdb02e0f1471b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b781c141b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f15f2160f161e162d163c164c165b166b167a168a169a16a916b916c816d816e816f81707171615f2161e162d163c174b15f2161e162d163c174b175b"; /// @dev The runtime bytecode of the contract. bytes constant RUNTIME_CODE = - hex"608060405234801561000f575f80fd5b506004361061007a575f3560e01c80636f5aa28d116100585780636f5aa28d146100dd578063c6c0cbb61461010b578063ccf4477514610135578063d6d8c9a814610148575f80fd5b806301ffc9a71461007e578063336284d4146100a6578063570c7a63146100bb575b5f80fd5b61009161008c366004612159565b610150565b60405190151581526020015b60405180910390f35b6100ae6101d7565b60405161009d91906121b5565b6100ce6100c93660046121db565b610b58565b60405161009d93929190612285565b6040517f339d2c0f76e1042e14b7e006217f629d71d489d753712f95756f882f3779757c815260200161009d565b61011e6101193660046121db565b610c9c565b60408051921515835260208301919091520161009d565b60408051602081019091525f81526100ae565b6100ae610cd4565b5f6001600160e01b031982166391ccb1d560e01b148061018057506001600160e01b03198216636f5aa28d60e01b145b8061019b57506001600160e01b03198216631a2c8edd60e01b145b806101b657506001600160e01b03198216630cd8a13560e21b145b806101d157506301ffc9a760e01b6001600160e01b03198316145b92915050565b60605f6101e6600460016122f6565b6101f19060026122f6565b6101fc9060016122f6565b6102079060016122f6565b6001600160401b0381111561021e5761021e6121c7565b60405190808252806020026020018201604052801561025157816020015b606081526020019060019003908161023c5790505b50604080516002808252606082019092529192505f9190816020015b61214f81526020019060019003908161026d5790505090506115f2815f8151811061029a5761029a612309565b60200260200101906001600160401b031690816001600160401b03168152505061160f816001815181106102d0576102d0612309565b6001600160401b039290921660209283029190910190910152604080516003808252608082019092525f91816020015b61214f81526020019060019003908161030057905050905061161e815f8151811061032d5761032d612309565b60200260200101906001600160401b031690816001600160401b03168152505061162d8160018151811061036357610363612309565b60200260200101906001600160401b031690816001600160401b03168152505061163c8160028151811061039957610399612309565b6001600160401b039290921660209283029190910190910152604080516002808252606082019092525f91816020015b61214f8152602001906001900390816103c957905050905061164c815f815181106103f6576103f6612309565b60200260200101906001600160401b031690816001600160401b03168152505061165b8160018151811061042c5761042c612309565b6001600160401b03929092166020928302919091019091015260408051600580825260c082019092525f91816020015b61214f81526020019060019003908161045c57905050905061166b815f8151811061048957610489612309565b60200260200101906001600160401b031690816001600160401b03168152505061167a816001815181106104bf576104bf612309565b60200260200101906001600160401b031690816001600160401b03168152505061168a816002815181106104f5576104f5612309565b60200260200101906001600160401b031690816001600160401b03168152505061169a8160038151811061052b5761052b612309565b60200260200101906001600160401b031690816001600160401b0316815250506116a98160048151811061056157610561612309565b6001600160401b03929092166020928302919091019091015260408051600580825260c082019092525f91816020015b61214f8152602001906001900390816105915790505090506116b9815f815181106105be576105be612309565b60200260200101906001600160401b031690816001600160401b0316815250506116c8816001815181106105f4576105f4612309565b60200260200101906001600160401b031690816001600160401b0316815250506116d88160028151811061062a5761062a612309565b60200260200101906001600160401b031690816001600160401b0316815250506116e88160038151811061066057610660612309565b60200260200101906001600160401b031690816001600160401b0316815250506116f88160048151811061069657610696612309565b6001600160401b0392909216602092830291909101909101526040805160018082528183019092525f91816020015b61214f8152602001906001900390816106c5579050509050611707815f815181106106f2576106f2612309565b6001600160401b0392909216602092830291909101909101526040805160018082528183019092525f91816020015b61214f815260200190600190039081610721579050509050611716815f8151811061074e5761074e612309565b60200260200101906001600160401b031690816001600160401b03168152505086885f8151811061078157610781612309565b602002602001018190525085886001815181106107a0576107a0612309565b602002602001018190525084886002815181106107bf576107bf612309565b602002602001018190525083886003815181106107de576107de612309565b602002602001018190525082886004815181106107fd576107fd612309565b6020026020010181905250818860058151811061081c5761081c612309565b6020026020010181905250808860068151811061083b5761083b612309565b602090810291909101015260408051600580825260c082019092525f91816020015b61214f81526020019060019003908161085d5790505090506115f2815f8151811061088a5761088a612309565b60200260200101906001600160401b031690816001600160401b03168152505061161e816001815181106108c0576108c0612309565b60200260200101906001600160401b031690816001600160401b03168152505061162d816002815181106108f6576108f6612309565b60200260200101906001600160401b031690816001600160401b03168152505061163c8160038151811061092c5761092c612309565b60200260200101906001600160401b031690816001600160401b03168152505061174b8160048151811061096257610962612309565b6001600160401b03909216602092830291909101909101528089610988600660016122f6565b8151811061099857610998612309565b602090810291909101015260408051600680825260e082019092525f91816020015b61214f8152602001906001900390816109ba5790505090506115f2815f815181106109e7576109e7612309565b60200260200101906001600160401b031690816001600160401b03168152505061161e81600181518110610a1d57610a1d612309565b60200260200101906001600160401b031690816001600160401b03168152505061162d81600281518110610a5357610a53612309565b60200260200101906001600160401b031690816001600160401b03168152505061163c81600381518110610a8957610a89612309565b60200260200101906001600160401b031690816001600160401b03168152505061174b81600481518110610abf57610abf612309565b60200260200101906001600160401b031690816001600160401b03168152505061175b81600581518110610af557610af5612309565b6001600160401b0390921660209283029190910190910152808a610b1b600660026122f6565b81518110610b2b57610b2b612309565b602090810291909101015289610b48610b438261176b565b6117cd565b9b50505050505050505050505090565b5f6060805f805f610b7887610b6b61185c565b610b7361187c565b61189c565b9250925092505f610b8e82610220015160200190565b90505f8261022001515182610ba391906122f6565b90505f610bc183836f07fffffe0000000003ff20000000000061198d565b80925081945050505f80610bda86610240015184611a29565b915091508115610c6f575f610bef8783611b00565b905061214f5f610bfd611b2f565b90505f60028251610c0e9190612331565b9050808510610c3f576040516303bdd1b160e51b815260048101869052602481018290526044015b60405180910390fd5b6001850160020282015161ffff169250610c588c8c8686565b9e509e509e50505050505050505050505050610c95565b5050604080515f80825281830190925260208101828152919a5090985096505050505050505b9193909250565b5f805f805f610cc4866002810151815160228084019461ffff93909316840101920160200190565b505f988998509650505050505050565b60605f610ce3600460016122f6565b610cee9060026122f6565b610cf99060016122f6565b610d049060016122f6565b6001600160401b03811115610d1b57610d1b6121c7565b604051908082528060200260200182016040528015610d4e57816020015b6060815260200190600190039081610d395790505b50604080516002808252606082019092529192505f9190816020015b61214f815260200190600190039081610d6a579050509050611b4f815f81518110610d9757610d97612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600181518110610dcd57610dcd612309565b6001600160401b039290921660209283029190910190910152604080516003808252608082019092525f91816020015b61214f815260200190600190039081610dfd579050509050611b4f815f81518110610e2a57610e2a612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600181518110610e6057610e60612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600281518110610e9657610e96612309565b6001600160401b039290921660209283029190910190910152604080516002808252606082019092525f91816020015b61214f815260200190600190039081610ec6579050509050611b4f815f81518110610ef357610ef3612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600181518110610f2957610f29612309565b6001600160401b03929092166020928302919091019091015260408051600580825260c082019092525f91816020015b61214f815260200190600190039081610f59579050509050611b4f815f81518110610f8657610f86612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600181518110610fbc57610fbc612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600281518110610ff257610ff2612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160038151811061102857611028612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160048151811061105e5761105e612309565b6001600160401b03929092166020928302919091019091015260408051600580825260c082019092525f91816020015b61214f81526020019060019003908161108e579050509050611b4f815f815181106110bb576110bb612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f816001815181106110f1576110f1612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160028151811061112757611127612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160038151811061115d5761115d612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160048151811061119357611193612309565b6001600160401b0392909216602092830291909101909101526040805160018082528183019092525f91816020015b61214f8152602001906001900390816111c2579050509050611b78815f815181106111ef576111ef612309565b6001600160401b0392909216602092830291909101909101526040805160018082528183019092525f91816020015b61214f81526020019060019003908161121e579050509050611c14815f8151811061124b5761124b612309565b60200260200101906001600160401b031690816001600160401b03168152505086885f8151811061127e5761127e612309565b6020026020010181905250858860018151811061129d5761129d612309565b602002602001018190525084886002815181106112bc576112bc612309565b602002602001018190525083886003815181106112db576112db612309565b602002602001018190525082886004815181106112fa576112fa612309565b6020026020010181905250818860058151811061131957611319612309565b6020026020010181905250808860068151811061133857611338612309565b602090810291909101015260408051600580825260c082019092525f91816020015b61214f81526020019060019003908161135a579050509050611b4f815f8151811061138757611387612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f816001815181106113bd576113bd612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f816002815181106113f3576113f3612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160038151811061142957611429612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160048151811061145f5761145f612309565b6001600160401b03909216602092830291909101909101528089611485600660016122f6565b8151811061149557611495612309565b602090810291909101015260408051600680825260e082019092525f91816020015b61214f8152602001906001900390816114b7579050509050611b4f815f815181106114e4576114e4612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160018151811061151a5761151a612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160028151811061155057611550612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160038151811061158657611586612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f816004815181106115bc576115bc612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600581518110610af557610af5612309565b5f6060806116005f80611ccc565b92509250925093509350939050565b5f6060806116005f6001611ccc565b5f60608061160060015f611ccc565b5f606080611600600180611ccc565b5f60608061160060016002611ccc565b5f60608061160060025f611ccc565b5f60608061160060026001611ccc565b5f60608061160060035f611ccc565b5f60608061160060036001611ccc565b5f60608061160060036002611ccc565b5f606080611600600380611ccc565b5f60608061160060036004611ccc565b5f60608061160060045f611ccc565b5f60608061160060046001611ccc565b5f60608061160060046002611ccc565b5f60608061160060046003611ccc565b5f606080611600600480611ccc565b5f606080611600600585611ccc565b5f60608060ff80851690600886901c1661173a6117348360066122f6565b82611ccc565b945094509450505093509350939050565b5f60608061160060016003611ccc565b5f60608061160060016004611ccc565b60605f61177783611d4e565b9050606060405190506020820260200181016040528181526020840160208551028101602083015b818310156117c257602083515102806020855101835e602093909301920161179f565b509195945050505050565b60605f82516002026001600160401b038111156117ec576117ec6121c7565b6040519080825280601f01601f191660200182016040528015611816576020820181803683370190505b50905061ffff80196020850160208651028101600285015b818310156118505780518351861690851617815260209092019160020161182e565b50939695505050505050565b60606040518060c00160405280609a81526020016124a3609a9139905090565b60606040518060600160405280603c8152602001612467603c9139905090565b5f8061192b6040518061026001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f80191681526020015f81526020015f81526020015f81526020015f81526020015f81526020015f80191681526020016060815260200160608152602001606081526020015f815260200160608152602001606081525090565b606061ffff600288015116935060ff600388015116925061ffff60058801511660058801975080885260208101880191505061197787878760405180602001604052805f815250611d7c565b915080826101e001819052505093509350939050565b5f8080600181878703602081116119a457806119a7565b60205b915050875192505b8519600184841a1b161581831016156119cd576001820191506119af565b9681019660208290036008810293841c90931b92611a185760408051602081018590520160408051601f198184030181529082905263e47fe8b760e01b8252610c36916004016121b5565b50869350909150505b935093915050565b600182810180515f928392600560ff93909316602102870192830192909101835b81831015611aee5760018301516021909301805190935f90819060ff168180611a73838e611f2d565b915091508186165f03611a95575f809b509b5050505050505050505050611af9565b5f87611aa5600185038916611f58565b016004028b015195505062ffffff9081169350841683039150611ad99050575060019750601c1a9550611af9945050505050565b611ae283611f58565b84019350505050611a4a565b5f8095509550505050505b9250929050565b6101c08201516002828102820101516101e08401515f9261ffff9092169190611b269083565b95945050505050565b60606040518060600160405280603c815260200161253d603c9139905090565b5f81515f14611b71576040516304f8b58160e51b815260040160405180910390fd5b505f919050565b5f8151600103611bd5575060208101516001600160e01b038116601b0b60e082901d5f611ba6838383612011565b905061ffff811115611bcb57604051631e4e01d760e21b815260040160405180910390fd5b9250611c0f915050565b81515f03611bf657604051630f16066b60e41b815260040160405180910390fd5b604051630358cd2160e31b815260040160405180910390fd5b919050565b5f8151600203611ca957602082015160408301516001600160e01b038216601b0b60e083901d5f611c46838383612011565b6001600160e01b038516601b0b935060e085901d925090505f611c6a848483612011565b905060ff821180611c7b575060ff81115b15611c9957604051631e4e01d760e21b815260040160405180910390fd5b60081b179450611c0f9350505050565b600282511015611bf657604051630f16066b60e41b815260040160405180910390fd5b5f60608060ff851180611cdf575060ff84115b15611d0757604051639b0f326160e01b81526004810186905260248101859052604401610c36565b6040805160248101909152600386602383015385602283015360106021830153806020830153506004815260408051602081019091525f8152600197919650945092505050565b5f60208201602083510281015b80821015611d755781515183019250602082019150611d5b565b5050919050565b611e096040518061026001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f80191681526020015f81526020015f81526020015f81526020015f81526020015f81526020015f80191681526020016060815260200160608152602001606081526020015f815260200160608152602001606081525090565b5f6040518061026001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f801b81526020015f8152602001600481526020015f81526020015f81526020015f81526020015f801b815260200184815260200185815260200160046001600160401b03811115611e8e57611e8e6121c7565b604051908082528060200260200182016040528015611eb7578160200160208202803683370190505b5081525f602080830182905260408084018b905260609384018a90528051601f01601f19168281528083018252835161ffff191681178452855290840182905283018190529082018190526080820181905260a08201819052610120820181905261014082018190526102008201529050611b26565b5f80825f528360205360215f2090506001815f1a1b915062ffffff8116611af9575060019250929050565b5f5f198203611f6a5750610100919050565b507f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f7f5555555555555555555555555555555555555555555555555555555555555555600183901c16909103600281901c7f3333333333333333333333333333333333333333333333333333333333333333908116911601600481901c01167f01010101010101010101010101010101010101010101010101010101010101010260f81c90565b5f805f61201f868686612053565b915091508061204a5760405162bc8ecf60e31b81526004810187905260248101869052604401610c36565b50949350505050565b5f805f85121561208057604051634a7d166b60e01b81526004810186905260248101859052604401610c36565b845f0361209257505f90506001611a21565b8460ff84168501858112156120c45760405163d556b11160e01b81526004810188905260248101879052604401610c36565b5f805f83121561211057604c198312156120e7575f809550955050505050611a21565b825f03600a0a91508184816120fe576120fe61231d565b0495505084029091149150611a219050565b5f83131561213f5761212383600a612430565b915061212f828561243b565b955060019450611a219350505050565b8360019550955050505050611a21565b612157612452565b565b5f60208284031215612169575f80fd5b81356001600160e01b031981168114612180575f80fd5b9392505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6121806020830184612187565b634e487b7160e01b5f52604160045260245ffd5b5f602082840312156121eb575f80fd5b81356001600160401b0380821115612201575f80fd5b818401915084601f830112612214575f80fd5b813581811115612226576122266121c7565b604051601f8201601f19908116603f0116810190838211818310171561224e5761224e6121c7565b81604052828152876020848701011115612266575f80fd5b826020860160208301375f928101602001929092525095945050505050565b83151581525f6020606060208401526122a16060840186612187565b8381036040850152845180825260208087019201905f5b818110156122d4578351835292840192918401916001016122b8565b509098975050505050505050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156101d1576101d16122e2565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601260045260245ffd5b5f8261234b57634e487b7160e01b5f52601260045260245ffd5b500490565b600181815b8085111561238a57815f1904821115612370576123706122e2565b8085161561237d57918102915b93841c9390800290612355565b509250929050565b5f826123a0575060016101d1565b816123ac57505f6101d1565b81600181146123c257600281146123cc576123e8565b60019150506101d1565b60ff8411156123dd576123dd6122e2565b50506001821b6101d1565b5060208310610133831016604e8410600b841016171561240b575081810a6101d1565b6124158383612350565b805f1904821115612428576124286122e2565b029392505050565b5f6121808383612392565b80820281158282048414176101d1576101d16122e2565b634e487b7160e01b5f52605160045260245ffdfe1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b781c141b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f0101080010800082000100010480300038412a001800080010020004200004002018038ff54900cc66c60616592209895f0b16fec9301a02e0920c5bfe561c216092011c4c610b1974270f844db208bcd3bf1d989376111049db13b93430190ae9a00af82a7805c138f40d28083f0742ef2104d561fd1415a13317716a6118d260cc107b9bfc0eec7ade15cba2891b6b14a512792bdb02e0f14715f2160f161e162d163c164c165b166b167a168a169a16a916b916c816d816e816f81707171615f2161e162d163c174b15f2161e162d163c174b175b"; + hex"608060405234801561000f575f80fd5b506004361061007a575f3560e01c80636f5aa28d116100585780636f5aa28d146100dd578063c6c0cbb61461010b578063ccf4477514610135578063d6d8c9a814610148575f80fd5b806301ffc9a71461007e578063336284d4146100a6578063570c7a63146100bb575b5f80fd5b61009161008c366004612159565b610150565b60405190151581526020015b60405180910390f35b6100ae6101d7565b60405161009d91906121b5565b6100ce6100c93660046121db565b610b58565b60405161009d93929190612285565b6040517fdc6156fd1b9fda1ce642d416969c2f632029b10b9e3864fbde264f391c51bdee815260200161009d565b61011e6101193660046121db565b610c9c565b60408051921515835260208301919091520161009d565b60408051602081019091525f81526100ae565b6100ae610cd4565b5f6001600160e01b031982166391ccb1d560e01b148061018057506001600160e01b03198216636f5aa28d60e01b145b8061019b57506001600160e01b03198216631a2c8edd60e01b145b806101b657506001600160e01b03198216630cd8a13560e21b145b806101d157506301ffc9a760e01b6001600160e01b03198316145b92915050565b60605f6101e6600460016122f6565b6101f19060026122f6565b6101fc9060016122f6565b6102079060016122f6565b6001600160401b0381111561021e5761021e6121c7565b60405190808252806020026020018201604052801561025157816020015b606081526020019060019003908161023c5790505b50604080516002808252606082019092529192505f9190816020015b61214f81526020019060019003908161026d5790505090506115f2815f8151811061029a5761029a612309565b60200260200101906001600160401b031690816001600160401b03168152505061160f816001815181106102d0576102d0612309565b6001600160401b039290921660209283029190910190910152604080516003808252608082019092525f91816020015b61214f81526020019060019003908161030057905050905061161e815f8151811061032d5761032d612309565b60200260200101906001600160401b031690816001600160401b03168152505061162d8160018151811061036357610363612309565b60200260200101906001600160401b031690816001600160401b03168152505061163c8160028151811061039957610399612309565b6001600160401b039290921660209283029190910190910152604080516002808252606082019092525f91816020015b61214f8152602001906001900390816103c957905050905061164c815f815181106103f6576103f6612309565b60200260200101906001600160401b031690816001600160401b03168152505061165b8160018151811061042c5761042c612309565b6001600160401b03929092166020928302919091019091015260408051600580825260c082019092525f91816020015b61214f81526020019060019003908161045c57905050905061166b815f8151811061048957610489612309565b60200260200101906001600160401b031690816001600160401b03168152505061167a816001815181106104bf576104bf612309565b60200260200101906001600160401b031690816001600160401b03168152505061168a816002815181106104f5576104f5612309565b60200260200101906001600160401b031690816001600160401b03168152505061169a8160038151811061052b5761052b612309565b60200260200101906001600160401b031690816001600160401b0316815250506116a98160048151811061056157610561612309565b6001600160401b03929092166020928302919091019091015260408051600580825260c082019092525f91816020015b61214f8152602001906001900390816105915790505090506116b9815f815181106105be576105be612309565b60200260200101906001600160401b031690816001600160401b0316815250506116c8816001815181106105f4576105f4612309565b60200260200101906001600160401b031690816001600160401b0316815250506116d88160028151811061062a5761062a612309565b60200260200101906001600160401b031690816001600160401b0316815250506116e88160038151811061066057610660612309565b60200260200101906001600160401b031690816001600160401b0316815250506116f88160048151811061069657610696612309565b6001600160401b0392909216602092830291909101909101526040805160018082528183019092525f91816020015b61214f8152602001906001900390816106c5579050509050611707815f815181106106f2576106f2612309565b6001600160401b0392909216602092830291909101909101526040805160018082528183019092525f91816020015b61214f815260200190600190039081610721579050509050611716815f8151811061074e5761074e612309565b60200260200101906001600160401b031690816001600160401b03168152505086885f8151811061078157610781612309565b602002602001018190525085886001815181106107a0576107a0612309565b602002602001018190525084886002815181106107bf576107bf612309565b602002602001018190525083886003815181106107de576107de612309565b602002602001018190525082886004815181106107fd576107fd612309565b6020026020010181905250818860058151811061081c5761081c612309565b6020026020010181905250808860068151811061083b5761083b612309565b602090810291909101015260408051600580825260c082019092525f91816020015b61214f81526020019060019003908161085d5790505090506115f2815f8151811061088a5761088a612309565b60200260200101906001600160401b031690816001600160401b03168152505061161e816001815181106108c0576108c0612309565b60200260200101906001600160401b031690816001600160401b03168152505061162d816002815181106108f6576108f6612309565b60200260200101906001600160401b031690816001600160401b03168152505061163c8160038151811061092c5761092c612309565b60200260200101906001600160401b031690816001600160401b03168152505061174b8160048151811061096257610962612309565b6001600160401b03909216602092830291909101909101528089610988600660016122f6565b8151811061099857610998612309565b602090810291909101015260408051600680825260e082019092525f91816020015b61214f8152602001906001900390816109ba5790505090506115f2815f815181106109e7576109e7612309565b60200260200101906001600160401b031690816001600160401b03168152505061161e81600181518110610a1d57610a1d612309565b60200260200101906001600160401b031690816001600160401b03168152505061162d81600281518110610a5357610a53612309565b60200260200101906001600160401b031690816001600160401b03168152505061163c81600381518110610a8957610a89612309565b60200260200101906001600160401b031690816001600160401b03168152505061174b81600481518110610abf57610abf612309565b60200260200101906001600160401b031690816001600160401b03168152505061175b81600581518110610af557610af5612309565b6001600160401b0390921660209283029190910190910152808a610b1b600660026122f6565b81518110610b2b57610b2b612309565b602090810291909101015289610b48610b438261176b565b6117cd565b9b50505050505050505050505090565b5f6060805f805f610b7887610b6b61185c565b610b7361187c565b61189c565b9250925092505f610b8e82610220015160200190565b90505f8261022001515182610ba391906122f6565b90505f610bc183836f07fffffe0000000003ff20000000000061198d565b80925081945050505f80610bda86610240015184611a29565b915091508115610c6f575f610bef8783611b00565b905061214f5f610bfd611b2f565b90505f60028251610c0e9190612331565b9050808510610c3f576040516303bdd1b160e51b815260048101869052602481018290526044015b60405180910390fd5b6001850160020282015161ffff169250610c588c8c8686565b9e509e509e50505050505050505050505050610c95565b5050604080515f80825281830190925260208101828152919a5090985096505050505050505b9193909250565b5f805f805f610cc4866002810151815160228084019461ffff93909316840101920160200190565b505f988998509650505050505050565b60605f610ce3600460016122f6565b610cee9060026122f6565b610cf99060016122f6565b610d049060016122f6565b6001600160401b03811115610d1b57610d1b6121c7565b604051908082528060200260200182016040528015610d4e57816020015b6060815260200190600190039081610d395790505b50604080516002808252606082019092529192505f9190816020015b61214f815260200190600190039081610d6a579050509050611b4f815f81518110610d9757610d97612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600181518110610dcd57610dcd612309565b6001600160401b039290921660209283029190910190910152604080516003808252608082019092525f91816020015b61214f815260200190600190039081610dfd579050509050611b4f815f81518110610e2a57610e2a612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600181518110610e6057610e60612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600281518110610e9657610e96612309565b6001600160401b039290921660209283029190910190910152604080516002808252606082019092525f91816020015b61214f815260200190600190039081610ec6579050509050611b4f815f81518110610ef357610ef3612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600181518110610f2957610f29612309565b6001600160401b03929092166020928302919091019091015260408051600580825260c082019092525f91816020015b61214f815260200190600190039081610f59579050509050611b4f815f81518110610f8657610f86612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600181518110610fbc57610fbc612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600281518110610ff257610ff2612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160038151811061102857611028612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160048151811061105e5761105e612309565b6001600160401b03929092166020928302919091019091015260408051600580825260c082019092525f91816020015b61214f81526020019060019003908161108e579050509050611b4f815f815181106110bb576110bb612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f816001815181106110f1576110f1612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160028151811061112757611127612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160038151811061115d5761115d612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160048151811061119357611193612309565b6001600160401b0392909216602092830291909101909101526040805160018082528183019092525f91816020015b61214f8152602001906001900390816111c2579050509050611b78815f815181106111ef576111ef612309565b6001600160401b0392909216602092830291909101909101526040805160018082528183019092525f91816020015b61214f81526020019060019003908161121e579050509050611c14815f8151811061124b5761124b612309565b60200260200101906001600160401b031690816001600160401b03168152505086885f8151811061127e5761127e612309565b6020026020010181905250858860018151811061129d5761129d612309565b602002602001018190525084886002815181106112bc576112bc612309565b602002602001018190525083886003815181106112db576112db612309565b602002602001018190525082886004815181106112fa576112fa612309565b6020026020010181905250818860058151811061131957611319612309565b6020026020010181905250808860068151811061133857611338612309565b602090810291909101015260408051600580825260c082019092525f91816020015b61214f81526020019060019003908161135a579050509050611b4f815f8151811061138757611387612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f816001815181106113bd576113bd612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f816002815181106113f3576113f3612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160038151811061142957611429612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160048151811061145f5761145f612309565b6001600160401b03909216602092830291909101909101528089611485600660016122f6565b8151811061149557611495612309565b602090810291909101015260408051600680825260e082019092525f91816020015b61214f8152602001906001900390816114b7579050509050611b4f815f815181106114e4576114e4612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160018151811061151a5761151a612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160028151811061155057611550612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f8160038151811061158657611586612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f816004815181106115bc576115bc612309565b60200260200101906001600160401b031690816001600160401b031681525050611b4f81600581518110610af557610af5612309565b5f6060806116005f80611ccc565b92509250925093509350939050565b5f6060806116005f6001611ccc565b5f60608061160060015f611ccc565b5f606080611600600180611ccc565b5f60608061160060016002611ccc565b5f60608061160060025f611ccc565b5f60608061160060026001611ccc565b5f60608061160060035f611ccc565b5f60608061160060036001611ccc565b5f60608061160060036002611ccc565b5f606080611600600380611ccc565b5f60608061160060036004611ccc565b5f60608061160060045f611ccc565b5f60608061160060046001611ccc565b5f60608061160060046002611ccc565b5f60608061160060046003611ccc565b5f606080611600600480611ccc565b5f606080611600600585611ccc565b5f60608060ff80851690600886901c1661173a6117348360066122f6565b82611ccc565b945094509450505093509350939050565b5f60608061160060016003611ccc565b5f60608061160060016004611ccc565b60605f61177783611d4e565b9050606060405190506020820260200181016040528181526020840160208551028101602083015b818310156117c257602083515102806020855101835e602093909301920161179f565b509195945050505050565b60605f82516002026001600160401b038111156117ec576117ec6121c7565b6040519080825280601f01601f191660200182016040528015611816576020820181803683370190505b50905061ffff80196020850160208651028101600285015b818310156118505780518351861690851617815260209092019160020161182e565b50939695505050505050565b60606040518060c00160405280609a8152602001612467609a9139905090565b60606040518060600160405280603c8152602001612501603c9139905090565b5f8061192b6040518061026001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f80191681526020015f81526020015f81526020015f81526020015f81526020015f81526020015f80191681526020016060815260200160608152602001606081526020015f815260200160608152602001606081525090565b606061ffff600288015116935060ff600388015116925061ffff60058801511660058801975080885260208101880191505061197787878760405180602001604052805f815250611d7c565b915080826101e001819052505093509350939050565b5f8080600181878703602081116119a457806119a7565b60205b915050875192505b8519600184841a1b161581831016156119cd576001820191506119af565b9681019660208290036008810293841c90931b92611a185760408051602081018590520160408051601f198184030181529082905263e47fe8b760e01b8252610c36916004016121b5565b50869350909150505b935093915050565b600182810180515f928392600560ff93909316602102870192830192909101835b81831015611aee5760018301516021909301805190935f90819060ff168180611a73838e611f2d565b915091508186165f03611a95575f809b509b5050505050505050505050611af9565b5f87611aa5600185038916611f58565b016004028b015195505062ffffff9081169350841683039150611ad99050575060019750601c1a9550611af9945050505050565b611ae283611f58565b84019350505050611a4a565b5f8095509550505050505b9250929050565b6101c08201516002828102820101516101e08401515f9261ffff9092169190611b269083565b95945050505050565b60606040518060600160405280603c815260200161253d603c9139905090565b5f81515f14611b71576040516304f8b58160e51b815260040160405180910390fd5b505f919050565b5f8151600103611bd5575060208101516001600160e01b038116601b0b60e082901d5f611ba6838383612011565b905061ffff811115611bcb57604051631e4e01d760e21b815260040160405180910390fd5b9250611c0f915050565b81515f03611bf657604051630f16066b60e41b815260040160405180910390fd5b604051630358cd2160e31b815260040160405180910390fd5b919050565b5f8151600203611ca957602082015160408301516001600160e01b038216601b0b60e083901d5f611c46838383612011565b6001600160e01b038516601b0b935060e085901d925090505f611c6a848483612011565b905060ff821180611c7b575060ff81115b15611c9957604051631e4e01d760e21b815260040160405180910390fd5b60081b179450611c0f9350505050565b600282511015611bf657604051630f16066b60e41b815260040160405180910390fd5b5f60608060ff851180611cdf575060ff84115b15611d0757604051639b0f326160e01b81526004810186905260248101859052604401610c36565b6040805160248101909152600386602383015385602283015360106021830153806020830153506004815260408051602081019091525f8152600197919650945092505050565b5f60208201602083510281015b80821015611d755781515183019250602082019150611d5b565b5050919050565b611e096040518061026001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f80191681526020015f81526020015f81526020015f81526020015f81526020015f81526020015f80191681526020016060815260200160608152602001606081526020015f815260200160608152602001606081525090565b5f6040518061026001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f801b81526020015f8152602001600481526020015f81526020015f81526020015f81526020015f801b815260200184815260200185815260200160046001600160401b03811115611e8e57611e8e6121c7565b604051908082528060200260200182016040528015611eb7578160200160208202803683370190505b5081525f602080830182905260408084018b905260609384018a90528051601f01601f19168281528083018252835161ffff191681178452855290840182905283018190529082018190526080820181905260a08201819052610120820181905261014082018190526102008201529050611b26565b5f80825f528360205360215f2090506001815f1a1b915062ffffff8116611af9575060019250929050565b5f5f198203611f6a5750610100919050565b507f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f7f5555555555555555555555555555555555555555555555555555555555555555600183901c16909103600281901c7f3333333333333333333333333333333333333333333333333333333333333333908116911601600481901c01167f01010101010101010101010101010101010101010101010101010101010101010260f81c90565b5f805f61201f868686612053565b915091508061204a5760405162bc8ecf60e31b81526004810187905260248101869052604401610c36565b50949350505050565b5f805f85121561208057604051634a7d166b60e01b81526004810186905260248101859052604401610c36565b845f0361209257505f90506001611a21565b8460ff84168501858112156120c45760405163d556b11160e01b81526004810188905260248101879052604401610c36565b5f805f83121561211057604c198312156120e7575f809550955050505050611a21565b825f03600a0a91508184816120fe576120fe61231d565b0495505084029091149150611a219050565b5f83131561213f5761212383600a612430565b915061212f828561243b565b955060019450611a219350505050565b8360019550955050505050611a21565b612157612452565b565b5f60208284031215612169575f80fd5b81356001600160e01b031981168114612180575f80fd5b9392505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6121806020830184612187565b634e487b7160e01b5f52604160045260245ffd5b5f602082840312156121eb575f80fd5b81356001600160401b0380821115612201575f80fd5b818401915084601f830112612214575f80fd5b813581811115612226576122266121c7565b604051601f8201601f19908116603f0116810190838211818310171561224e5761224e6121c7565b81604052828152876020848701011115612266575f80fd5b826020860160208301375f928101602001929092525095945050505050565b83151581525f6020606060208401526122a16060840186612187565b8381036040850152845180825260208087019201905f5b818110156122d4578351835292840192918401916001016122b8565b509098975050505050505050565b634e487b7160e01b5f52601160045260245ffd5b808201808211156101d1576101d16122e2565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601260045260245ffd5b5f8261234b57634e487b7160e01b5f52601260045260245ffd5b500490565b600181815b8085111561238a57815f1904821115612370576123706122e2565b8085161561237d57918102915b93841c9390800290612355565b509250929050565b5f826123a0575060016101d1565b816123ac57505f6101d1565b81600181146123c257600281146123cc576123e8565b60019150506101d1565b60ff8411156123dd576123dd6122e2565b50506001821b6101d1565b5060208310610133831016604e8410600b841016171561240b575081810a6101d1565b6124158383612350565b805f1904821115612428576124286122e2565b029392505050565b5f6121808383612392565b80820281158282048414176101d1576101d16122e2565b634e487b7160e01b5f52605160045260245ffdfe0101080010800082000100010480300038412a001810000010020004200004002018038ff54900cc66c60616592209895f0b16fec9301a02e0920c5bfe561c21609201e959460b1974270f844db208bcd3bf1d989376111049db13b93430190ae9a00af82a7805c138f40d28083f0742ef2104d561fd1415a13317716a6118d260cc107b9bfc0eec7ade15cba2891b6b14a512792bdb02e0f1471b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b781c141b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f1b4f15f2160f161e162d163c164c165b166b167a168a169a16a916b916c816d816e816f81707171615f2161e162d163c174b15f2161e162d163c174b175b"; /// @dev The hash of the meta that describes the contract. -bytes32 constant DESCRIBED_BY_META_HASH = bytes32(0x339d2c0f76e1042e14b7e006217f629d71d489d753712f95756f882f3779757c); +bytes32 constant DESCRIBED_BY_META_HASH = bytes32(0xdc6156fd1b9fda1ce642d416969c2f632029b10b9e3864fbde264f391c51bdee); /// @dev The parse meta that is used to lookup word definitions. /// The structure of the parse meta is: @@ -44,7 +44,7 @@ bytes32 constant DESCRIBED_BY_META_HASH = bytes32(0x339d2c0f76e1042e14b7e006217f /// bit count of the previous bloom filter. If we reach the end of the bloom /// filters then we have a miss. bytes constant PARSE_META = - hex"0101080010800082000100010480300038412a001800080010020004200004002018038ff54900cc66c60616592209895f0b16fec9301a02e0920c5bfe561c216092011c4c610b1974270f844db208bcd3bf1d989376111049db13b93430190ae9a00af82a7805c138f40d28083f0742ef2104d561fd1415a13317716a6118d260cc107b9bfc0eec7ade15cba2891b6b14a512792bdb02e0f147"; + hex"0101080010800082000100010480300038412a001810000010020004200004002018038ff54900cc66c60616592209895f0b16fec9301a02e0920c5bfe561c21609201e959460b1974270f844db208bcd3bf1d989376111049db13b93430190ae9a00af82a7805c138f40d28083f0742ef2104d561fd1415a13317716a6118d260cc107b9bfc0eec7ade15cba2891b6b14a512792bdb02e0f147"; /// @dev The build depth of the parser meta. From c2c0e7354083d03fb4696bb06fe7304139c6a874 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Tue, 31 Mar 2026 19:59:08 +0400 Subject: [PATCH 26/69] Regenerate gas snapshot with renamed contracts Co-Authored-By: Claude Opus 4.6 (1M context) --- .gas-snapshot | 620 +++++++++++++++++++++++++++++--------------------- 1 file changed, 359 insertions(+), 261 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 9dbd13cfd0..aa021c2444 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,261 +1,359 @@ -GenericPoolOrderBookV6ArbOrderTakerExpressionTest:testGenericPoolTakeOrdersExpression((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,uint256[],uint256[]) (runs: 21, μ: 380135, ~: 377444) -GenericPoolOrderBookV6ArbOrderTakerExpressionTest:testGenericPoolTakeOrdersWrongExpression((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,address,bytes)) (runs: 21, μ: 144678, ~: 139362) -GenericPoolOrderBookV6ArbOrderTakerSenderTest:testGenericPoolTakeOrdersSender((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256) (runs: 21, μ: 293508, ~: 311336) -GenericPoolOrderBookV6FlashBorrowerTest:testGenericPoolOrderBookV6FlashBorrowerTakeOrdersSender((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256) (runs: 21, μ: 458264, ~: 489243) -LibOrderTest:testHashEqual((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32)) (runs: 111, μ: 170926, ~: 166248) -LibOrderTest:testHashNotEqual((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),(address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32)) (runs: 111, μ: 231155, ~: 233733) -OrderBookV5FlashBorrowerIERC165Test:testOrderBookV5FlashBorrowerIERC165(bytes4) (runs: 5106, μ: 2289436, ~: 2289436) -OrderBookV6AddOrderEnactTest:testAddLiveOrderNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 938532, ~: 893129) -OrderBookV6AddOrderEnactTest:testAddLiveOrderRevertNoAdd(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 699398, ~: 666288) -OrderBookV6AddOrderEnactTest:testAddOrderContext(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 1042861, ~: 1006504) -OrderBookV6AddOrderEnactTest:testAddOrderEmptyNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 626703, ~: 595830) -OrderBookV6AddOrderEnactTest:testAddOrderOneReadState(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 685702, ~: 654818) -OrderBookV6AddOrderEnactTest:testAddOrderOneStateless(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 671083, ~: 640199) -OrderBookV6AddOrderEnactTest:testAddOrderWriteStateDifferentOwnersNamespaced(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 3022963, ~: 2976578) -OrderBookV6AddOrderEnactTest:testAddOrderWriteStateSequential(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 911048, ~: 880123) -OrderBookV6AddOrderEnactTest:testAddOrderWriteStateSingle(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 1297701, ~: 1241519) -OrderBookV6AddOrderMockTest:testAddOrderSameAccountWithDifferentConfig(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,bytes) (runs: 111, μ: 2158663, ~: 2100666) -OrderBookV6AddOrderMockTest:testAddOrderTwoAccountsWithDifferentConfig(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,bytes) (runs: 111, μ: 1951982, ~: 1956511) -OrderBookV6AddOrderMockTest:testAddOrderTwoAccountsWithSameConfig(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 111, μ: 1843239, ~: 1886059) -OrderBookV6AddOrderMockTest:testAddOrderWithCalculationsInputsAndOutputsSucceeds(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 110, μ: 964508, ~: 924631) -OrderBookV6AddOrderMockTest:testAddOrderWithNonEmptyMetaEmitsMetaV1(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 110, μ: 973045, ~: 933008) -OrderBookV6AddOrderMockTest:testAddOrderWithNonEmptyMetaReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 110, μ: 555088, ~: 533636) -OrderBookV6AddOrderMockTest:testAddOrderWithoutCalculationsDeploys(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 541024, ~: 525175) -OrderBookV6AddOrderMockTest:testAddOrderWithoutInputsReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 131604, ~: 125294) -OrderBookV6AddOrderMockTest:testAddOrderWithoutOutputsReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 131166, ~: 119362) -OrderBookV6AddOrderNonceTest:testAddOrderNonceDifferentNonceStateChange(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes32) (runs: 111, μ: 959655, ~: 919681) -OrderBookV6AddOrderNonceTest:testAddOrderNonceSameNonceDifferentOrderStateChange(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 1208487, ~: 1205005) -OrderBookV6AddOrderNonceTest:testAddOrderNonceSameOrderNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 769098, ~: 745872) -OrderBookV6AddOrderOwnerTest:testAddOrderOwnerDifferentOwnerStateChange(((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,address) (runs: 111, μ: 1032070, ~: 1010540) -OrderBookV6AddOrderOwnerTest:testAddOrderOwnerSameOrderNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 769201, ~: 745975) -OrderBookV6AddOrderTest:testAddOrderRealCalculateInputsReverts1(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 532777, ~: 517877) -OrderBookV6AddOrderTest:testAddOrderRealCalculateInputsReverts2(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 534556, ~: 519656) -OrderBookV6AddOrderTest:testAddOrderRealCalculateInputsRevertsPreference(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 534141, ~: 519241) -OrderBookV6AddOrderTest:testAddOrderRealNoHandleIODeploys(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 525069, ~: 510169) -OrderBookV6AddOrderTest:testAddOrderRealNoSourcesDeploys(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 504519, ~: 489623) -OrderBookV6AddOrderTest:testAddOrderRealOneStackCalculateReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 537135, ~: 522235) -OrderBookV6AddOrderTest:testAddOrderRealThreeStackCalculate(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 549604, ~: 534704) -OrderBookV6AddOrderTest:testAddOrderRealTwoStackCalculateReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 543268, ~: 528368) -OrderBookV6AddOrderTest:testAddOrderRealZeroStackCalculateReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 531499, ~: 516599) -OrderBookV6ArbOrderTakerContextTest:testOrderBookV6ArbOrderTakerContext() (gas: 2046356) -OrderBookV6ArbOrderTakerIERC165Test:testOrderBookV6ArbOrderTakerIERC165(bytes4) (runs: 5107, μ: 1772793, ~: 1772793) -OrderBookV6ClearHandleIORevertTest:testClearOrderAliceNoHandleIORevert() (gas: 622225) -OrderBookV6ClearHandleIORevertTest:testClearOrderBobNoHandleIORevert() (gas: 622160) -OrderBookV6ClearHandleIORevertTest:testClearOrderBothNoHandleIORevert() (gas: 601345) -OrderBookV6ClearHandleIORevertTest:testClearOrderHandleIO0() (gas: 653977) -OrderBookV6ClearHandleIORevertTest:testClearOrderHandleIO1() (gas: 650317) -OrderBookV6ClearHandleIORevertTest:testClearOrderHandleIO2() (gas: 650459) -OrderBookV6ClearHandleIORevertTest:testClearOrderHandleIO3() (gas: 653933) -OrderBookV6ClearHandleIORevertTest:testClearOrderHandleIO4() (gas: 717684) -OrderBookV6ClearHandleIORevertTest:testClearOrderHandleIO5() (gas: 681804) -OrderBookV6ClearOrderBadStackTest:testClearOrderBadStackEmptyStack(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 1882942, ~: 1929303) -OrderBookV6ClearOrderBadStackTest:testClearOrderBadStackOneEmpty(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 1963370, ~: 2003414) -OrderBookV6ClearOrderBadStackTest:testClearOrderBadStackOneOne(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 1970194, ~: 2010237) -OrderBookV6ClearOrderBadStackTest:testClearOrderBadStackOneOtherOne(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 1902341, ~: 1948708) -OrderBookV6ClearOrderBadStackTest:testClearOrderBadStackOneStack(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 1896164, ~: 1942531) -OrderBookV6ClearOrderBadStackTest:testClearOrderBadStackOtherEmpty(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 1895538, ~: 1941899) -OrderBookV6ClearOrderContextTest:testContextEmptyStack(address,address,bytes32,bytes32,bytes32,bytes32) (runs: 20, μ: 2190636, ~: 2200939) -OrderBookV6ClearSameTokenTest:testClearSameToken(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 1554816, ~: 1599535) -OrderBookV6ClearTest:testClear2ZeroRatioAliceAndBob(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 110, μ: 3607727, ~: 3672618) -OrderBookV6ClearTest:testClear2ZeroRatioAliceOnly(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 110, μ: 3629011, ~: 3693902) -OrderBookV6ClearTest:testClear2ZeroRatioBobOnly(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 110, μ: 3632533, ~: 3697424) -OrderBookV6ClearTest:testClearFuzzIoRatioError(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32,uint256,uint256) (runs: 110, μ: 3629502, ~: 3646896) -OrderBookV6ClearTest:testClearFuzzIoRatioHappy(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32,uint256,uint256) (runs: 110, μ: 3669003, ~: 3686586) -OrderBookV6ClearTest:testClearSimple(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 110, μ: 3697336, ~: 3762214) -OrderBookV6ClearZeroAmountTest:testClearZeroAmount(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 2401419, ~: 2465074) -OrderBookV6DepositEnactTest:testDepositRevertInAction(address,bytes32,uint256) (runs: 20, μ: 126750, ~: 126611) -OrderBookV6DepositEnactTest:testOrderBookDepositEnactEmptyNoop(address,bytes32,uint256) (runs: 20, μ: 75554, ~: 75415) -OrderBookV6DepositEnactTest:testOrderBookDepositEnactOneReadState(address,bytes32,uint256) (runs: 20, μ: 135813, ~: 135674) -OrderBookV6DepositEnactTest:testOrderBookDepositEnactOneStateless(address,bytes32,uint256) (runs: 20, μ: 121217, ~: 121078) -OrderBookV6DepositEnactTest:testOrderBookDepositEvalWriteStateDifferentOwnersNamespaced(address,address,bytes32,uint256) (runs: 21, μ: 976699, ~: 976643) -OrderBookV6DepositEnactTest:testOrderBookDepositEvalWriteStateSequential(address,bytes32,uint256) (runs: 20, μ: 610978, ~: 610814) -OrderBookV6DepositEnactTest:testOrderBookDepositEvalWriteStateSingle(address,bytes32,uint256) (runs: 20, μ: 243540, ~: 243376) -OrderBookV6DepositEnactTest:testOrderDepositContext(address,bytes32,uint256,uint256) (runs: 20, μ: 704598, ~: 712253) -OrderBookV6DepositTest:testDepositEvent(address,bytes32,uint256) (runs: 110, μ: 71729, ~: 71627) -OrderBookV6DepositTest:testDepositFail(address,bytes32,uint256) (runs: 110, μ: 1040466626, ~: 1040466489) -OrderBookV6DepositTest:testDepositGas00() (gas: 15740) -OrderBookV6DepositTest:testDepositGas01() (gas: 64054) -OrderBookV6DepositTest:testDepositMany((address,address,bytes32,uint256,bytes32)[]) (runs: 105, μ: 8966192, ~: 7864680) -OrderBookV6DepositTest:testDepositReentrancy(address,bytes32,uint256,address,bytes32,uint256) (runs: 110, μ: 544961, ~: 544994) -OrderBookV6DepositTest:testDepositSimple(address,bytes32,uint256) (runs: 110, μ: 71178, ~: 71076) -OrderBookV6DepositTest:testDepositZero(address,bytes32) (runs: 110, μ: 13961, ~: 13961) -OrderBookV6DepositTest:testDepositZeroVaultId(address,address,bytes32) (runs: 5106, μ: 13834, ~: 13834) -OrderBookV6EnactTest:testOrderBookEvalEmptyNoop(address) (runs: 111, μ: 14260, ~: 14260) -OrderBookV6EnactTest:testOrderBookEvalOneReadState(address) (runs: 111, μ: 71892, ~: 71892) -OrderBookV6EnactTest:testOrderBookEvalOneStateless(address) (runs: 111, μ: 57276, ~: 57276) -OrderBookV6EnactTest:testOrderBookEvalWriteStateDifferentOwnersNamespaced(address,address) (runs: 111, μ: 837360, ~: 837360) -OrderBookV6EnactTest:testOrderBookEvalWriteStateSequential() (gas: 523537) -OrderBookV6EnactTest:testOrderBookEvalWriteStateSingle(address) (runs: 111, μ: 166224, ~: 166224) -OrderBookV6FlashLenderFeeTest:testFlashFee(address,uint256) (runs: 5107, μ: 3798, ~: 3798) -OrderBookV6FlashLenderGriefRecipientTest:testFlashLoanToNonReceiver(uint256,bytes,bytes32,bytes) (runs: 5107, μ: 24272, ~: 24264) -OrderBookV6FlashLenderIERC165Test:testOrderBookV6FlashLenderIERC165(bytes4) (runs: 5106, μ: 366649, ~: 366649) -OrderBookV6FlashLenderMaxFlashLoanTest:testFlashMaxLoan(uint256) (runs: 5107, μ: 7448, ~: 7448) -OrderBookV6FlashLenderMockSuccessTest:testFlashLoanToReceiver(uint256,bytes) (runs: 5107, μ: 11830, ~: 11823) -OrderBookV6FlashLenderReentrant:testReenterAddOrder(uint256,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 12750576, ~: 12992923) -OrderBookV6FlashLenderReentrant:testReenterCheckOrderExists(bytes32,uint256) (runs: 111, μ: 439689, ~: 439869) -OrderBookV6FlashLenderReentrant:testReenterClear(uint256,address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 26779445, ~: 27488840) -OrderBookV6FlashLenderReentrant:testReenterDeposit(uint256,uint256,uint256) (runs: 110, μ: 569731, ~: 569629) -OrderBookV6FlashLenderReentrant:testReenterReadVaultBalances(uint256,uint256) (runs: 110, μ: 485330, ~: 485330) -OrderBookV6FlashLenderReentrant:testReenterRemoveOrder(uint256,(address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32)) (runs: 111, μ: 11743403, ~: 11288049) -OrderBookV6FlashLenderReentrant:testReenterTakeOrder(uint256,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 13310258, ~: 13510950) -OrderBookV6FlashLenderReentrant:testReenterWithdraw(uint256,uint256,uint256) (runs: 110, μ: 551216, ~: 551114) -OrderBookV6FlashLenderTransferTest:testFlashLoanTransferFail(uint256,uint256,bool) (runs: 111, μ: 946830, ~: 947862) -OrderBookV6FlashLenderTransferTest:testFlashLoanTransferSuccess(uint256,bool) (runs: 111, μ: 900641, ~: 909733) -OrderBookV6QuoteSameTokenTest:testQuoteSameToken(((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,bytes32[],bytes)[])) (runs: 20, μ: 8048353, ~: 7621050) -OrderBookV6QuoteTest:testQuoteContextSender(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),uint256) (runs: 111, μ: 8960848, ~: 9260272) -OrderBookV6QuoteTest:testQuoteDeadOrder(((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,bytes32[],bytes)[])) (runs: 111, μ: 6501720, ~: 5431388) -OrderBookV6QuoteTest:testQuoteMaxOutput(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),uint256) (runs: 111, μ: 1029816, ~: 1064091) -OrderBookV6QuoteTest:testQuoteSimple(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),uint256) (runs: 111, μ: 1023609, ~: 1057753) -OrderBookV6RemoveOrderEnactTest:testRemoveOrderContext(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 647606, ~: 636057) -OrderBookV6RemoveOrderEnactTest:testRemoveOrderDeadOrder(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 329892, ~: 321107) -OrderBookV6RemoveOrderEnactTest:testRemoveOrderEmptyNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 835598, ~: 810182) -OrderBookV6RemoveOrderEnactTest:testRemoveOrderOneReadState(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 894799, ~: 869378) -OrderBookV6RemoveOrderEnactTest:testRemoveOrderOneStateless(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 880269, ~: 854848) -OrderBookV6RemoveOrderEnactTest:testRemoveOrderRevertInAction(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 993761, ~: 965665) -OrderBookV6RemoveOrderEnactTest:testRemoveOrderWriteStateDifferentOwnersNamespaced(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 4120695, ~: 4041924) -OrderBookV6RemoveOrderEnactTest:testRemoveOrderWriteStateSequential(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 1120935, ~: 1095486) -OrderBookV6RemoveOrderEnactTest:testRemoveOrderWriteStateSingle(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 1732289, ~: 1684183) -OrderBookV6RemoveOrderMockTest:testRemoveOrderAddRemoveMulti(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 111, μ: 5275817, ~: 5035488) -OrderBookV6RemoveOrderMockTest:testRemoveOrderDifferent(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 111, μ: 3689120, ~: 3616789) -OrderBookV6RemoveOrderMockTest:testRemoveOrderDifferentOwners(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 111, μ: 3526613, ~: 3602387) -OrderBookV6RemoveOrderMockTest:testRemoveOrderDifferentOwnersDifferent(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 111, μ: 7138579, ~: 7078430) -OrderBookV6RemoveOrderMockTest:testRemoveOrderDoesNotExist(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 111, μ: 361112, ~: 346529) -OrderBookV6RemoveOrderMockTest:testRemoveOrderOnlyOwner(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 111, μ: 1940170, ~: 1983960) -OrderBookV6RemoveOrderOwnerTest:testRemoveOrderOwnerDifferentOwnerStateChange(((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,address) (runs: 111, μ: 4620921, ~: 4480522) -OrderBookV6RemoveOrderOwnerTest:testRemoveOrderOwnerSameOrderNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 2576783, ~: 2491125) -OrderBookV6RemoveOrderOwnerTest:testRemoveOrderWrongOwner(((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,address) (runs: 111, μ: 667386, ~: 653431) -OrderBookV6SubParserContextCalculatedIORatioTest:testSubParserContextHappy() (gas: 2065358) -OrderBookV6SubParserContextCalculatedIORatioTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2042454) -OrderBookV6SubParserContextCalculatedIORatioTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2028887) -OrderBookV6SubParserContextCalculatedMaxOutputTest:testSubParserContextHappy() (gas: 2065685) -OrderBookV6SubParserContextCalculatedMaxOutputTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2042777) -OrderBookV6SubParserContextCalculatedMaxOutputTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2029215) -OrderBookV6SubParserContextInputTokenDecimalsTest:testSubParserContextHappy() (gas: 2065524) -OrderBookV6SubParserContextInputTokenDecimalsTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2042616) -OrderBookV6SubParserContextInputTokenDecimalsTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2029053) -OrderBookV6SubParserContextInputTokenTest:testSubParserContextHappy() (gas: 2064061) -OrderBookV6SubParserContextInputTokenTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2041154) -OrderBookV6SubParserContextInputTokenTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2027591) -OrderBookV6SubParserContextInputVaultBalanceBeforeTest:testSubParserContextHappy() (gas: 2065196) -OrderBookV6SubParserContextInputVaultBalanceBeforeTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2042292) -OrderBookV6SubParserContextInputVaultBalanceBeforeTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2028725) -OrderBookV6SubParserContextInputVaultBalanceIncreaseTest:testSubParserContextHappy() (gas: 2065524) -OrderBookV6SubParserContextInputVaultBalanceIncreaseTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2042616) -OrderBookV6SubParserContextInputVaultBalanceIncreaseTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2029053) -OrderBookV6SubParserContextInputVaultIdTest:testSubParserContextHappy() (gas: 2064548) -OrderBookV6SubParserContextInputVaultIdTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2041641) -OrderBookV6SubParserContextInputVaultIdTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2028077) -OrderBookV6SubParserContextOrderBookTest:testSubParserContextHappy() (gas: 2063737) -OrderBookV6SubParserContextOrderBookTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2040830) -OrderBookV6SubParserContextOrderBookTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2027267) -OrderBookV6SubParserContextOrderClearerTest:testSubParserContextHappy() (gas: 2064385) -OrderBookV6SubParserContextOrderClearerTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2041478) -OrderBookV6SubParserContextOrderClearerTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2027915) -OrderBookV6SubParserContextOrderCounterpartyTest:testSubParserContextHappy() (gas: 2065196) -OrderBookV6SubParserContextOrderCounterpartyTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2042292) -OrderBookV6SubParserContextOrderCounterpartyTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2028725) -OrderBookV6SubParserContextOrderHashTest:testSubParserContextHappy() (gas: 2063899) -OrderBookV6SubParserContextOrderHashTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2040992) -OrderBookV6SubParserContextOrderHashTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2027429) -OrderBookV6SubParserContextOrderOwnerTest:testSubParserContextHappy() (gas: 2064062) -OrderBookV6SubParserContextOrderOwnerTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2041155) -OrderBookV6SubParserContextOrderOwnerTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2027591) -OrderBookV6SubParserContextOutputTokenDecimalsTest:testSubParserContextHappy() (gas: 2065686) -OrderBookV6SubParserContextOutputTokenDecimalsTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2042778) -OrderBookV6SubParserContextOutputTokenDecimalsTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2029215) -OrderBookV6SubParserContextOutputTokenTest:testSubParserContextHappy() (gas: 2064223) -OrderBookV6SubParserContextOutputTokenTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2041316) -OrderBookV6SubParserContextOutputTokenTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2027753) -OrderBookV6SubParserContextOutputVaultBalanceBeforeTest:testSubParserContextHappy() (gas: 2065358) -OrderBookV6SubParserContextOutputVaultBalanceBeforeTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2042454) -OrderBookV6SubParserContextOutputVaultBalanceBeforeTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2028887) -OrderBookV6SubParserContextOutputVaultBalanceDecreaseTest:testSubParserContextHappy() (gas: 2065686) -OrderBookV6SubParserContextOutputVaultBalanceDecreaseTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2042778) -OrderBookV6SubParserContextOutputVaultBalanceDecreaseTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2029215) -OrderBookV6SubParserContextOutputVaultIdTest:testSubParserContextHappy() (gas: 2064710) -OrderBookV6SubParserContextOutputVaultIdTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2041803) -OrderBookV6SubParserContextOutputVaultIdTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2028239) -OrderBookV6SubParserDescribedByMetaV1Test:testOrderBookV6SubParserDescribedByMetaV1Happy() (gas: 1978249) -OrderBookV6SubParserIERC165Test:testOrderBookV6SubParserIERC165(bytes4) (runs: 5107, μ: 1984624, ~: 1984624) -OrderBookV6SubParserPointersTest:testSubParserFunctionPointers() (gas: 1990810) -OrderBookV6SubParserPointersTest:testSubParserOperandParsers() (gas: 1990832) -OrderBookV6SubParserPointersTest:testSubParserParseMeta() (gas: 102268) -OrderBookV6SubParserPointersTest:testWordOperandLengthEquivalence() (gas: 880) -OrderBookV6SubParserSignedContextTest:testSubParserContextSignedContextHappy0() (gas: 2070733) -OrderBookV6SubParserSignedContextTest:testSubParserContextSignedContextHappy1() (gas: 2070844) -OrderBookV6SubParserSignedContextTest:testSubParserContextSignedContextHappy2() (gas: 2070845) -OrderBookV6SubParserSignedContextTest:testSubParserContextSignedContextHappy3() (gas: 2071044) -OrderBookV6SubParserSignedContextTest:testSubParserContextSignedContextUnhappyInput() (gas: 2047674) -OrderBookV6SubParserSignedContextTest:testSubParserContextSignedContextUnhappyNoOperand() (gas: 2025115) -OrderBookV6SubParserSignedContextTest:testSubParserContextSignedContextUnhappyTooManyOperands() (gas: 2033428) -OrderBookV6SubParserSignersTest:testSubParserContextSignerHappy0() (gas: 2066224) -OrderBookV6SubParserSignersTest:testSubParserContextSignerHappy1() (gas: 2066357) -OrderBookV6SubParserSignersTest:testSubParserContextSignerUnhappyInput() (gas: 2043150) -OrderBookV6SubParserSignersTest:testSubParserContextSignerUnhappyNoOperand() (gas: 2023791) -OrderBookV6SubParserSignersTest:testSubParserContextSignerUnhappyTooManyOperands() (gas: 2029364) -OrderBookV6TakeOrderBadStackTest:testTakeOrderBadStackEmptyStack(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 837592, ~: 819326) -OrderBookV6TakeOrderBadStackTest:testTakeOrderBadStackOneStack(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 844134, ~: 825865) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO00() (gas: 300477) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO1() (gas: 476823) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO10(uint256) (runs: 111, μ: 689086, ~: 644493) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO2() (gas: 490964) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO3() (gas: 647361) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO4() (gas: 663992) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO5() (gas: 663977) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO6() (gas: 649805) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO7(uint256) (runs: 111, μ: 917280, ~: 917519) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO8(uint256) (runs: 111, μ: 1088554, ~: 1088759) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO9(uint256) (runs: 111, μ: 761764, ~: 694136) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderNoHandleIORevert0() (gas: 296236) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderNoHandleIORevert1() (gas: 466195) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderNoHandleIORevert2() (gas: 452034) -OrderBookV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputMultipleOrdersMultipleOwners(uint256,uint256,uint256) (runs: 111, μ: 551087, ~: 561254) -OrderBookV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputMultipleOrdersSingleOwner(uint256,uint256) (runs: 111, μ: 481846, ~: 503807) -OrderBookV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputSingleAnyDeposit(uint256,uint256) (runs: 111, μ: 326192, ~: 328902) -OrderBookV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputSingleOrderLessThanMaximumInput(uint256,uint256) (runs: 111, μ: 303853, ~: 304538) -OrderBookV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputSingleOrderLessThanMaximumOutput(uint256) (runs: 111, μ: 305611, ~: 305561) -OrderBookV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputSingleOrderUnlimitedMax(uint256) (runs: 111, μ: 298579, ~: 298374) -OrderBookV6TakeOrderMaximumInputTest:testTakeOrderNoopZeroMaxTakerInput((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),(address,bytes32[],bytes)) (runs: 110, μ: 167510, ~: 162007) -OrderBookV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputMultipleOrders(uint256,uint256) (runs: 111, μ: 495888, ~: 517956) -OrderBookV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputMultipleOrdersDifferentOwners(uint256,uint256,uint256) (runs: 111, μ: 571993, ~: 587785) -OrderBookV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputSingleAnyDeposit(uint256,uint256) (runs: 111, μ: 334413, ~: 338379) -OrderBookV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputSingleOrderLimitedByVault(uint256,uint256) (runs: 111, μ: 311018, ~: 311728) -OrderBookV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputSingleOrderLimitedMax(uint256) (runs: 111, μ: 310092, ~: 310364) -OrderBookV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputSingleOrderUnlimitedMax(uint256) (runs: 111, μ: 305934, ~: 305681) -OrderBookV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputZero((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),(address,bytes32[],bytes)) (runs: 5106, μ: 162495, ~: 161657) -OrderBookV6TakeOrderNoopTest:testTakeOrderNoopNonLiveOrderOne((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,bytes32[],bytes)) (runs: 110, μ: 428237, ~: 435942) -OrderBookV6TakeOrderNoopTest:testTakeOrderNoopNonLiveOrderTwo((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),(address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,uint256,uint256,(address,bytes32[],bytes),(address,bytes32[],bytes)) (runs: 110, μ: 757840, ~: 758206) -OrderBookV6TakeOrderNoopTest:testTakeOrderNoopZeroOrders() (gas: 13193) -OrderBookV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad01() (gas: 303557) -OrderBookV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad02() (gas: 303535) -OrderBookV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad03() (gas: 305274) -OrderBookV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad04() (gas: 305252) -OrderBookV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad05() (gas: 305231) -OrderBookV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad06() (gas: 305296) -OrderBookV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad07() (gas: 304209) -OrderBookV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad08() (gas: 304186) -OrderBookV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad09() (gas: 304232) -OrderBookV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad10() (gas: 304187) -OrderBookV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad11() (gas: 304651) -OrderBookV6TakeOrderSameTokenTest:testTakeOrderSameToken(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 756980, ~: 718387) -OrderBookV6TakeOrderTokenMismatchTest:testTokenDecimalMismatchOutputs((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,uint256,uint256) (runs: 20, μ: 555505, ~: 571000) -OrderBookV6TakeOrderTokenMismatchTest:testTokenMismatchInputs((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,uint256,uint256) (runs: 20, μ: 555338, ~: 570833) -OrderBookV6VaultBalanceTest:testVaultBalanceNoDeposits(address,bytes32) (runs: 5106, μ: 9163, ~: 9163) -OrderBookV6WithdrawEvalTest:testOrderBookWithdrawEvalEmptyNoop(address,bytes32,uint256,uint256) (runs: 110, μ: 98383, ~: 99323) -OrderBookV6WithdrawEvalTest:testOrderBookWithdrawEvalOneReadState(address,bytes32,uint256,uint256) (runs: 110, μ: 158597, ~: 159539) -OrderBookV6WithdrawEvalTest:testOrderBookWithdrawEvalOneStateless(address,bytes32,uint256,uint256) (runs: 110, μ: 143960, ~: 144902) -OrderBookV6WithdrawEvalTest:testOrderBookWithdrawEvalWriteStateDifferentOwnersNamespaced(address,address,bytes32,uint256,uint256) (runs: 111, μ: 1060219, ~: 1063023) -OrderBookV6WithdrawEvalTest:testOrderBookWithdrawEvalWriteStateSequential(address,bytes32,uint256,uint256) (runs: 110, μ: 655960, ~: 656978) -OrderBookV6WithdrawEvalTest:testOrderBookWithdrawEvalWriteStateSingle(address,bytes32,uint256,uint256) (runs: 110, μ: 287751, ~: 288769) -OrderBookV6WithdrawEvalTest:testOrderBookWithdrawalEvalRevertInAction(address,bytes32,uint256,uint256) (runs: 110, μ: 142932, ~: 143874) -OrderBookV6WithdrawEvalTest:testOrderBookWithdrawalEvalZeroAmountEvalNoop(address,bytes32,uint256) (runs: 110, μ: 110929, ~: 110665) -OrderBookV6WithdrawEvalTest:testOrderWithdrawContext(address,bytes32,uint256,uint256) (runs: 110, μ: 774807, ~: 771817) -OrderBookV6WithdrawTest:testWithdrawEmptyVault(address,bytes32,uint256) (runs: 110, μ: 57644, ~: 57548) -OrderBookV6WithdrawTest:testWithdrawFailure(address,bytes32,uint256,uint256) (runs: 110, μ: 1040421911, ~: 1040404236) -OrderBookV6WithdrawTest:testWithdrawFullVault(address,bytes32,uint256,uint256) (runs: 110, μ: 79571, ~: 79798) -OrderBookV6WithdrawTest:testWithdrawMany((bool,address,address,bytes32,uint256,bytes32,uint256,bool)[]) (runs: 111, μ: 7409843, ~: 7190842) -OrderBookV6WithdrawTest:testWithdrawPartialVault(address,bytes32,uint256,uint256) (runs: 110, μ: 95763, ~: 95791) -OrderBookV6WithdrawTest:testWithdrawZero(address,address,bytes32) (runs: 111, μ: 13621, ~: 13621) -RouteProcessorOrderBookV6ArbOrderTakerExpressionTest:testRouteProcessorTakeOrdersExpression((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,uint256[],uint256[]) (runs: 111, μ: 361296, ~: 355146) -RouteProcessorOrderBookV6ArbOrderTakerExpressionTest:testRouteProcessorTakeOrdersWrongExpression((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,address,bytes)) (runs: 111, μ: 139968, ~: 136952) -RouteProcessorOrderBookV6ArbOrderTakerSenderTest:testRouteProcessorTakeOrdersSender((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256) (runs: 111, μ: 272813, ~: 263019) \ No newline at end of file +GenericPoolRaindexV6ArbOrderTakerApprovalRevokedTest:testApprovalRevokedAfterOnTakeOrders2() (gas: 4187360) +GenericPoolRaindexV6ArbOrderTakerExchangeRevertTest:testExchangeRevertPropagates() (gas: 4010015) +GenericPoolRaindexV6ArbOrderTakerSenderTest:testGenericPoolTakeOrdersSender((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256) (runs: 10, μ: 240617, ~: 236170) +GenericPoolRaindexV6FlashBorrowerApprovalRevokedTest:testApprovalRevokedAfterExchange() (gas: 4791226) +GenericPoolRaindexV6FlashBorrowerEthForwardedTest:testEthForwardedToExchangeDuringExchange() (gas: 4831176) +GenericPoolRaindexV6FlashBorrowerExchangeRevertTest:testExchangeRevertPropagates() (gas: 4645831) +GenericPoolRaindexV6FlashBorrowerTest:testGenericPoolRaindexV6FlashBorrowerTakeOrdersSender((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256) (runs: 10, μ: 376819, ~: 368454) +LibOrderTest:testHashEqual((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32)) (runs: 100, μ: 162224, ~: 170137) +LibOrderTest:testHashNotEqual((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),(address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32)) (runs: 100, μ: 326762, ~: 323279) +LibRaindexArbFinalizeArbNativeGasTest:testFinalizeArbSendsNativeGas() (gas: 4122396) +LibRaindexArbFinalizeArbOutputTokenProfitTest:testFinalizeArbTransfersOutputTokenProfit() (gas: 4128389) +LibRaindexArbFinalizeArbTaskContextTest:testFinalizeArbTaskContextValues() (gas: 4295096) +LibRaindexArbFinalizeArbTokenTransfersTest:testFinalizeArbTransfersInputTokenProfit() (gas: 4125310) +LibRaindexDeploySubgraphYamlAddressTest:testSubgraphYamlAddress() (gas: 5161) +LibRaindexDeployTest:testCreationCodeRaindex() (gas: 22417) +LibRaindexDeployTest:testCreationCodeSubParser() (gas: 8512) +LibRaindexDeployTest:testDeployAddressGenericPoolArbOrderTaker() (gas: 1720808) +LibRaindexDeployTest:testDeployAddressGenericPoolFlashBorrower() (gas: 2271572) +LibRaindexDeployTest:testDeployAddressRaindex() (gas: 4768334) +LibRaindexDeployTest:testDeployAddressRouteProcessor() (gas: 3235853) +LibRaindexDeployTest:testDeployAddressRouteProcessorArbOrderTaker() (gas: 1850834) +LibRaindexDeployTest:testDeployAddressSubParser() (gas: 1963503) +LibRaindexDeployTest:testEtchRaindex() (gas: 36203) +LibRaindexDeployTest:testEtchRaindexIdempotent() (gas: 36646) +LibRaindexDeployTest:testExpectedCodeHashGenericPoolArbOrderTaker() (gas: 1713609) +LibRaindexDeployTest:testExpectedCodeHashGenericPoolFlashBorrower() (gas: 2263196) +LibRaindexDeployTest:testExpectedCodeHashRaindex() (gas: 4754446) +LibRaindexDeployTest:testExpectedCodeHashRouteProcessorArbOrderTaker() (gas: 1843310) +LibRaindexDeployTest:testExpectedCodeHashSubParser() (gas: 1955756) +LibRaindexDeployTest:testGeneratedCodehashGenericPoolArbOrderTaker() (gas: 289) +LibRaindexDeployTest:testGeneratedCodehashGenericPoolFlashBorrower() (gas: 311) +LibRaindexDeployTest:testGeneratedCodehashRouteProcessor() (gas: 269) +LibRaindexDeployTest:testGeneratedCodehashRouteProcessorArbOrderTaker() (gas: 267) +LibRaindexDeployTest:testGeneratedDeployedAddressGenericPoolArbOrderTaker() (gas: 306) +LibRaindexDeployTest:testGeneratedDeployedAddressGenericPoolFlashBorrower() (gas: 349) +LibRaindexDeployTest:testGeneratedDeployedAddressRaindex() (gas: 304) +LibRaindexDeployTest:testGeneratedDeployedAddressRouteProcessor() (gas: 326) +LibRaindexDeployTest:testGeneratedDeployedAddressRouteProcessorArbOrderTaker() (gas: 326) +LibRaindexDeployTest:testGeneratedDeployedAddressSubParser() (gas: 325) +LibRaindexDeployTest:testRuntimeCodeGenericPoolArbOrderTaker() (gas: 1719703) +LibRaindexDeployTest:testRuntimeCodeGenericPoolFlashBorrower() (gas: 2271468) +LibRaindexDeployTest:testRuntimeCodeRaindex() (gas: 4773331) +LibRaindexDeployTest:testRuntimeCodeRouteProcessor() (gas: 3241315) +LibRaindexDeployTest:testRuntimeCodeRouteProcessorArbOrderTaker() (gas: 1849931) +LibRaindexDeployTest:testRuntimeCodeSubParser() (gas: 1962851) +LibRouteProcessor4CreationCodeTest:testRouteProcessor4Codehash() (gas: 3225289) +RaindexV6AddOrderEnactTest:testAddLiveOrderNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 839870, ~: 874655) +RaindexV6AddOrderEnactTest:testAddLiveOrderRevertNoAdd(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 630383, ~: 655763) +RaindexV6AddOrderEnactTest:testAddOrderContext(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 969918, ~: 997197) +RaindexV6AddOrderEnactTest:testAddOrderEmptyNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 565679, ~: 589179) +RaindexV6AddOrderEnactTest:testAddOrderOneReadState(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 625713, ~: 649223) +RaindexV6AddOrderEnactTest:testAddOrderOneStateless(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 610807, ~: 634317) +RaindexV6AddOrderEnactTest:testAddOrderWriteStateDifferentOwnersNamespaced(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 2968901, ~: 3094080) +RaindexV6AddOrderEnactTest:testAddOrderWriteStateSequential(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 856258, ~: 879800) +RaindexV6AddOrderEnactTest:testAddOrderWriteStateSingle(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 1173145, ~: 1216076) +RaindexV6AddOrderMockTest:testAddOrderSameAccountWithDifferentConfig(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,bytes) (runs: 100, μ: 2109643, ~: 2176892) +RaindexV6AddOrderMockTest:testAddOrderTwoAccountsWithDifferentConfig(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,bytes) (runs: 100, μ: 1990458, ~: 2002422) +RaindexV6AddOrderMockTest:testAddOrderTwoAccountsWithSameConfig(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 100, μ: 1813876, ~: 1728783) +RaindexV6AddOrderMockTest:testAddOrderWithCalculationsInputsAndOutputsSucceeds(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 100, μ: 963048, ~: 928089) +RaindexV6AddOrderMockTest:testAddOrderWithNonEmptyMetaEmitsMetaV1(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 100, μ: 972560, ~: 926284) +RaindexV6AddOrderMockTest:testAddOrderWithNonEmptyMetaReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 100, μ: 557742, ~: 535883) +RaindexV6AddOrderMockTest:testAddOrderWithoutCalculationsDeploys(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 573679, ~: 590764) +RaindexV6AddOrderMockTest:testAddOrderWithoutInputsReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 150121, ~: 147946) +RaindexV6AddOrderMockTest:testAddOrderWithoutOutputsReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 152178, ~: 151109) +RaindexV6AddOrderNonceTest:testAddOrderNonceDifferentNonceStateChange(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes32) (runs: 100, μ: 1015445, ~: 1032856) +RaindexV6AddOrderNonceTest:testAddOrderNonceSameNonceDifferentOrderStateChange(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 1235944, ~: 1238440) +RaindexV6AddOrderNonceTest:testAddOrderNonceSameOrderNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 806423, ~: 831849) +RaindexV6AddOrderOwnerTest:testAddOrderOwnerDifferentOwnerStateChange(((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,address) (runs: 100, μ: 1060302, ~: 1045214) +RaindexV6AddOrderOwnerTest:testAddOrderOwnerSameOrderNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 806526, ~: 831952) +RaindexV6AddOrderTest:testAddOrderRealCalculateInputsReverts1(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 565142, ~: 580853) +RaindexV6AddOrderTest:testAddOrderRealCalculateInputsReverts2(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 567005, ~: 582716) +RaindexV6AddOrderTest:testAddOrderRealCalculateInputsRevertsPreference(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 566593, ~: 582304) +RaindexV6AddOrderTest:testAddOrderRealNoHandleIODeploys(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 557181, ~: 572892) +RaindexV6AddOrderTest:testAddOrderRealNoSourcesDeploys(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 536431, ~: 552138) +RaindexV6AddOrderTest:testAddOrderRealOneStackCalculateReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 569719, ~: 585430) +RaindexV6AddOrderTest:testAddOrderRealThreeStackCalculate(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 582910, ~: 598621) +RaindexV6AddOrderTest:testAddOrderRealTwoStackCalculateReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 576219, ~: 591930) +RaindexV6AddOrderTest:testAddOrderRealZeroStackCalculateReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 563783, ~: 579494) +RaindexV6ArbOrderTakerContextTest:testRaindexV6ArbOrderTakerContext() (gas: 1909351) +RaindexV6ArbOrderTakerFallbackTest:testFallbackAcceptsCalldata() (gas: 3149) +RaindexV6ArbOrderTakerFallbackTest:testFallbackAcceptsETHWithCalldata() (gas: 12730) +RaindexV6ArbOrderTakerFallbackTest:testFallbackAcceptsEmptyCalldata() (gas: 3113) +RaindexV6ArbOrderTakerFallbackTest:testReceiveAcceptsETH() (gas: 12645) +RaindexV6ArbOrderTakerIERC165Test:testRaindexV6ArbOrderTakerIERC165(bytes4) (runs: 5096, μ: 1614805, ~: 1614805) +RaindexV6ArbOrderTakerNoOrdersTest:testArb5NoOrders() (gas: 15971) +RaindexV6ArbOrderTakerOnTakeOrders2DirectTest:testOnTakeOrders2DirectCallSucceeds() (gas: 2894327) +RaindexV6ArbOrderTakerOnTakeOrders2Test:testArb5RealTokenTransfers() (gas: 4097781) +RaindexV6ArbOrderTakerReentrancyTest:testArb5Reentrancy() (gas: 4083416) +RaindexV6ArbTaskGatedCheckTaskHashPassMatchTest:testCheckTaskHashPassesWhenMatch(bytes) (runs: 5096, μ: 351383, ~: 345693) +RaindexV6ArbTaskGatedCheckTaskHashPassZeroTest:testCheckTaskHashPassesWhenZero(bytes) (runs: 5096, μ: 341783, ~: 341410) +RaindexV6ArbTaskGatedCheckTaskHashWrongTaskTest:testCheckTaskHashRevertsWrongTask(bytes,bytes) (runs: 5096, μ: 354707, ~: 349220) +RaindexV6ArbTaskGatedConstructTest:testConstructEmitsEvent(bytes) (runs: 5096, μ: 356294, ~: 346724) +RaindexV6ArbTaskGatedITaskHashNonzeroTest:testITaskHashNonzeroBytecode(bytes) (runs: 5096, μ: 349142, ~: 343723) +RaindexV6ArbTaskGatedITaskHashZeroTest:testITaskHashZeroEmptyBytecode() (gas: 338868) +RaindexV6ClearHandleIORevertTest:testClearOrderAliceNoHandleIORevert() (gas: 640071) +RaindexV6ClearHandleIORevertTest:testClearOrderBobNoHandleIORevert() (gas: 640006) +RaindexV6ClearHandleIORevertTest:testClearOrderBothNoHandleIORevert() (gas: 618788) +RaindexV6ClearHandleIORevertTest:testClearOrderHandleIO0() (gas: 672615) +RaindexV6ClearHandleIORevertTest:testClearOrderHandleIO0BothVaultIdZero() (gas: 703035) +RaindexV6ClearHandleIORevertTest:testClearOrderHandleIO1() (gas: 668742) +RaindexV6ClearHandleIORevertTest:testClearOrderHandleIO2() (gas: 668884) +RaindexV6ClearHandleIORevertTest:testClearOrderHandleIO3() (gas: 672571) +RaindexV6ClearHandleIORevertTest:testClearOrderHandleIO4() (gas: 743080) +RaindexV6ClearHandleIORevertTest:testClearOrderHandleIO5() (gas: 705834) +RaindexV6ClearOrderBadStackTest:testClearOrderBadStackEmptyStack(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 1954830, ~: 2038606) +RaindexV6ClearOrderBadStackTest:testClearOrderBadStackOneEmpty(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 2034775, ~: 2119827) +RaindexV6ClearOrderBadStackTest:testClearOrderBadStackOneOne(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 2041943, ~: 2127000) +RaindexV6ClearOrderBadStackTest:testClearOrderBadStackOneOtherOne(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 1975325, ~: 2059111) +RaindexV6ClearOrderBadStackTest:testClearOrderBadStackOneStack(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 1968745, ~: 2052531) +RaindexV6ClearOrderBadStackTest:testClearOrderBadStackOtherEmpty(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 1968176, ~: 2051963) +RaindexV6ClearOrderContextTest:testContextEmptyStack(address,address,bytes32,bytes32,bytes32,bytes32) (runs: 10, μ: 2230716, ~: 2247840) +RaindexV6ClearOrderContextTest:testContextEmptyStackBothVaultIdZero(address,address) (runs: 10, μ: 2044332, ~: 2044852) +RaindexV6ClearSameOwnerTest:testClearSameOwner(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 1180597, ~: 1412796) +RaindexV6ClearSameTokenTest:testClearSameToken(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 1396803, ~: 1440341) +RaindexV6ClearTest:testClear2ZeroRatioAliceAndBob(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1299953, ~: 1291232) +RaindexV6ClearTest:testClear2ZeroRatioAliceOnly(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1321038, ~: 1312522) +RaindexV6ClearTest:testClear2ZeroRatioBobOnly(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1324926, ~: 1316205) +RaindexV6ClearTest:testClearAliceBobOutputVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1332701, ~: 1324295) +RaindexV6ClearTest:testClearAliceBothVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1348404, ~: 1340046) +RaindexV6ClearTest:testClearAliceInputBobBothVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1335650, ~: 1327016) +RaindexV6ClearTest:testClearAliceInputBobOutputVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1348328, ~: 1339809) +RaindexV6ClearTest:testClearAliceInputVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1376957, ~: 1368443) +RaindexV6ClearTest:testClearAliceOutputBobBothVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1320066, ~: 1311384) +RaindexV6ClearTest:testClearAliceOutputVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1361334, ~: 1352984) +RaindexV6ClearTest:testClearAllVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1307093, ~: 1298404) +RaindexV6ClearTest:testClearBobAliceInputVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1364313, ~: 1355686) +RaindexV6ClearTest:testClearBobBothVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1348604, ~: 1339979) +RaindexV6ClearTest:testClearBobInputAliceBothVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1335745, ~: 1327111) +RaindexV6ClearTest:testClearBobInputAliceOutputVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1348698, ~: 1340072) +RaindexV6ClearTest:testClearBobInputVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1377296, ~: 1368676) +RaindexV6ClearTest:testClearBobOutputAliceBothVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1319791, ~: 1311378) +RaindexV6ClearTest:testClearBobOutputVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1361261, ~: 1352749) +RaindexV6ClearTest:testClearFuzzIoRatioError(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32,uint256,uint256) (runs: 100, μ: 1312089, ~: 1287974) +RaindexV6ClearTest:testClearFuzzIoRatioHappy(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32,uint256,uint256) (runs: 100, μ: 1370413, ~: 1345387) +RaindexV6ClearTest:testClearSimple(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 1000, μ: 1394341, ~: 1374997) +RaindexV6ClearZeroAmountTest:testClearZeroAmount(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 2167411, ~: 2232487) +RaindexV6DepositEnactTest:testDepositRevertInAction(address,bytes32,uint256) (runs: 10, μ: 141395, ~: 141509) +RaindexV6DepositEnactTest:testOrderDepositContext(address,bytes32,uint256,uint256) (runs: 10, μ: 733659, ~: 743522) +RaindexV6DepositEnactTest:testRaindexDepositEnactEmptyNoop(address,bytes32,uint256) (runs: 10, μ: 92085, ~: 92199) +RaindexV6DepositEnactTest:testRaindexDepositEnactOneReadState(address,bytes32,uint256) (runs: 10, μ: 153388, ~: 153502) +RaindexV6DepositEnactTest:testRaindexDepositEnactOneStateless(address,bytes32,uint256) (runs: 10, μ: 138465, ~: 138579) +RaindexV6DepositEnactTest:testRaindexDepositEvalWriteStateDifferentOwnersNamespaced(address,address,bytes32,uint256) (runs: 10, μ: 1013146, ~: 1012819) +RaindexV6DepositEnactTest:testRaindexDepositEvalWriteStateSequential(address,bytes32,uint256) (runs: 10, μ: 640232, ~: 640296) +RaindexV6DepositEnactTest:testRaindexDepositEvalWriteStateSingle(address,bytes32,uint256) (runs: 10, μ: 263227, ~: 263291) +RaindexV6DepositTest:testDepositEvent(address,bytes32,uint256) (runs: 100, μ: 88407, ~: 88381) +RaindexV6DepositTest:testDepositFail(address,bytes32,uint256) (runs: 100, μ: 1040483736, ~: 1040483676) +RaindexV6DepositTest:testDepositGas00() (gas: 15751) +RaindexV6DepositTest:testDepositGas01() (gas: 83927) +RaindexV6DepositTest:testDepositMany((address,address,bytes32,uint256,bytes32)[]) (runs: 100, μ: 10354159, ~: 9671538) +RaindexV6DepositTest:testDepositReentrancy(address,bytes32,uint256,address,bytes32,uint256) (runs: 100, μ: 527807, ~: 527879) +RaindexV6DepositTest:testDepositSimple(address,bytes32,uint256) (runs: 100, μ: 87877, ~: 87851) +RaindexV6DepositTest:testDepositZero(address,bytes32) (runs: 100, μ: 31062, ~: 31137) +RaindexV6DepositTest:testDepositZeroVaultId(address,address,bytes32) (runs: 5096, μ: 30908, ~: 31010) +RaindexV6EnactTest:testRaindexEvalEmptyNoop(address) (runs: 100, μ: 34149, ~: 34224) +RaindexV6EnactTest:testRaindexEvalOneReadState(address) (runs: 100, μ: 92873, ~: 92948) +RaindexV6EnactTest:testRaindexEvalOneStateless(address) (runs: 100, μ: 77993, ~: 78068) +RaindexV6EnactTest:testRaindexEvalWriteStateDifferentOwnersNamespaced(address,address) (runs: 100, μ: 878147, ~: 878222) +RaindexV6EnactTest:testRaindexEvalWriteStateSequential() (gas: 556418) +RaindexV6EnactTest:testRaindexEvalWriteStateSingle(address) (runs: 100, μ: 189480, ~: 189555) +RaindexV6FlashBorrowerBadInitiatorTest:testOnFlashLoanBadInitiator(address) (runs: 5096, μ: 11005, ~: 11005) +RaindexV6FlashBorrowerBadLenderApprovalTest:testBadLenderRevertsWithApproval() (gas: 4383922) +RaindexV6FlashBorrowerFallbackTest:testFallbackAcceptsCalldata() (gas: 3149) +RaindexV6FlashBorrowerFallbackTest:testFallbackAcceptsETHWithCalldata() (gas: 12730) +RaindexV6FlashBorrowerFallbackTest:testFallbackAcceptsEmptyCalldata() (gas: 3113) +RaindexV6FlashBorrowerFallbackTest:testReceiveAcceptsETH() (gas: 12645) +RaindexV6FlashBorrowerFlashLoanFailedTest:testFlashLoanFailed() (gas: 4133090) +RaindexV6FlashBorrowerIERC165Test:testRaindexV6FlashBorrowerIERC165(bytes4) (runs: 5096, μ: 2154375, ~: 2154375) +RaindexV6FlashBorrowerLenderValidationTest:testMaliciousLenderCannotExploitOnFlashLoan() (gas: 2954818) +RaindexV6FlashBorrowerMixedDecimalsTest:testArb4MixedDecimals() (gas: 4697995) +RaindexV6FlashBorrowerNoOrdersTest:testArb4NoOrders() (gas: 16224) +RaindexV6FlashBorrowerRealTokenTransfersTest:testArb4RealTokenTransfers() (gas: 4701891) +RaindexV6FlashBorrowerReentrancyTest:testArb4Reentrancy() (gas: 4741194) +RaindexV6FlashLenderFeeTest:testFlashFee(address,uint256) (runs: 5096, μ: 3804, ~: 3804) +RaindexV6FlashLenderGriefRecipientTest:testFlashLoanToNonReceiver(uint256,bytes,bytes32,bytes) (runs: 5096, μ: 25328, ~: 24363) +RaindexV6FlashLenderIERC165Test:testRaindexV6FlashLenderIERC165(bytes4) (runs: 5096, μ: 312268, ~: 312268) +RaindexV6FlashLenderMaxFlashLoanTest:testFlashMaxLoan(uint256) (runs: 5096, μ: 7472, ~: 7472) +RaindexV6FlashLenderMockSuccessTest:testFlashLoanToReceiver(uint256,bytes) (runs: 5096, μ: 12182, ~: 11877) +RaindexV6FlashLenderReentrant:testReenterAddOrder(uint256,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 13516112, ~: 14090389) +RaindexV6FlashLenderReentrant:testReenterCheckOrderExists(bytes32,uint256) (runs: 100, μ: 407684, ~: 409475) +RaindexV6FlashLenderReentrant:testReenterClear(uint256,address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 26256780, ~: 27189818) +RaindexV6FlashLenderReentrant:testReenterDeposit(uint256,uint256,uint256) (runs: 100, μ: 555676, ~: 555995) +RaindexV6FlashLenderReentrant:testReenterReadVaultBalances(uint256,uint256) (runs: 100, μ: 454758, ~: 454957) +RaindexV6FlashLenderReentrant:testReenterRemoveOrder(uint256,(address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32)) (runs: 100, μ: 12516412, ~: 12823819) +RaindexV6FlashLenderReentrant:testReenterTakeOrder(uint256,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 13619158, ~: 13741253) +RaindexV6FlashLenderReentrant:testReenterWithdraw(uint256,uint256,uint256) (runs: 100, μ: 536933, ~: 537451) +RaindexV6FlashLenderTransferTest:testFlashLoanTransferFail(uint256,uint256,bool) (runs: 100, μ: 881755, ~: 883695) +RaindexV6FlashLenderTransferTest:testFlashLoanTransferSuccess(uint256,bool) (runs: 100, μ: 833293, ~: 826424) +RaindexV6QuoteSameTokenTest:testQuoteSameToken(((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,bytes32[],bytes)[])) (runs: 10, μ: 9325366, ~: 8700273) +RaindexV6QuoteTest:testQuoteContextSender(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),uint256) (runs: 100, μ: 9063594, ~: 8888604) +RaindexV6QuoteTest:testQuoteDeadOrder(((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,bytes32[],bytes)[])) (runs: 100, μ: 8103938, ~: 7514207) +RaindexV6QuoteTest:testQuoteMaxOutput(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),uint256) (runs: 100, μ: 1055942, ~: 1035470) +RaindexV6QuoteTest:testQuoteSimple(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),uint256) (runs: 100, μ: 1049447, ~: 1029711) +RaindexV6QuoteTest:testQuoteSimpleBothVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),uint256) (runs: 100, μ: 1010867, ~: 991129) +RaindexV6RemoveOrderEnactTest:testRemoveOrderContext(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 676462, ~: 687049) +RaindexV6RemoveOrderEnactTest:testRemoveOrderDeadOrder(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 356482, ~: 364953) +RaindexV6RemoveOrderEnactTest:testRemoveOrderEmptyNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 874495, ~: 903175) +RaindexV6RemoveOrderEnactTest:testRemoveOrderOneReadState(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 934769, ~: 963455) +RaindexV6RemoveOrderEnactTest:testRemoveOrderOneStateless(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 919952, ~: 948638) +RaindexV6RemoveOrderEnactTest:testRemoveOrderRevertInAction(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 1032728, ~: 1064218) +RaindexV6RemoveOrderEnactTest:testRemoveOrderWriteStateDifferentOwnersNamespaced(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 4258817, ~: 4113599) +RaindexV6RemoveOrderEnactTest:testRemoveOrderWriteStateSequential(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 1166237, ~: 1194937) +RaindexV6RemoveOrderEnactTest:testRemoveOrderWriteStateSingle(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 1791619, ~: 1846282) +RaindexV6RemoveOrderMockTest:testRemoveOrderAddRemoveMulti(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 100, μ: 5232985, ~: 4993442) +RaindexV6RemoveOrderMockTest:testRemoveOrderDifferent(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 100, μ: 3794890, ~: 3971187) +RaindexV6RemoveOrderMockTest:testRemoveOrderDifferentOwners(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 100, μ: 3416772, ~: 3220010) +RaindexV6RemoveOrderMockTest:testRemoveOrderDifferentOwnersDifferent(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 100, μ: 7284202, ~: 7123781) +RaindexV6RemoveOrderMockTest:testRemoveOrderDoesNotExist(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 100, μ: 376436, ~: 362925) +RaindexV6RemoveOrderMockTest:testRemoveOrderOnlyOwner(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 100, μ: 1903567, ~: 1800049) +RaindexV6RemoveOrderOwnerTest:testRemoveOrderOwnerDifferentOwnerStateChange(((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,address) (runs: 100, μ: 4679006, ~: 4572729) +RaindexV6RemoveOrderOwnerTest:testRemoveOrderOwnerSameOrderNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 2652659, ~: 2741449) +RaindexV6RemoveOrderOwnerTest:testRemoveOrderWrongOwner(((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,address) (runs: 100, μ: 689918, ~: 680133) +RaindexV6SubParserContextCalculatedIORatioTest:testSubParserContextHappy() (gas: 94106) +RaindexV6SubParserContextCalculatedIORatioTest:testSubParserContextUnhappyDisallowedInputs() (gas: 71681) +RaindexV6SubParserContextCalculatedIORatioTest:testSubParserContextUnhappyDisallowedOperand() (gas: 57743) +RaindexV6SubParserContextCalculatedMaxOutputTest:testSubParserContextHappy() (gas: 94433) +RaindexV6SubParserContextCalculatedMaxOutputTest:testSubParserContextUnhappyDisallowedInputs() (gas: 72004) +RaindexV6SubParserContextCalculatedMaxOutputTest:testSubParserContextUnhappyDisallowedOperand() (gas: 58071) +RaindexV6SubParserContextInputTokenDecimalsTest:testSubParserContextHappy() (gas: 94272) +RaindexV6SubParserContextInputTokenDecimalsTest:testSubParserContextUnhappyDisallowedInputs() (gas: 71843) +RaindexV6SubParserContextInputTokenDecimalsTest:testSubParserContextUnhappyDisallowedOperand() (gas: 57909) +RaindexV6SubParserContextInputTokenTest:testSubParserContextHappy() (gas: 92809) +RaindexV6SubParserContextInputTokenTest:testSubParserContextUnhappyDisallowedInputs() (gas: 70381) +RaindexV6SubParserContextInputTokenTest:testSubParserContextUnhappyDisallowedOperand() (gas: 56447) +RaindexV6SubParserContextInputVaultBalanceBeforeTest:testSubParserContextHappy() (gas: 93944) +RaindexV6SubParserContextInputVaultBalanceBeforeTest:testSubParserContextUnhappyDisallowedInputs() (gas: 71519) +RaindexV6SubParserContextInputVaultBalanceBeforeTest:testSubParserContextUnhappyDisallowedOperand() (gas: 57581) +RaindexV6SubParserContextInputVaultBalanceIncreaseTest:testSubParserContextHappy() (gas: 94272) +RaindexV6SubParserContextInputVaultBalanceIncreaseTest:testSubParserContextUnhappyDisallowedInputs() (gas: 71843) +RaindexV6SubParserContextInputVaultBalanceIncreaseTest:testSubParserContextUnhappyDisallowedOperand() (gas: 57909) +RaindexV6SubParserContextInputVaultIdTest:testSubParserContextHappy() (gas: 94007) +RaindexV6SubParserContextInputVaultIdTest:testSubParserContextUnhappyDisallowedInputs() (gas: 71579) +RaindexV6SubParserContextInputVaultIdTest:testSubParserContextUnhappyDisallowedOperand() (gas: 57644) +RaindexV6SubParserContextOrderClearerTest:testSubParserContextHappy() (gas: 93133) +RaindexV6SubParserContextOrderClearerTest:testSubParserContextUnhappyDisallowedInputs() (gas: 70705) +RaindexV6SubParserContextOrderClearerTest:testSubParserContextUnhappyDisallowedOperand() (gas: 56771) +RaindexV6SubParserContextOrderCounterpartyTest:testSubParserContextHappy() (gas: 93944) +RaindexV6SubParserContextOrderCounterpartyTest:testSubParserContextUnhappyDisallowedInputs() (gas: 71519) +RaindexV6SubParserContextOrderCounterpartyTest:testSubParserContextUnhappyDisallowedOperand() (gas: 57581) +RaindexV6SubParserContextOrderHashTest:testSubParserContextHappy() (gas: 93358) +RaindexV6SubParserContextOrderHashTest:testSubParserContextUnhappyDisallowedInputs() (gas: 70930) +RaindexV6SubParserContextOrderHashTest:testSubParserContextUnhappyDisallowedOperand() (gas: 56996) +RaindexV6SubParserContextOrderOwnerTest:testSubParserContextHappy() (gas: 92810) +RaindexV6SubParserContextOrderOwnerTest:testSubParserContextUnhappyDisallowedInputs() (gas: 70382) +RaindexV6SubParserContextOrderOwnerTest:testSubParserContextUnhappyDisallowedOperand() (gas: 56447) +RaindexV6SubParserContextOutputTokenDecimalsTest:testSubParserContextHappy() (gas: 94434) +RaindexV6SubParserContextOutputTokenDecimalsTest:testSubParserContextUnhappyDisallowedInputs() (gas: 72005) +RaindexV6SubParserContextOutputTokenDecimalsTest:testSubParserContextUnhappyDisallowedOperand() (gas: 58071) +RaindexV6SubParserContextOutputTokenTest:testSubParserContextHappy() (gas: 92971) +RaindexV6SubParserContextOutputTokenTest:testSubParserContextUnhappyDisallowedInputs() (gas: 70543) +RaindexV6SubParserContextOutputTokenTest:testSubParserContextUnhappyDisallowedOperand() (gas: 56609) +RaindexV6SubParserContextOutputVaultBalanceBeforeTest:testSubParserContextHappy() (gas: 94106) +RaindexV6SubParserContextOutputVaultBalanceBeforeTest:testSubParserContextUnhappyDisallowedInputs() (gas: 71681) +RaindexV6SubParserContextOutputVaultBalanceBeforeTest:testSubParserContextUnhappyDisallowedOperand() (gas: 57743) +RaindexV6SubParserContextOutputVaultBalanceDecreaseTest:testSubParserContextHappy() (gas: 94434) +RaindexV6SubParserContextOutputVaultBalanceDecreaseTest:testSubParserContextUnhappyDisallowedInputs() (gas: 72005) +RaindexV6SubParserContextOutputVaultBalanceDecreaseTest:testSubParserContextUnhappyDisallowedOperand() (gas: 58071) +RaindexV6SubParserContextOutputVaultIdTest:testSubParserContextHappy() (gas: 93458) +RaindexV6SubParserContextOutputVaultIdTest:testSubParserContextUnhappyDisallowedInputs() (gas: 71030) +RaindexV6SubParserContextOutputVaultIdTest:testSubParserContextUnhappyDisallowedOperand() (gas: 57095) +RaindexV6SubParserContextRaindexTest:testSubParserContextHappy() (gas: 92161) +RaindexV6SubParserContextRaindexTest:testSubParserContextUnhappyDisallowedInputs() (gas: 69733) +RaindexV6SubParserContextRaindexTest:testSubParserContextUnhappyDisallowedOperand() (gas: 55799) +RaindexV6SubParserDescribedByMetaV1Test:testRaindexV6SubParserDescribedByMetaV1Happy() (gas: 7351) +RaindexV6SubParserIERC165Test:testRaindexV6SubParserIERC165(bytes4) (runs: 5096, μ: 13077, ~: 13077) +RaindexV6SubParserPointersTest:testSubParserFunctionPointers() (gas: 19234) +RaindexV6SubParserPointersTest:testSubParserOperandParsers() (gas: 19256) +RaindexV6SubParserPointersTest:testSubParserParseMeta() (gas: 104645) +RaindexV6SubParserPointersTest:testWordOperandLengthEquivalence() (gas: 925) +RaindexV6SubParserSignedContextTest:testSubParserContextSignedContextHappy0() (gas: 99740) +RaindexV6SubParserSignedContextTest:testSubParserContextSignedContextHappy1() (gas: 99832) +RaindexV6SubParserSignedContextTest:testSubParserContextSignedContextHappy2() (gas: 99833) +RaindexV6SubParserSignedContextTest:testSubParserContextSignedContextHappy3() (gas: 100013) +RaindexV6SubParserSignedContextTest:testSubParserContextSignedContextUnhappyInput() (gas: 77164) +RaindexV6SubParserSignedContextTest:testSubParserContextSignedContextUnhappyNoOperand() (gas: 53858) +RaindexV6SubParserSignedContextTest:testSubParserContextSignedContextUnhappyTooManyOperands() (gas: 62552) +RaindexV6SubParserSignersTest:testSubParserContextSignerHappy0() (gas: 95106) +RaindexV6SubParserSignersTest:testSubParserContextSignerHappy1() (gas: 95220) +RaindexV6SubParserSignersTest:testSubParserContextSignerUnhappyInput() (gas: 72560) +RaindexV6SubParserSignersTest:testSubParserContextSignerUnhappyNoOperand() (gas: 52534) +RaindexV6SubParserSignersTest:testSubParserContextSignerUnhappyTooManyOperands() (gas: 58366) +RaindexV6TakeOrderBadStackTest:testTakeOrderBadStackEmptyStack(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 882291, ~: 846981) +RaindexV6TakeOrderBadStackTest:testTakeOrderBadStackOneStack(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 889172, ~: 853858) +RaindexV6TakeOrderExceedsMaxRatioTest:testTakeOrderExceedsMaxRatio() (gas: 258233) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO00() (gas: 320920) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO00BothVaultIdZero() (gas: 302984) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO1() (gas: 499705) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO10(uint256) (runs: 100, μ: 710374, ~: 674157) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO2() (gas: 514077) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO3() (gas: 672957) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO4() (gas: 689985) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO5() (gas: 689970) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO6() (gas: 675612) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO7(uint256) (runs: 100, μ: 945377, ~: 945663) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO8(uint256) (runs: 100, μ: 1119342, ~: 1119606) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO9(uint256) (runs: 100, μ: 790383, ~: 726129) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderNoHandleIORevert0() (gas: 316087) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderNoHandleIORevert1() (gas: 488717) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderNoHandleIORevert2() (gas: 474325) +RaindexV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputMultipleOrdersMultipleOwners(uint256,uint256,uint256) (runs: 100, μ: 554180, ~: 581444) +RaindexV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputMultipleOrdersSingleOwner(uint256,uint256) (runs: 100, μ: 500663, ~: 524679) +RaindexV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputSingleAnyDeposit(uint256,uint256) (runs: 100, μ: 344261, ~: 347866) +RaindexV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputSingleAnyDepositBothVaultIdZero(uint256,uint256) (runs: 100, μ: 302832, ~: 303843) +RaindexV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputSingleOrderLessThanMaximumInput(uint256,uint256) (runs: 100, μ: 318422, ~: 323492) +RaindexV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputSingleOrderLessThanMaximumOutput(uint256) (runs: 100, μ: 325326, ~: 325230) +RaindexV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputSingleOrderUnlimitedMax(uint256) (runs: 100, μ: 318278, ~: 318237) +RaindexV6TakeOrderMaximumInputTest:testTakeOrderNoopZeroMaxTakerInput((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),(address,bytes32[],bytes)) (runs: 100, μ: 172148, ~: 175764) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputMultipleOrders(uint256,uint256) (runs: 100, μ: 516474, ~: 539231) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputMultipleOrdersBothVaultIdZero(uint256,uint256) (runs: 100, μ: 502885, ~: 520401) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputMultipleOrdersDifferentOwners(uint256,uint256,uint256) (runs: 100, μ: 579605, ~: 608407) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputMultipleOrdersDifferentOwnersBothVaultIdZero(uint256,uint256,uint256) (runs: 100, μ: 509239, ~: 530794) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputSingleAnyDeposit(uint256,uint256) (runs: 100, μ: 354953, ~: 357648) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputSingleAnyDepositBothVaultIdZero(uint256,uint256) (runs: 5096, μ: 312790, ~: 313612) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputSingleAnyDepositInputVaultIdZero(uint256,uint256) (runs: 5096, μ: 339349, ~: 343084) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputSingleAnyDepositOutputVaultIdZero(uint256,uint256) (runs: 5096, μ: 327105, ~: 328154) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputSingleOrderLimitedByVault(uint256,uint256) (runs: 100, μ: 325575, ~: 330816) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputSingleOrderLimitedMax(uint256) (runs: 100, μ: 329932, ~: 330236) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputSingleOrderUnlimitedMax(uint256) (runs: 100, μ: 325868, ~: 325949) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputZero((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),(address,bytes32[],bytes)) (runs: 5096, μ: 179347, ~: 178322) +RaindexV6TakeOrderMinimumIOTest:testTakeOrderMinimumIORevert() (gas: 284449) +RaindexV6TakeOrderNoopTest:testTakeOrderNoopNonLiveOrderOne((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,bytes32[],bytes)) (runs: 100, μ: 449200, ~: 452997) +RaindexV6TakeOrderNoopTest:testTakeOrderNoopNonLiveOrderTwo((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),(address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,uint256,uint256,(address,bytes32[],bytes),(address,bytes32[],bytes)) (runs: 100, μ: 801426, ~: 788472) +RaindexV6TakeOrderNoopTest:testTakeOrderNoopZeroOrders() (gas: 30529) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad01() (gas: 325437) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad01BothVaultIdZero() (gas: 306756) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad02() (gas: 325438) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad03() (gas: 327154) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad04() (gas: 327132) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad05() (gas: 327089) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad06() (gas: 327110) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad07() (gas: 326067) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad08() (gas: 326044) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad09() (gas: 326024) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad10() (gas: 326067) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad11() (gas: 326509) +RaindexV6TakeOrderSameTokenTest:testTakeOrderSameToken(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 672562, ~: 702210) +RaindexV6TakeOrderTokenMismatchTest:testTokenDecimalMismatchOutputs((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,uint256,uint256) (runs: 10, μ: 592418, ~: 592485) +RaindexV6TakeOrderTokenMismatchTest:testTokenMismatchInputs((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,uint256,uint256) (runs: 10, μ: 592251, ~: 592318) +RaindexV6VaultBalanceTest:testVaultBalanceNoDeposits(address,address,bytes32) (runs: 5096, μ: 9254, ~: 9254) +RaindexV6WithdrawEvalTest:testOrderWithdrawContext(address,bytes32,uint256,uint256) (runs: 100, μ: 802331, ~: 798475) +RaindexV6WithdrawEvalTest:testRaindexWithdrawEvalEmptyNoop(address,bytes32,uint256,uint256) (runs: 100, μ: 114405, ~: 115488) +RaindexV6WithdrawEvalTest:testRaindexWithdrawEvalOneReadState(address,bytes32,uint256,uint256) (runs: 100, μ: 175556, ~: 176639) +RaindexV6WithdrawEvalTest:testRaindexWithdrawEvalOneStateless(address,bytes32,uint256,uint256) (runs: 100, μ: 160694, ~: 161777) +RaindexV6WithdrawEvalTest:testRaindexWithdrawEvalWriteStateDifferentOwnersNamespaced(address,address,bytes32,uint256,uint256) (runs: 100, μ: 1096418, ~: 1099893) +RaindexV6WithdrawEvalTest:testRaindexWithdrawEvalWriteStateSequential(address,bytes32,uint256,uint256) (runs: 100, μ: 684677, ~: 685822) +RaindexV6WithdrawEvalTest:testRaindexWithdrawEvalWriteStateSingle(address,bytes32,uint256,uint256) (runs: 100, μ: 306906, ~: 308051) +RaindexV6WithdrawEvalTest:testRaindexWithdrawalEvalRevertInAction(address,bytes32,uint256,uint256) (runs: 100, μ: 157058, ~: 158141) +RaindexV6WithdrawEvalTest:testRaindexWithdrawalEvalZeroAmountEvalNoop(address,bytes32,uint256) (runs: 100, μ: 125722, ~: 125539) +RaindexV6WithdrawTest:testWithdrawEmptyVault(address,bytes32,uint256) (runs: 100, μ: 74357, ~: 74331) +RaindexV6WithdrawTest:testWithdrawFailure(address,bytes32,uint256,uint256) (runs: 100, μ: 1040425210, ~: 1040443415) +RaindexV6WithdrawTest:testWithdrawFullVault(address,bytes32,uint256,uint256) (runs: 100, μ: 88225, ~: 88257) +RaindexV6WithdrawTest:testWithdrawMany((bool,address,address,bytes32,uint256,bytes32,uint256,bool)[]) (runs: 100, μ: 6625444, ~: 6768896) +RaindexV6WithdrawTest:testWithdrawPartialVault(address,bytes32,uint256,uint256) (runs: 100, μ: 111846, ~: 111815) +RaindexV6WithdrawTest:testWithdrawZero(address,address,bytes32) (runs: 100, μ: 31101, ~: 31151) +RaindexV6WithdrawTest:testWithdrawZeroVaultId(address,address) (runs: 5096, μ: 30266, ~: 30343) +RouteProcessorRaindexV6ArbOrderTakerLossyRoundingTest:testOnTakeOrders2LossyOutputRoundsUp() (gas: 159755) +RouteProcessorRaindexV6ArbOrderTakerNonStandardDecimalsTest:testRouteProcessorArb5SixDecimalTokens() (gas: 4302386) +RouteProcessorRaindexV6ArbOrderTakerOnTakeOrders2DirectTest:testOnTakeOrders2DirectCallByAttacker() (gas: 3245122) +RouteProcessorRaindexV6ArbOrderTakerOnTakeOrders2Test:testRouteProcessorArb5() (gas: 4302213) +RouteProcessorRaindexV6ArbOrderTakerSenderTest:testRouteProcessorTakeOrdersSender((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256) (runs: 100, μ: 253612, ~: 259029) \ No newline at end of file From 028ece0b0f06a202c8978cd531134881ba20fd12 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Tue, 31 Mar 2026 20:29:51 +0400 Subject: [PATCH 27/69] Fix spelling, stale comments, and ob-yaml URL references MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix "raindexs" → "raindexes" spelling in test descriptions - Rename OB_NPM_PACKAGE → RAINDEX_NPM_PACKAGE in CI - Rename ob-addr CLI alias → raindex-addr - Update ob-yaml.md URLs → raindex-yaml.md - Fix "order book" → "raindex" in NatSpec comments Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/npm-package-release.yml | 4 ++-- crates/cli/src/commands/order/mod.rs | 2 +- crates/common/src/raindex_client/mod.rs | 2 +- crates/js_api/src/yaml/mod.rs | 2 +- .../ui-components/src/__tests__/LocalDbStatusModal.test.ts | 4 ++-- test/abstract/RaindexV6FlashLender.maxFlashLoan.t.sol | 2 +- test/concrete/ob/RaindexV6.deposit.t.sol | 2 +- test/concrete/ob/RaindexV6.withdraw.t.sol | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/npm-package-release.yml b/.github/workflows/npm-package-release.yml index 01d674569e..3a676e962d 100644 --- a/.github/workflows/npm-package-release.yml +++ b/.github/workflows/npm-package-release.yml @@ -186,11 +186,11 @@ jobs: # Create raindex npm package tarball - name: Create raindex NPM Package Tarball if: ${{ env.OLD_HASH != env.NEW_HASH }} - run: echo "OB_NPM_PACKAGE=$(npm pack --silent -w @rainlanguage/raindex)" >> $GITHUB_ENV + run: echo "RAINDEX_NPM_PACKAGE=$(npm pack --silent -w @rainlanguage/raindex)" >> $GITHUB_ENV - name: Rename raindex NPM Package Tarball if: ${{ env.OLD_HASH != env.NEW_HASH }} - run: mv ${{ env.OB_NPM_PACKAGE }} raindex_npm_package_${{ env.NEW_VERSION }}.tgz + run: mv ${{ env.RAINDEX_NPM_PACKAGE }} raindex_npm_package_${{ env.NEW_VERSION }}.tgz # publish raindex pkg to npm - name: Publish raindex pkg To NPM diff --git a/crates/cli/src/commands/order/mod.rs b/crates/cli/src/commands/order/mod.rs index ef60e2a7c5..e98e5d754c 100644 --- a/crates/cli/src/commands/order/mod.rs +++ b/crates/cli/src/commands/order/mod.rs @@ -45,7 +45,7 @@ pub enum Order { #[command( about = "Get the raindex address for a given order", - alias = "ob-addr" + alias = "raindex-addr" )] RaindexAddress(RaindexAddress), diff --git a/crates/common/src/raindex_client/mod.rs b/crates/common/src/raindex_client/mod.rs index 661d2117c2..cfbb8a07cb 100644 --- a/crates/common/src/raindex_client/mod.rs +++ b/crates/common/src/raindex_client/mod.rs @@ -131,7 +131,7 @@ impl RaindexClient { #[wasm_export( js_name = "raindexYamls", param_description = "List of YAML configuration strings. \ - The YAML files must match the [raindex yaml spec](https://github.com/rainlanguage/specs/blob/main/ob-yaml.md) + The YAML files must match the [raindex yaml spec](https://github.com/rainlanguage/specs/blob/main/raindex-yaml.md) " )] raindex_yamls: Vec, diff --git a/crates/js_api/src/yaml/mod.rs b/crates/js_api/src/yaml/mod.rs index dc2fadcda3..c2039e085b 100644 --- a/crates/js_api/src/yaml/mod.rs +++ b/crates/js_api/src/yaml/mod.rs @@ -28,7 +28,7 @@ impl RaindexYaml { /// This constructor parses one or more YAML configuration strings to create an RaindexYaml /// instance that provides access to raindex configurations, network settings, tokens, and /// other deployment metadata. The YAML sources are merged and validated according to the - /// [raindex specification](https://github.com/rainlanguage/specs/blob/main/ob-yaml.md). + /// [raindex specification](https://github.com/rainlanguage/specs/blob/main/raindex-yaml.md). /// /// ## Examples /// diff --git a/packages/ui-components/src/__tests__/LocalDbStatusModal.test.ts b/packages/ui-components/src/__tests__/LocalDbStatusModal.test.ts index c78b2c182b..485b935ef7 100644 --- a/packages/ui-components/src/__tests__/LocalDbStatusModal.test.ts +++ b/packages/ui-components/src/__tests__/LocalDbStatusModal.test.ts @@ -252,7 +252,7 @@ describe('LocalDbStatusModal', () => { expect(screen.getByText('Network initialization failed')).toBeInTheDocument(); }); - it('groups raindexs correctly by chain ID', () => { + it('groups raindexes correctly by chain ID', () => { const networkStatuses = new Map([ [137, { chainId: 137, status: 'active', schedulerState: 'leader' }], [42161, { chainId: 42161, status: 'active', schedulerState: 'leader' }] @@ -299,7 +299,7 @@ describe('LocalDbStatusModal', () => { expect(screen.getByText('0x2222222222222222222222222222222222222222')).toBeInTheDocument(); }); - it('handles multiple raindexs on the same network', () => { + it('handles multiple raindexes on the same network', () => { const networkStatuses = new Map([ [137, { chainId: 137, status: 'active', schedulerState: 'leader' }] ]); diff --git a/test/abstract/RaindexV6FlashLender.maxFlashLoan.t.sol b/test/abstract/RaindexV6FlashLender.maxFlashLoan.t.sol index 0ff8ef4ff2..052f59d2ad 100644 --- a/test/abstract/RaindexV6FlashLender.maxFlashLoan.t.sol +++ b/test/abstract/RaindexV6FlashLender.maxFlashLoan.t.sol @@ -9,7 +9,7 @@ import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; /// Tests the maximum flash loan amount for `RaindexV6FlashLender`. contract RaindexV6FlashLenderMaxFlashLoanTest is RaindexV6ExternalMockTest { /// Tests that the maximum flash loan amount for `RaindexV6FlashLender` is - /// the balance of the token in the order book. + /// the balance of the token in the raindex. function testFlashMaxLoan(uint256 amount) public { vm.mockCall( address(iToken0), abi.encodeWithSelector(IERC20.balanceOf.selector, address(iRaindex)), abi.encode(amount) diff --git a/test/concrete/ob/RaindexV6.deposit.t.sol b/test/concrete/ob/RaindexV6.deposit.t.sol index f80cf22989..9c3edaaf75 100644 --- a/test/concrete/ob/RaindexV6.deposit.t.sol +++ b/test/concrete/ob/RaindexV6.deposit.t.sol @@ -14,7 +14,7 @@ import {ReentrancyGuard} from "openzeppelin-contracts/contracts/utils/Reentrancy import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; /// @title RaindexV6DepositTest -/// Tests depositing to an order book. +/// Tests depositing to a raindex. contract RaindexV6DepositTest is RaindexV6ExternalMockTest { using LibDecimalFloat for Float; diff --git a/test/concrete/ob/RaindexV6.withdraw.t.sol b/test/concrete/ob/RaindexV6.withdraw.t.sol index 96af2852bb..5e62d7fdc3 100644 --- a/test/concrete/ob/RaindexV6.withdraw.t.sol +++ b/test/concrete/ob/RaindexV6.withdraw.t.sol @@ -16,7 +16,7 @@ import {LibDecimalFloatImplementation} from "rain.math.float/lib/implementation/ import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; /// @title RaindexV6WithdrawTest -/// Tests withdrawing from the order book. +/// Tests withdrawing from the raindex. contract RaindexV6WithdrawTest is RaindexV6ExternalMockTest { using Math for uint256; From 0ec04e56ae2872322b9ccb3a48e86309c9c257b3 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Tue, 31 Mar 2026 21:13:16 +0400 Subject: [PATCH 28/69] Rename ob- Nix commands to raindex- prefixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ob-rs-test → raindex-rs-test - ob-ui-components-prelude → raindex-ui-components-prelude - rainix-ob-cli-artifact → raindex-cli-artifact Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/copilot-instructions.md | 2 +- .github/workflows/build-cli-binary.yaml | 2 +- .github/workflows/rainix.yaml | 2 +- flake.nix | 18 +++++++++--------- prep-all.sh | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 0e3f2b8fe1..58d984ee20 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -71,7 +71,7 @@ nix develop -c bash -c '(cd lib/rain.interpreter && rainix-sol-prelude && rainix nix develop -c bash -c '(cd lib/rain.interpreter/lib/rain.interpreter.interface/lib/rain.math.float && rainix-sol-prelude && rainix-rs-prelude)' nix develop -c bash -c '(cd lib/rain.interpreter/lib/rain.metadata && rainix-sol-prelude && rainix-rs-prelude)' nix develop -c rainix-sol-prelude && nix develop -c rainix-rs-prelude && nix develop -c raindex-prelude -nix develop -c ob-ui-components-prelude +nix develop -c raindex-ui-components-prelude nix develop -c npm run build -w @rainlanguage/raindex nix develop -c npm run build -w @rainlanguage/ui-components nix develop -c npm run build -w @rainlanguage/webapp diff --git a/.github/workflows/build-cli-binary.yaml b/.github/workflows/build-cli-binary.yaml index e550828f91..673ab2bc22 100644 --- a/.github/workflows/build-cli-binary.yaml +++ b/.github/workflows/build-cli-binary.yaml @@ -43,7 +43,7 @@ jobs: - run: ./prep-base.sh - name: Build CLI tarball - run: nix develop -c rainix-ob-cli-artifact + run: nix develop -c raindex-cli-artifact - name: Prepare release metadata run: | diff --git a/.github/workflows/rainix.yaml b/.github/workflows/rainix.yaml index 3139533289..782ffc87e9 100644 --- a/.github/workflows/rainix.yaml +++ b/.github/workflows/rainix.yaml @@ -17,7 +17,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest] - task: [ob-rs-test, rainix-rs-artifacts] + task: [raindex-rs-test, rainix-rs-artifacts] is-not-main: - ${{ github.ref != 'refs/heads/main' }} include: diff --git a/flake.nix b/flake.nix index 8e21de91f9..9a96005901 100644 --- a/flake.nix +++ b/flake.nix @@ -33,16 +33,16 @@ ''; }; - ob-rs-test = rainix.mkTask.${system} { - name = "ob-rs-test"; + raindex-rs-test = rainix.mkTask.${system} { + name = "raindex-rs-test"; body = '' set -euxo pipefail cargo test --workspace ''; }; - ob-ui-components-prelude = rainix.mkTask.${system} { - name = "ob-ui-components-prelude"; + raindex-ui-components-prelude = rainix.mkTask.${system} { + name = "raindex-ui-components-prelude"; body = '' set -euxo pipefail @@ -56,8 +56,8 @@ ]; }; - rainix-ob-cli-artifact = rainix.mkTask.${system} { - name = "rainix-ob-cli-artifact"; + raindex-cli-artifact = rainix.mkTask.${system} { + name = "raindex-cli-artifact"; body = '' set -euxo pipefail @@ -151,7 +151,7 @@ devShells.default = pkgs.mkShell { packages = [ packages.raindex-prelude - packages.ob-rs-test + packages.raindex-rs-test packages.rainix-wasm-artifacts packages.rainix-wasm-test packages.rainix-wasm-browser-test @@ -159,8 +159,8 @@ packages.build-js-bindings packages.test-js-bindings rain.defaultPackage.${system} - packages.ob-ui-components-prelude - packages.rainix-ob-cli-artifact + packages.raindex-ui-components-prelude + packages.raindex-cli-artifact ]; shellHook = rainix.devShells.${system}.default.shellHook; diff --git a/prep-all.sh b/prep-all.sh index 39747db048..a47a72a720 100755 --- a/prep-all.sh +++ b/prep-all.sh @@ -30,7 +30,7 @@ echo "Preparing base setup..." ./prep-base.sh echo "Setting up UI components..." -nix develop -i ${keep[@]} -c ob-ui-components-prelude +nix develop -i ${keep[@]} -c raindex-ui-components-prelude echo "Building packages..." nix develop -i ${keep[@]} -c bash -c '(npm run build -w @rainlanguage/raindex)' From 43afd9af4eba30ef8599bbbecbffc418ddd009a0 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Wed, 1 Apr 2026 14:12:15 +0400 Subject: [PATCH 29/69] wip on bumping dep --- foundry.lock | 2 +- lib/rain.interpreter | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/foundry.lock b/foundry.lock index f0d37918b3..9fe4430e83 100644 --- a/foundry.lock +++ b/foundry.lock @@ -3,7 +3,7 @@ "rev": "43a6ed3a98f0141e1963b4b9136e8c80e2889bd1" }, "lib/rain.interpreter": { - "rev": "2780cdd642398ce4eee4e699363ce100cdc4ef60" + "rev": "1ea41cd004a926e3a964ba5498654f3cd538f139" }, "lib/rain.raindex.interface": { "rev": "ad4427dcb07e6df95def94999799470db89321b3" diff --git a/lib/rain.interpreter b/lib/rain.interpreter index 96608b8023..1ea41cd004 160000 --- a/lib/rain.interpreter +++ b/lib/rain.interpreter @@ -1 +1 @@ -Subproject commit 96608b8023a564eed2e96c69cfb3255cb2bbfdb7 +Subproject commit 1ea41cd004a926e3a964ba5498654f3cd538f139 From 1566699b612573fe9bc66aba7a1d9c6efcf4fa8b Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Wed, 1 Apr 2026 14:59:51 +0400 Subject: [PATCH 30/69] Rename ob test fixture keys to raindex Co-Authored-By: Claude Opus 4.6 (1M context) --- .../local_db/pipeline/runner/environment.rs | 4 +-- .../src/local_db/pipeline/runner/remotes.rs | 28 +++++++++---------- .../src/local_db/pipeline/runner/utils.rs | 14 +++++----- .../local_db/pipeline/runner/config.rs | 14 +++++----- .../local_db/pipeline/runner/environment.rs | 2 +- .../local_db/pipeline/runner/mod.rs | 18 ++++++------ .../common/src/types/orders_list_flattened.rs | 14 +++++----- 7 files changed, 47 insertions(+), 47 deletions(-) diff --git a/crates/common/src/local_db/pipeline/runner/environment.rs b/crates/common/src/local_db/pipeline/runner/environment.rs index 033d0b6f3d..9908ecc419 100644 --- a/crates/common/src/local_db/pipeline/runner/environment.rs +++ b/crates/common/src/local_db/pipeline/runner/environment.rs @@ -690,7 +690,7 @@ local-db-sync: bootstrap-block-threshold: 10000 sync-interval-ms: 5000 raindexes: - ob-a: + raindex-a: address: 0x00000000000000000000000000000000000000a1 network: network-a subgraph: network-a @@ -749,7 +749,7 @@ networks: let mut parsed = parse_runner_settings(&sample_settings_yaml()).expect("sample settings"); let manifest_url = Url::parse(&server.base_url()).unwrap(); - update_remote_url(&mut parsed.raindexes, "ob-a", &manifest_url); + update_remote_url(&mut parsed.raindexes, "raindex-a", &manifest_url); let fetcher = default_manifest_fetcher(); let manifests = block_on(fetcher(&parsed.raindexes)).expect("manifest map"); diff --git a/crates/common/src/local_db/pipeline/runner/remotes.rs b/crates/common/src/local_db/pipeline/runner/remotes.rs index d15400f219..3327ddbc80 100644 --- a/crates/common/src/local_db/pipeline/runner/remotes.rs +++ b/crates/common/src/local_db/pipeline/runner/remotes.rs @@ -138,19 +138,19 @@ local-db-sync: bootstrap-block-threshold: 5000 sync-interval-ms: 5000 raindexes: - ob-a: + raindex-a: address: 0x00000000000000000000000000000000000000a1 network: network-a subgraph: network-a local-db-remote: remote-a deployment-block: 111 - ob-b: + raindex-b: address: 0x00000000000000000000000000000000000000b2 network: network-b subgraph: network-b local-db-remote: remote-b deployment-block: 222 - ob-c: + raindex-c: address: 0x00000000000000000000000000000000000000c3 network: network-a subgraph: network-a @@ -195,8 +195,8 @@ raindexes: let targets = build_runner_targets(&parsed.raindexes, &parsed.syncs).unwrap(); let target = targets .into_iter() - .find(|t| t.raindex_key == "ob-a") - .expect("target ob-a"); + .find(|t| t.raindex_key == "raindex-a") + .expect("target raindex-a"); let manifest_entry = ManifestRaindex { address: target.inputs.raindex_id.raindex_address, @@ -304,9 +304,9 @@ networks: let mut parsed = parsed_settings(); let url_one = Url::parse(&server_one.base_url()).unwrap(); let url_two = Url::parse(&server_two.base_url()).unwrap(); - update_remote_url(&mut parsed.raindexes, "ob-a", &url_one); - update_remote_url(&mut parsed.raindexes, "ob-c", &url_one); - update_remote_url(&mut parsed.raindexes, "ob-b", &url_two); + update_remote_url(&mut parsed.raindexes, "raindex-a", &url_one); + update_remote_url(&mut parsed.raindexes, "raindex-c", &url_one); + update_remote_url(&mut parsed.raindexes, "raindex-b", &url_two); let manifests = rt .block_on(get_manifests(&parsed.raindexes)) @@ -352,9 +352,9 @@ networks: {} let mut parsed = parsed_settings(); let url_one = Url::parse(&server_one.base_url()).unwrap(); let url_two = Url::parse(&server_two.base_url()).unwrap(); - update_remote_url(&mut parsed.raindexes, "ob-a", &url_one); - update_remote_url(&mut parsed.raindexes, "ob-c", &url_one); - update_remote_url(&mut parsed.raindexes, "ob-b", &url_two); + update_remote_url(&mut parsed.raindexes, "raindex-a", &url_one); + update_remote_url(&mut parsed.raindexes, "raindex-c", &url_one); + update_remote_url(&mut parsed.raindexes, "raindex-b", &url_two); let err = rt.block_on(get_manifests(&parsed.raindexes)).unwrap_err(); match err { @@ -368,9 +368,9 @@ networks: {} let rt = build_runtime(); let mut parsed = parsed_settings(); let unreachable = Url::parse("nosuch://unreachable.example/manifest.yaml").unwrap(); - update_remote_url(&mut parsed.raindexes, "ob-a", &unreachable); - update_remote_url(&mut parsed.raindexes, "ob-b", &unreachable); - update_remote_url(&mut parsed.raindexes, "ob-c", &unreachable); + update_remote_url(&mut parsed.raindexes, "raindex-a", &unreachable); + update_remote_url(&mut parsed.raindexes, "raindex-b", &unreachable); + update_remote_url(&mut parsed.raindexes, "raindex-c", &unreachable); let err = rt.block_on(get_manifests(&parsed.raindexes)).unwrap_err(); match err { diff --git a/crates/common/src/local_db/pipeline/runner/utils.rs b/crates/common/src/local_db/pipeline/runner/utils.rs index 03318ecea6..4c72fd1d66 100644 --- a/crates/common/src/local_db/pipeline/runner/utils.rs +++ b/crates/common/src/local_db/pipeline/runner/utils.rs @@ -171,19 +171,19 @@ local-db-sync: bootstrap-block-threshold: 5000 sync-interval-ms: 5000 raindexes: - ob-a: + raindex-a: address: 0x00000000000000000000000000000000000000a1 network: network-a subgraph: network-a local-db-remote: remote-a deployment-block: 111 - ob-b: + raindex-b: address: 0x00000000000000000000000000000000000000b2 network: network-b subgraph: network-b local-db-remote: remote-b deployment-block: 222 - ob-c: + raindex-c: address: 0x00000000000000000000000000000000000000c3 network: network-a subgraph: network-a @@ -240,7 +240,7 @@ raindexes: let parsed = parse_runner_settings(&sample_settings_yaml()).expect("parse succeeds"); assert_eq!(parsed.raindexes.len(), 3); assert_eq!(parsed.syncs.len(), 2); - assert!(parsed.raindexes.contains_key("ob-a")); + assert!(parsed.raindexes.contains_key("raindex-a")); assert!(parsed.syncs.contains_key("network-a")); } @@ -331,8 +331,8 @@ raindexes: let target_a = targets .iter() - .find(|t| t.raindex_key == "ob-a") - .expect("target for ob-a exists"); + .find(|t| t.raindex_key == "raindex-a") + .expect("target for raindex-a exists"); assert_eq!(target_a.network_key, "network-a"); assert_eq!(target_a.inputs.raindex_id.chain_id, 1); assert_eq!( @@ -395,7 +395,7 @@ raindexes: input.raindex_id.raindex_address == address!("00000000000000000000000000000000000000b2") }) - .expect("input for ob-b exists"); + .expect("input for raindex-b exists"); assert_eq!(input_b.raindex_id.chain_id, 2); assert_eq!(input_b.cfg.fetch.max_concurrent_requests(), 2); } diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/config.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/config.rs index 9000b7b10b..cfaac9ac36 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/config.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/config.rs @@ -110,19 +110,19 @@ local-db-sync: bootstrap-block-threshold: 5000 sync-interval-ms: 5000 raindexes: - ob-a: + raindex-a: address: 0x00000000000000000000000000000000000000a1 network: network-a subgraph: network-a local-db-remote: remote-a deployment-block: 111 - ob-b: + raindex-b: address: 0x00000000000000000000000000000000000000b2 network: network-b subgraph: network-b local-db-remote: remote-b deployment-block: 222 - ob-c: + raindex-c: address: 0x00000000000000000000000000000000000000c3 network: network-a subgraph: network-a @@ -142,9 +142,9 @@ raindexes: assert_eq!(config.network_key, "network-a"); assert_eq!(config.chain_id, 1); assert_eq!(config.settings.raindexes.len(), 2); - assert!(config.settings.raindexes.contains_key("ob-a")); - assert!(config.settings.raindexes.contains_key("ob-c")); - assert!(!config.settings.raindexes.contains_key("ob-b")); + assert!(config.settings.raindexes.contains_key("raindex-a")); + assert!(config.settings.raindexes.contains_key("raindex-c")); + assert!(!config.settings.raindexes.contains_key("raindex-b")); } #[test] @@ -186,6 +186,6 @@ raindexes: let targets = config.build_targets().expect("targets ok"); assert_eq!(targets.len(), 1); - assert_eq!(targets[0].raindex_key, "ob-b"); + assert_eq!(targets[0].raindex_key, "raindex-b"); } } diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/environment.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/environment.rs index 1d25961a9d..a76de8cf96 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/environment.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/environment.rs @@ -91,7 +91,7 @@ mod tests { fn sample_target(metadata_rpcs: Vec) -> RunnerTarget { let fetch = FetchConfig::new(1, 1, 1, 1, 0, 0).expect("fetch config"); RunnerTarget { - raindex_key: "test-ob".to_string(), + raindex_key: "test-raindex".to_string(), network_key: "test-network".to_string(), manifest_url: Url::parse("https://manifests.example/client.yaml").unwrap(), inputs: SyncInputs { diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs index bd7adc31b8..21b386417c 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs @@ -351,8 +351,8 @@ mod tests { const CHAIN_ID: u32 = 42161; const NETWORK_KEY: &str = "anvil"; - const RAINDEX_KEY_A: &str = "ob-a"; - const RAINDEX_KEY_B: &str = "ob-b"; + const RAINDEX_KEY_A: &str = "raindex-a"; + const RAINDEX_KEY_B: &str = "raindex-b"; const RAINDEX_A: Address = address!("00000000000000000000000000000000000000a1"); const RAINDEX_B: Address = address!("00000000000000000000000000000000000000b2"); @@ -952,11 +952,11 @@ mod tests { const END_HASH_B: &str = "0x000000000000000000000000000000000000000000000000000000000000beef"; fn dump_url_a() -> Url { - Url::parse("https://dumps.example/ob-a.sql").unwrap() + Url::parse("https://dumps.example/raindex-a.sql").unwrap() } fn dump_url_b() -> Url { - Url::parse("https://dumps.example/ob-b.sql").unwrap() + Url::parse("https://dumps.example/raindex-b.sql").unwrap() } fn manifest_for_a() -> ManifestMap { @@ -1026,13 +1026,13 @@ local-db-sync: bootstrap-block-threshold: 10000 sync-interval-ms: 5000 raindexes: - ob-a: + raindex-a: address: 0x00000000000000000000000000000000000000a1 network: anvil subgraph: anvil local-db-remote: remote-a deployment-block: 123 - ob-b: + raindex-b: address: 0x00000000000000000000000000000000000000b2 network: anvil subgraph: anvil @@ -1067,7 +1067,7 @@ local-db-sync: bootstrap-block-threshold: 10000 sync-interval-ms: 5000 raindexes: - ob-a: + raindex-a: address: 0x00000000000000000000000000000000000000a1 network: anvil subgraph: anvil @@ -1428,7 +1428,7 @@ raindexes: let record_a = records .iter() .find(|r| r.raindex_key == RAINDEX_KEY_A) - .expect("record for ob-a"); + .expect("record for raindex-a"); assert!(record_a .dump_sql .as_ref() @@ -1438,7 +1438,7 @@ raindexes: let record_b = records .iter() .find(|r| r.raindex_key == RAINDEX_KEY_B) - .expect("record for ob-b"); + .expect("record for raindex-b"); assert!(record_b.dump_sql.is_none()); assert_eq!(record_b.latest_block, 0); } diff --git a/crates/common/src/types/orders_list_flattened.rs b/crates/common/src/types/orders_list_flattened.rs index e223aa0818..4b96749810 100644 --- a/crates/common/src/types/orders_list_flattened.rs +++ b/crates/common/src/types/orders_list_flattened.rs @@ -145,7 +145,7 @@ mod tests { decimals: Some(SgBigInt("18".into())), }, raindex: SgRaindex { - id: SgBytes("ob-id".into()), + id: SgBytes("raindex-id".into()), }, orders_as_output: vec![], orders_as_input: vec![], @@ -164,14 +164,14 @@ mod tests { decimals: Some(SgBigInt("18".into())), }, raindex: SgRaindex { - id: SgBytes("ob-id".into()), + id: SgBytes("raindex-id".into()), }, orders_as_output: vec![], orders_as_input: vec![], balance_changes: vec![], }], raindex: SgRaindex { - id: SgBytes("ob-id".into()), + id: SgBytes("raindex-id".into()), }, active: true, timestamp_added: SgBigInt("1678886400".into()), @@ -242,7 +242,7 @@ mod tests { owner: SgBytes("vault-owner-2".into()), balance: SgBytes("1000".into()), raindex: SgRaindex { - id: SgBytes("ob-id".into()), + id: SgBytes("raindex-id".into()), }, orders_as_output: vec![], orders_as_input: vec![], @@ -261,7 +261,7 @@ mod tests { owner: SgBytes("vault-owner-2".into()), balance: SgBytes("1000".into()), raindex: SgRaindex { - id: SgBytes("ob-id".into()), + id: SgBytes("raindex-id".into()), }, orders_as_output: vec![], orders_as_input: vec![], @@ -353,7 +353,7 @@ mod tests { owner: SgBytes("vault-owner".into()), balance: SgBytes("1000".into()), raindex: SgRaindex { - id: SgBytes("ob-id".into()), + id: SgBytes("raindex-id".into()), }, orders_as_output: vec![], orders_as_input: vec![], @@ -372,7 +372,7 @@ mod tests { owner: SgBytes("vault-owner".into()), balance: SgBytes("1000".into()), raindex: SgRaindex { - id: SgBytes("ob-id".into()), + id: SgBytes("raindex-id".into()), }, vault_id: SgBytes("222".into()), token: SgErc20 { From 9489767c5286b002c95db78595334cc2c8e35ea8 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Wed, 1 Apr 2026 15:05:51 +0400 Subject: [PATCH 31/69] Rename src/concrete/ob/ and test/concrete/ob/ to raindex/ Co-Authored-By: Claude Opus 4.6 (1M context) --- script/BuildPointers.sol | 2 +- script/Deploy.sol | 2 +- src/concrete/{ob => raindex}/RaindexV6.sol | 0 test/abstract/RaindexV6ArbOrderTaker.context.t.sol | 2 +- test/concrete/{ob => raindex}/RaindexV6.addOrder.entask.t.sol | 0 test/concrete/{ob => raindex}/RaindexV6.addOrder.mock.t.sol | 0 test/concrete/{ob => raindex}/RaindexV6.addOrder.nonce.t.sol | 0 test/concrete/{ob => raindex}/RaindexV6.addOrder.owner.t.sol | 0 test/concrete/{ob => raindex}/RaindexV6.addOrder.t.sol | 2 +- test/concrete/{ob => raindex}/RaindexV6.clear.badStack.t.sol | 2 +- test/concrete/{ob => raindex}/RaindexV6.clear.context.t.sol | 0 .../{ob => raindex}/RaindexV6.clear.handleIO.revert.t.sol | 0 test/concrete/{ob => raindex}/RaindexV6.clear.mock.t.sol | 2 +- test/concrete/{ob => raindex}/RaindexV6.clear.sameOwner.t.sol | 2 +- test/concrete/{ob => raindex}/RaindexV6.clear.sameToken.t.sol | 2 +- test/concrete/{ob => raindex}/RaindexV6.clear.zeroAmount.t.sol | 2 +- test/concrete/{ob => raindex}/RaindexV6.deposit.entask.t.sol | 0 test/concrete/{ob => raindex}/RaindexV6.deposit.t.sol | 0 test/concrete/{ob => raindex}/RaindexV6.entask.t.sol | 0 test/concrete/{ob => raindex}/RaindexV6.quote.sameToken.t.sol | 2 +- test/concrete/{ob => raindex}/RaindexV6.quote.t.sol | 2 +- .../concrete/{ob => raindex}/RaindexV6.removeOrder.entask.t.sol | 0 test/concrete/{ob => raindex}/RaindexV6.removeOrder.mock.t.sol | 2 +- test/concrete/{ob => raindex}/RaindexV6.removeOrder.owner.t.sol | 2 +- .../concrete/{ob => raindex}/RaindexV6.takeOrder.badStack.t.sol | 2 +- .../{ob => raindex}/RaindexV6.takeOrder.exceedsMaxRatio.t.sol | 0 .../{ob => raindex}/RaindexV6.takeOrder.handleIO.revert.t.sol | 0 .../{ob => raindex}/RaindexV6.takeOrder.maximumInput.t.sol | 0 .../{ob => raindex}/RaindexV6.takeOrder.maximumOutput.t.sol | 0 .../{ob => raindex}/RaindexV6.takeOrder.minimumIO.t.sol | 2 +- test/concrete/{ob => raindex}/RaindexV6.takeOrder.noop.t.sol | 0 .../{ob => raindex}/RaindexV6.takeOrder.precision.t.sol | 0 .../{ob => raindex}/RaindexV6.takeOrder.sameToken.t.sol | 2 +- .../{ob => raindex}/RaindexV6.takeOrder.tokenMismatch.t.sol | 2 +- test/concrete/{ob => raindex}/RaindexV6.vaultBalance.t.sol | 0 test/concrete/{ob => raindex}/RaindexV6.withdraw.entask.t.sol | 0 test/concrete/{ob => raindex}/RaindexV6.withdraw.t.sol | 0 test/lib/deploy/LibRaindexDeploy.t.sol | 2 +- test/util/abstract/RaindexV6SelfTest.sol | 2 +- test/util/lib/LibTestAddOrder.sol | 2 +- 40 files changed, 20 insertions(+), 20 deletions(-) rename src/concrete/{ob => raindex}/RaindexV6.sol (100%) rename test/concrete/{ob => raindex}/RaindexV6.addOrder.entask.t.sol (100%) rename test/concrete/{ob => raindex}/RaindexV6.addOrder.mock.t.sol (100%) rename test/concrete/{ob => raindex}/RaindexV6.addOrder.nonce.t.sol (100%) rename test/concrete/{ob => raindex}/RaindexV6.addOrder.owner.t.sol (100%) rename test/concrete/{ob => raindex}/RaindexV6.addOrder.t.sol (99%) rename test/concrete/{ob => raindex}/RaindexV6.clear.badStack.t.sol (99%) rename test/concrete/{ob => raindex}/RaindexV6.clear.context.t.sol (100%) rename test/concrete/{ob => raindex}/RaindexV6.clear.handleIO.revert.t.sol (100%) rename test/concrete/{ob => raindex}/RaindexV6.clear.mock.t.sol (99%) rename test/concrete/{ob => raindex}/RaindexV6.clear.sameOwner.t.sol (96%) rename test/concrete/{ob => raindex}/RaindexV6.clear.sameToken.t.sol (96%) rename test/concrete/{ob => raindex}/RaindexV6.clear.zeroAmount.t.sol (96%) rename test/concrete/{ob => raindex}/RaindexV6.deposit.entask.t.sol (100%) rename test/concrete/{ob => raindex}/RaindexV6.deposit.t.sol (100%) rename test/concrete/{ob => raindex}/RaindexV6.entask.t.sol (100%) rename test/concrete/{ob => raindex}/RaindexV6.quote.sameToken.t.sol (95%) rename test/concrete/{ob => raindex}/RaindexV6.quote.t.sol (99%) rename test/concrete/{ob => raindex}/RaindexV6.removeOrder.entask.t.sol (100%) rename test/concrete/{ob => raindex}/RaindexV6.removeOrder.mock.t.sol (99%) rename test/concrete/{ob => raindex}/RaindexV6.removeOrder.owner.t.sol (98%) rename test/concrete/{ob => raindex}/RaindexV6.takeOrder.badStack.t.sol (98%) rename test/concrete/{ob => raindex}/RaindexV6.takeOrder.exceedsMaxRatio.t.sol (100%) rename test/concrete/{ob => raindex}/RaindexV6.takeOrder.handleIO.revert.t.sol (100%) rename test/concrete/{ob => raindex}/RaindexV6.takeOrder.maximumInput.t.sol (100%) rename test/concrete/{ob => raindex}/RaindexV6.takeOrder.maximumOutput.t.sol (100%) rename test/concrete/{ob => raindex}/RaindexV6.takeOrder.minimumIO.t.sol (96%) rename test/concrete/{ob => raindex}/RaindexV6.takeOrder.noop.t.sol (100%) rename test/concrete/{ob => raindex}/RaindexV6.takeOrder.precision.t.sol (100%) rename test/concrete/{ob => raindex}/RaindexV6.takeOrder.sameToken.t.sol (96%) rename test/concrete/{ob => raindex}/RaindexV6.takeOrder.tokenMismatch.t.sol (98%) rename test/concrete/{ob => raindex}/RaindexV6.vaultBalance.t.sol (100%) rename test/concrete/{ob => raindex}/RaindexV6.withdraw.entask.t.sol (100%) rename test/concrete/{ob => raindex}/RaindexV6.withdraw.t.sol (100%) diff --git a/script/BuildPointers.sol b/script/BuildPointers.sol index b6ca61b522..ca4d77caae 100644 --- a/script/BuildPointers.sol +++ b/script/BuildPointers.sol @@ -5,7 +5,7 @@ pragma solidity =0.8.25; import {Script} from "forge-std/Script.sol"; import {LibCodeGen} from "rain.sol.codegen/lib/LibCodeGen.sol"; import {LibFs} from "rain.sol.codegen/lib/LibFs.sol"; -import {RaindexV6} from "../src/concrete/ob/RaindexV6.sol"; +import {RaindexV6} from "../src/concrete/raindex/RaindexV6.sol"; import {RaindexV6SubParser} from "../src/concrete/parser/RaindexV6SubParser.sol"; import {LibRaindexSubParser, EXTERN_PARSE_META_BUILD_DEPTH} from "../src/lib/LibRaindexSubParser.sol"; import {LibGenParseMeta} from "rain.interpreter.interface/lib/codegen/LibGenParseMeta.sol"; diff --git a/script/Deploy.sol b/script/Deploy.sol index 7de3fc4b5d..1f6202bce2 100644 --- a/script/Deploy.sol +++ b/script/Deploy.sol @@ -58,7 +58,7 @@ contract Deploy is Script { LibRainDeploy.supportedNetworks(), deployerPrivateKey, RAINDEX_CREATION_CODE, - "src/concrete/ob/RaindexV6.sol:RaindexV6", + "src/concrete/raindex/RaindexV6.sol:RaindexV6", LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, LibRaindexDeploy.RAINDEX_DEPLOYED_CODEHASH, deps, diff --git a/src/concrete/ob/RaindexV6.sol b/src/concrete/raindex/RaindexV6.sol similarity index 100% rename from src/concrete/ob/RaindexV6.sol rename to src/concrete/raindex/RaindexV6.sol diff --git a/test/abstract/RaindexV6ArbOrderTaker.context.t.sol b/test/abstract/RaindexV6ArbOrderTaker.context.t.sol index 5d73f91d79..6532ce2f72 100644 --- a/test/abstract/RaindexV6ArbOrderTaker.context.t.sol +++ b/test/abstract/RaindexV6ArbOrderTaker.context.t.sol @@ -15,7 +15,7 @@ import { } from "rain.raindex.interface/interface/IRaindexV6.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {StateNamespace, LibNamespace} from "../../src/concrete/ob/RaindexV6.sol"; +import {StateNamespace, LibNamespace} from "../../src/concrete/raindex/RaindexV6.sol"; import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; contract RaindexV6ArbOrderTakerContextTest is RaindexV6ExternalRealTest { diff --git a/test/concrete/ob/RaindexV6.addOrder.entask.t.sol b/test/concrete/raindex/RaindexV6.addOrder.entask.t.sol similarity index 100% rename from test/concrete/ob/RaindexV6.addOrder.entask.t.sol rename to test/concrete/raindex/RaindexV6.addOrder.entask.t.sol diff --git a/test/concrete/ob/RaindexV6.addOrder.mock.t.sol b/test/concrete/raindex/RaindexV6.addOrder.mock.t.sol similarity index 100% rename from test/concrete/ob/RaindexV6.addOrder.mock.t.sol rename to test/concrete/raindex/RaindexV6.addOrder.mock.t.sol diff --git a/test/concrete/ob/RaindexV6.addOrder.nonce.t.sol b/test/concrete/raindex/RaindexV6.addOrder.nonce.t.sol similarity index 100% rename from test/concrete/ob/RaindexV6.addOrder.nonce.t.sol rename to test/concrete/raindex/RaindexV6.addOrder.nonce.t.sol diff --git a/test/concrete/ob/RaindexV6.addOrder.owner.t.sol b/test/concrete/raindex/RaindexV6.addOrder.owner.t.sol similarity index 100% rename from test/concrete/ob/RaindexV6.addOrder.owner.t.sol rename to test/concrete/raindex/RaindexV6.addOrder.owner.t.sol diff --git a/test/concrete/ob/RaindexV6.addOrder.t.sol b/test/concrete/raindex/RaindexV6.addOrder.t.sol similarity index 99% rename from test/concrete/ob/RaindexV6.addOrder.t.sol rename to test/concrete/raindex/RaindexV6.addOrder.t.sol index b57166512c..05f32c5b01 100644 --- a/test/concrete/ob/RaindexV6.addOrder.t.sol +++ b/test/concrete/raindex/RaindexV6.addOrder.t.sol @@ -6,7 +6,7 @@ import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRea import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; import {OrderConfigV4, EvaluableV4, TaskV2} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {IParserV2} from "rain.interpreter.interface/interface/IParserV2.sol"; -import {UnsupportedCalculateOutputs} from "../../../src/concrete/ob/RaindexV6.sol"; +import {UnsupportedCalculateOutputs} from "../../../src/concrete/raindex/RaindexV6.sol"; /// @title RaindexV6AddOrderTest /// @notice A test harness for testing the RaindexV6 addOrder function. diff --git a/test/concrete/ob/RaindexV6.clear.badStack.t.sol b/test/concrete/raindex/RaindexV6.clear.badStack.t.sol similarity index 99% rename from test/concrete/ob/RaindexV6.clear.badStack.t.sol rename to test/concrete/raindex/RaindexV6.clear.badStack.t.sol index 445be19ca6..02fe1f2156 100644 --- a/test/concrete/ob/RaindexV6.clear.badStack.t.sol +++ b/test/concrete/raindex/RaindexV6.clear.badStack.t.sol @@ -12,7 +12,7 @@ import { SignedContextV1, TaskV2 } from "rain.raindex.interface/interface/IRaindexV6.sol"; -import {UnsupportedCalculateOutputs} from "../../../src/concrete/ob/RaindexV6.sol"; +import {UnsupportedCalculateOutputs} from "../../../src/concrete/raindex/RaindexV6.sol"; import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; contract RaindexV6ClearOrderBadStackTest is RaindexV6ExternalRealTest { diff --git a/test/concrete/ob/RaindexV6.clear.context.t.sol b/test/concrete/raindex/RaindexV6.clear.context.t.sol similarity index 100% rename from test/concrete/ob/RaindexV6.clear.context.t.sol rename to test/concrete/raindex/RaindexV6.clear.context.t.sol diff --git a/test/concrete/ob/RaindexV6.clear.handleIO.revert.t.sol b/test/concrete/raindex/RaindexV6.clear.handleIO.revert.t.sol similarity index 100% rename from test/concrete/ob/RaindexV6.clear.handleIO.revert.t.sol rename to test/concrete/raindex/RaindexV6.clear.handleIO.revert.t.sol diff --git a/test/concrete/ob/RaindexV6.clear.mock.t.sol b/test/concrete/raindex/RaindexV6.clear.mock.t.sol similarity index 99% rename from test/concrete/ob/RaindexV6.clear.mock.t.sol rename to test/concrete/raindex/RaindexV6.clear.mock.t.sol index b5ad3e952e..cc62e374ea 100644 --- a/test/concrete/ob/RaindexV6.clear.mock.t.sol +++ b/test/concrete/raindex/RaindexV6.clear.mock.t.sol @@ -18,7 +18,7 @@ import { Float } from "rain.raindex.interface/interface/IRaindexV6.sol"; import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; -import {NotOrderOwner, StackItem, NegativeBounty, ClearZeroAmount} from "../../../src/concrete/ob/RaindexV6.sol"; +import {NotOrderOwner, StackItem, NegativeBounty, ClearZeroAmount} from "../../../src/concrete/raindex/RaindexV6.sol"; import {LibNamespace} from "rain.interpreter.interface/lib/ns/LibNamespace.sol"; import {StateNamespace, EvalV4, SourceIndexV2} from "rain.interpreter.interface/interface/IInterpreterV4.sol"; import { diff --git a/test/concrete/ob/RaindexV6.clear.sameOwner.t.sol b/test/concrete/raindex/RaindexV6.clear.sameOwner.t.sol similarity index 96% rename from test/concrete/ob/RaindexV6.clear.sameOwner.t.sol rename to test/concrete/raindex/RaindexV6.clear.sameOwner.t.sol index e7b6eb6e76..90d14be257 100644 --- a/test/concrete/ob/RaindexV6.clear.sameOwner.t.sol +++ b/test/concrete/raindex/RaindexV6.clear.sameOwner.t.sol @@ -7,7 +7,7 @@ import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; import {LibTestTakeOrder} from "test/util/lib/LibTestTakeOrder.sol"; import {OrderConfigV4, OrderV4, ClearConfigV2, TaskV2} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {SignedContextV1} from "rain.interpreter.interface/interface/deprecated/v1/IInterpreterCallerV2.sol"; -import {SameOwner} from "../../../src/concrete/ob/RaindexV6.sol"; +import {SameOwner} from "../../../src/concrete/raindex/RaindexV6.sol"; /// Clearing two orders with the same owner must revert with SameOwner. contract RaindexV6ClearSameOwnerTest is RaindexV6ExternalRealTest { diff --git a/test/concrete/ob/RaindexV6.clear.sameToken.t.sol b/test/concrete/raindex/RaindexV6.clear.sameToken.t.sol similarity index 96% rename from test/concrete/ob/RaindexV6.clear.sameToken.t.sol rename to test/concrete/raindex/RaindexV6.clear.sameToken.t.sol index 3b1cb84cc7..4521230c51 100644 --- a/test/concrete/ob/RaindexV6.clear.sameToken.t.sol +++ b/test/concrete/raindex/RaindexV6.clear.sameToken.t.sol @@ -12,7 +12,7 @@ import { TaskV2 } from "rain.raindex.interface/interface/IRaindexV6.sol"; import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; -import {TokenSelfTrade} from "../../../src/concrete/ob/RaindexV6.sol"; +import {TokenSelfTrade} from "../../../src/concrete/raindex/RaindexV6.sol"; contract RaindexV6ClearSameTokenTest is RaindexV6ExternalRealTest { /// forge-config: default.fuzz.runs = 10 diff --git a/test/concrete/ob/RaindexV6.clear.zeroAmount.t.sol b/test/concrete/raindex/RaindexV6.clear.zeroAmount.t.sol similarity index 96% rename from test/concrete/ob/RaindexV6.clear.zeroAmount.t.sol rename to test/concrete/raindex/RaindexV6.clear.zeroAmount.t.sol index eec1aed4b8..629c484a51 100644 --- a/test/concrete/ob/RaindexV6.clear.zeroAmount.t.sol +++ b/test/concrete/raindex/RaindexV6.clear.zeroAmount.t.sol @@ -11,7 +11,7 @@ import { ClearConfigV2 } from "rain.raindex.interface/interface/IRaindexV6.sol"; import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; -import {ClearZeroAmount} from "../../../src/concrete/ob/RaindexV6.sol"; +import {ClearZeroAmount} from "../../../src/concrete/raindex/RaindexV6.sol"; contract RaindexV6ClearZeroAmountTest is RaindexV6ExternalRealTest { /// forge-config: default.fuzz.runs = 10 diff --git a/test/concrete/ob/RaindexV6.deposit.entask.t.sol b/test/concrete/raindex/RaindexV6.deposit.entask.t.sol similarity index 100% rename from test/concrete/ob/RaindexV6.deposit.entask.t.sol rename to test/concrete/raindex/RaindexV6.deposit.entask.t.sol diff --git a/test/concrete/ob/RaindexV6.deposit.t.sol b/test/concrete/raindex/RaindexV6.deposit.t.sol similarity index 100% rename from test/concrete/ob/RaindexV6.deposit.t.sol rename to test/concrete/raindex/RaindexV6.deposit.t.sol diff --git a/test/concrete/ob/RaindexV6.entask.t.sol b/test/concrete/raindex/RaindexV6.entask.t.sol similarity index 100% rename from test/concrete/ob/RaindexV6.entask.t.sol rename to test/concrete/raindex/RaindexV6.entask.t.sol diff --git a/test/concrete/ob/RaindexV6.quote.sameToken.t.sol b/test/concrete/raindex/RaindexV6.quote.sameToken.t.sol similarity index 95% rename from test/concrete/ob/RaindexV6.quote.sameToken.t.sol rename to test/concrete/raindex/RaindexV6.quote.sameToken.t.sol index ad8fc45aa1..e0a1a0b975 100644 --- a/test/concrete/ob/RaindexV6.quote.sameToken.t.sol +++ b/test/concrete/raindex/RaindexV6.quote.sameToken.t.sol @@ -4,7 +4,7 @@ pragma solidity =0.8.25; import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRealTest.sol"; import {QuoteV2, OrderConfigV4, TaskV2} from "rain.raindex.interface/interface/IRaindexV6.sol"; -import {TokenSelfTrade} from "../../../src/concrete/ob/RaindexV6.sol"; +import {TokenSelfTrade} from "../../../src/concrete/raindex/RaindexV6.sol"; import {Float} from "rain.math.float/lib/LibDecimalFloat.sol"; /// @title RaindexV6QuoteSameTokenTest diff --git a/test/concrete/ob/RaindexV6.quote.t.sol b/test/concrete/raindex/RaindexV6.quote.t.sol similarity index 99% rename from test/concrete/ob/RaindexV6.quote.t.sol rename to test/concrete/raindex/RaindexV6.quote.t.sol index d7793fc54e..4de0841a30 100644 --- a/test/concrete/ob/RaindexV6.quote.t.sol +++ b/test/concrete/raindex/RaindexV6.quote.t.sol @@ -15,7 +15,7 @@ import { import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {TokenSelfTrade} from "../../../src/concrete/ob/RaindexV6.sol"; +import {TokenSelfTrade} from "../../../src/concrete/raindex/RaindexV6.sol"; import {Float, LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol"; diff --git a/test/concrete/ob/RaindexV6.removeOrder.entask.t.sol b/test/concrete/raindex/RaindexV6.removeOrder.entask.t.sol similarity index 100% rename from test/concrete/ob/RaindexV6.removeOrder.entask.t.sol rename to test/concrete/raindex/RaindexV6.removeOrder.entask.t.sol diff --git a/test/concrete/ob/RaindexV6.removeOrder.mock.t.sol b/test/concrete/raindex/RaindexV6.removeOrder.mock.t.sol similarity index 99% rename from test/concrete/ob/RaindexV6.removeOrder.mock.t.sol rename to test/concrete/raindex/RaindexV6.removeOrder.mock.t.sol index 18256a83d4..62524a3a2e 100644 --- a/test/concrete/ob/RaindexV6.removeOrder.mock.t.sol +++ b/test/concrete/raindex/RaindexV6.removeOrder.mock.t.sol @@ -5,7 +5,7 @@ pragma solidity =0.8.25; import {RaindexV6ExternalMockTest} from "test/util/abstract/RaindexV6ExternalMockTest.sol"; import {OrderConfigV4, OrderV4, EvaluableV4, TaskV2} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; -import {NotOrderOwner} from "../../../src/concrete/ob/RaindexV6.sol"; +import {NotOrderOwner} from "../../../src/concrete/raindex/RaindexV6.sol"; /// @title RaindexV6RemoveOrderMockTest /// @notice A contract to test the Raindex removeOrder function. diff --git a/test/concrete/ob/RaindexV6.removeOrder.owner.t.sol b/test/concrete/raindex/RaindexV6.removeOrder.owner.t.sol similarity index 98% rename from test/concrete/ob/RaindexV6.removeOrder.owner.t.sol rename to test/concrete/raindex/RaindexV6.removeOrder.owner.t.sol index 82ded43520..a45243d060 100644 --- a/test/concrete/ob/RaindexV6.removeOrder.owner.t.sol +++ b/test/concrete/raindex/RaindexV6.removeOrder.owner.t.sol @@ -6,7 +6,7 @@ import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRea import {OrderConfigV4, OrderV4, EvaluableV4, TaskV2} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; import {LibOrder} from "../../../src/lib/LibOrder.sol"; -import {NotOrderOwner} from "../../../src/concrete/ob/RaindexV6.sol"; +import {NotOrderOwner} from "../../../src/concrete/raindex/RaindexV6.sol"; contract RaindexV6RemoveOrderOwnerTest is RaindexV6ExternalRealTest { using LibOrder for OrderV4; diff --git a/test/concrete/ob/RaindexV6.takeOrder.badStack.t.sol b/test/concrete/raindex/RaindexV6.takeOrder.badStack.t.sol similarity index 98% rename from test/concrete/ob/RaindexV6.takeOrder.badStack.t.sol rename to test/concrete/raindex/RaindexV6.takeOrder.badStack.t.sol index 6b6657e828..fe8a067366 100644 --- a/test/concrete/ob/RaindexV6.takeOrder.badStack.t.sol +++ b/test/concrete/raindex/RaindexV6.takeOrder.badStack.t.sol @@ -6,7 +6,7 @@ import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRea import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; import {LibTestTakeOrder} from "test/util/lib/LibTestTakeOrder.sol"; import {OrderConfigV4, OrderV4, TaskV2, TakeOrdersConfigV5} from "rain.raindex.interface/interface/IRaindexV6.sol"; -import {UnsupportedCalculateOutputs} from "../../../src/concrete/ob/RaindexV6.sol"; +import {UnsupportedCalculateOutputs} from "../../../src/concrete/raindex/RaindexV6.sol"; contract RaindexV6TakeOrderBadStackTest is RaindexV6ExternalRealTest { function checkBadStack( diff --git a/test/concrete/ob/RaindexV6.takeOrder.exceedsMaxRatio.t.sol b/test/concrete/raindex/RaindexV6.takeOrder.exceedsMaxRatio.t.sol similarity index 100% rename from test/concrete/ob/RaindexV6.takeOrder.exceedsMaxRatio.t.sol rename to test/concrete/raindex/RaindexV6.takeOrder.exceedsMaxRatio.t.sol diff --git a/test/concrete/ob/RaindexV6.takeOrder.handleIO.revert.t.sol b/test/concrete/raindex/RaindexV6.takeOrder.handleIO.revert.t.sol similarity index 100% rename from test/concrete/ob/RaindexV6.takeOrder.handleIO.revert.t.sol rename to test/concrete/raindex/RaindexV6.takeOrder.handleIO.revert.t.sol diff --git a/test/concrete/ob/RaindexV6.takeOrder.maximumInput.t.sol b/test/concrete/raindex/RaindexV6.takeOrder.maximumInput.t.sol similarity index 100% rename from test/concrete/ob/RaindexV6.takeOrder.maximumInput.t.sol rename to test/concrete/raindex/RaindexV6.takeOrder.maximumInput.t.sol diff --git a/test/concrete/ob/RaindexV6.takeOrder.maximumOutput.t.sol b/test/concrete/raindex/RaindexV6.takeOrder.maximumOutput.t.sol similarity index 100% rename from test/concrete/ob/RaindexV6.takeOrder.maximumOutput.t.sol rename to test/concrete/raindex/RaindexV6.takeOrder.maximumOutput.t.sol diff --git a/test/concrete/ob/RaindexV6.takeOrder.minimumIO.t.sol b/test/concrete/raindex/RaindexV6.takeOrder.minimumIO.t.sol similarity index 96% rename from test/concrete/ob/RaindexV6.takeOrder.minimumIO.t.sol rename to test/concrete/raindex/RaindexV6.takeOrder.minimumIO.t.sol index fc204da238..2ca8402783 100644 --- a/test/concrete/ob/RaindexV6.takeOrder.minimumIO.t.sol +++ b/test/concrete/raindex/RaindexV6.takeOrder.minimumIO.t.sol @@ -7,7 +7,7 @@ import {RaindexV6ExternalRealTest} from "test/util/abstract/RaindexV6ExternalRea import {LibTestTakeOrder} from "test/util/lib/LibTestTakeOrder.sol"; import {OrderV4, TakeOrdersConfigV5, TaskV2} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {Float, LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; -import {MinimumIO} from "../../../src/concrete/ob/RaindexV6.sol"; +import {MinimumIO} from "../../../src/concrete/raindex/RaindexV6.sol"; /// When the total taker IO is less than the configured minimumIO, /// takeOrders4 must revert with MinimumIO(minimumIO, actualIO). diff --git a/test/concrete/ob/RaindexV6.takeOrder.noop.t.sol b/test/concrete/raindex/RaindexV6.takeOrder.noop.t.sol similarity index 100% rename from test/concrete/ob/RaindexV6.takeOrder.noop.t.sol rename to test/concrete/raindex/RaindexV6.takeOrder.noop.t.sol diff --git a/test/concrete/ob/RaindexV6.takeOrder.precision.t.sol b/test/concrete/raindex/RaindexV6.takeOrder.precision.t.sol similarity index 100% rename from test/concrete/ob/RaindexV6.takeOrder.precision.t.sol rename to test/concrete/raindex/RaindexV6.takeOrder.precision.t.sol diff --git a/test/concrete/ob/RaindexV6.takeOrder.sameToken.t.sol b/test/concrete/raindex/RaindexV6.takeOrder.sameToken.t.sol similarity index 96% rename from test/concrete/ob/RaindexV6.takeOrder.sameToken.t.sol rename to test/concrete/raindex/RaindexV6.takeOrder.sameToken.t.sol index ced38fce53..59d666a9cd 100644 --- a/test/concrete/ob/RaindexV6.takeOrder.sameToken.t.sol +++ b/test/concrete/raindex/RaindexV6.takeOrder.sameToken.t.sol @@ -12,7 +12,7 @@ import { TakeOrdersConfigV5 } from "rain.raindex.interface/interface/IRaindexV6.sol"; import {LibTestAddOrder} from "test/util/lib/LibTestAddOrder.sol"; -import {TokenSelfTrade} from "../../../src/concrete/ob/RaindexV6.sol"; +import {TokenSelfTrade} from "../../../src/concrete/raindex/RaindexV6.sol"; import {Float, LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; contract RaindexV6TakeOrderSameTokenTest is RaindexV6ExternalRealTest { diff --git a/test/concrete/ob/RaindexV6.takeOrder.tokenMismatch.t.sol b/test/concrete/raindex/RaindexV6.takeOrder.tokenMismatch.t.sol similarity index 98% rename from test/concrete/ob/RaindexV6.takeOrder.tokenMismatch.t.sol rename to test/concrete/raindex/RaindexV6.takeOrder.tokenMismatch.t.sol index 2c533c86b2..9795eb73bf 100644 --- a/test/concrete/ob/RaindexV6.takeOrder.tokenMismatch.t.sol +++ b/test/concrete/raindex/RaindexV6.takeOrder.tokenMismatch.t.sol @@ -11,7 +11,7 @@ import { EvaluableV4, SignedContextV1 } from "rain.raindex.interface/interface/IRaindexV6.sol"; -import {TokenMismatch} from "../../../src/concrete/ob/RaindexV6.sol"; +import {TokenMismatch} from "../../../src/concrete/raindex/RaindexV6.sol"; import {Float, LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; /// @title RaindexV6TakeOrderTokenMismatchTest diff --git a/test/concrete/ob/RaindexV6.vaultBalance.t.sol b/test/concrete/raindex/RaindexV6.vaultBalance.t.sol similarity index 100% rename from test/concrete/ob/RaindexV6.vaultBalance.t.sol rename to test/concrete/raindex/RaindexV6.vaultBalance.t.sol diff --git a/test/concrete/ob/RaindexV6.withdraw.entask.t.sol b/test/concrete/raindex/RaindexV6.withdraw.entask.t.sol similarity index 100% rename from test/concrete/ob/RaindexV6.withdraw.entask.t.sol rename to test/concrete/raindex/RaindexV6.withdraw.entask.t.sol diff --git a/test/concrete/ob/RaindexV6.withdraw.t.sol b/test/concrete/raindex/RaindexV6.withdraw.t.sol similarity index 100% rename from test/concrete/ob/RaindexV6.withdraw.t.sol rename to test/concrete/raindex/RaindexV6.withdraw.t.sol diff --git a/test/lib/deploy/LibRaindexDeploy.t.sol b/test/lib/deploy/LibRaindexDeploy.t.sol index ec956f2ec8..955f64ca9d 100644 --- a/test/lib/deploy/LibRaindexDeploy.t.sol +++ b/test/lib/deploy/LibRaindexDeploy.t.sol @@ -6,7 +6,7 @@ import {Test} from "forge-std/Test.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; import {LibRaindexDeploy} from "../../../src/lib/deploy/LibRaindexDeploy.sol"; import {LibEtchRaindex} from "test/util/lib/LibEtchRaindex.sol"; -import {RaindexV6} from "../../../src/concrete/ob/RaindexV6.sol"; +import {RaindexV6} from "../../../src/concrete/raindex/RaindexV6.sol"; import {RaindexV6SubParser} from "../../../src/concrete/parser/RaindexV6SubParser.sol"; import { CREATION_CODE as RAINDEX_CREATION_CODE, diff --git a/test/util/abstract/RaindexV6SelfTest.sol b/test/util/abstract/RaindexV6SelfTest.sol index 21adc394dd..12d4f096b4 100644 --- a/test/util/abstract/RaindexV6SelfTest.sol +++ b/test/util/abstract/RaindexV6SelfTest.sol @@ -6,7 +6,7 @@ import {Test} from "forge-std/Test.sol"; import {REVERTING_MOCK_BYTECODE} from "test/util/lib/LibTestConstants.sol"; -import {RaindexV6} from "../../../src/concrete/ob/RaindexV6.sol"; +import {RaindexV6} from "../../../src/concrete/raindex/RaindexV6.sol"; /// @title RaindexV6SelfTest /// Abstract contract that is an `RaindexV6` and can be used to test itself. diff --git a/test/util/lib/LibTestAddOrder.sol b/test/util/lib/LibTestAddOrder.sol index 1ec02dcb2a..e4c0edc569 100644 --- a/test/util/lib/LibTestAddOrder.sol +++ b/test/util/lib/LibTestAddOrder.sol @@ -8,7 +8,7 @@ import {OrderConfigV4, OrderV4, IOV2} from "rain.raindex.interface/interface/IRa import {IInterpreterV4, SourceIndexV2} from "rain.interpreter.interface/interface/IInterpreterV4.sol"; import {IInterpreterStoreV3} from "rain.interpreter.interface/interface/IInterpreterStoreV3.sol"; import {EvaluableV4} from "rain.interpreter.interface/interface/IInterpreterCallerV4.sol"; -import {HANDLE_IO_ENTRYPOINT} from "../../../src/concrete/ob/RaindexV6.sol"; +import {HANDLE_IO_ENTRYPOINT} from "../../../src/concrete/raindex/RaindexV6.sol"; import {LibBytecode} from "rain.interpreter.interface/lib/bytecode/LibBytecode.sol"; library LibTestAddOrder { From 8ad99daed9b72c8c5cf6d8f8ad1627733287e4bb Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Wed, 1 Apr 2026 15:14:59 +0400 Subject: [PATCH 32/69] Rename OB to Raindex in test comments and assert messages Co-Authored-By: Claude Opus 4.6 (1M context) --- .../RaindexV6ArbOrderTaker.onTakeOrders2.t.sol | 2 +- .../RaindexV6FlashBorrower.mixedDecimals.t.sol | 2 +- ...RaindexV6FlashBorrower.realTokenTransfers.t.sol | 4 ++-- .../RaindexV6FlashBorrower.reentrancy.t.sol | 2 +- ...aindexV6ArbOrderTaker.nonStandardDecimals.t.sol | 10 +++++----- ...essorRaindexV6ArbOrderTaker.onTakeOrders2.t.sol | 8 ++++---- test/concrete/raindex/RaindexV6.clear.mock.t.sol | 8 ++++---- .../raindex/RaindexV6.takeOrder.precision.t.sol | 2 +- test/lib/LibRaindexArb.finalizeArbNativeGas.t.sol | 2 +- ...ibRaindexArb.finalizeArbOutputTokenProfit.t.sol | 8 ++++---- .../lib/LibRaindexArb.finalizeArbTaskContext.t.sol | 2 +- .../LibRaindexArb.finalizeArbTokenTransfers.t.sol | 8 ++++---- .../concrete/RealisticOrderTakerMockRaindex.sol | 2 +- test/util/concrete/ReentrantMockRaindex.sol | 4 ++-- test/util/lib/LibTestArb.sol | 14 +++++++------- 15 files changed, 39 insertions(+), 39 deletions(-) diff --git a/test/abstract/RaindexV6ArbOrderTaker.onTakeOrders2.t.sol b/test/abstract/RaindexV6ArbOrderTaker.onTakeOrders2.t.sol index 27372c3ac8..2c9a893057 100644 --- a/test/abstract/RaindexV6ArbOrderTaker.onTakeOrders2.t.sol +++ b/test/abstract/RaindexV6ArbOrderTaker.onTakeOrders2.t.sol @@ -82,7 +82,7 @@ contract RaindexV6ArbOrderTakerOnTakeOrders2Test is Test { }) ); - // OB received all inputToken from arb. + // Raindex received all inputToken from arb. assertEq(inputToken.balanceOf(address(raindex)), 100e18); // Exchange received all outputToken from arb. assertEq(outputToken.balanceOf(address(exchange)), 100e18); diff --git a/test/abstract/RaindexV6FlashBorrower.mixedDecimals.t.sol b/test/abstract/RaindexV6FlashBorrower.mixedDecimals.t.sol index 22f967ed36..2a7091d4a7 100644 --- a/test/abstract/RaindexV6FlashBorrower.mixedDecimals.t.sol +++ b/test/abstract/RaindexV6FlashBorrower.mixedDecimals.t.sol @@ -44,7 +44,7 @@ contract RaindexV6FlashBorrowerMixedDecimalsTest is Test { RealisticFlashLendingMockRaindex(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS); MockExchange exchange = new MockExchange(); - // OB needs outputToken for both the flash loan and takeOrders4. + // Raindex needs outputToken for both the flash loan and takeOrders4. outputToken.mint(address(raindex), 1000e6); // Exchange has 100e6 of inputToken for the swap. inputToken.mint(address(exchange), 100e6); diff --git a/test/abstract/RaindexV6FlashBorrower.realTokenTransfers.t.sol b/test/abstract/RaindexV6FlashBorrower.realTokenTransfers.t.sol index 066097bb35..c41522f7bd 100644 --- a/test/abstract/RaindexV6FlashBorrower.realTokenTransfers.t.sol +++ b/test/abstract/RaindexV6FlashBorrower.realTokenTransfers.t.sol @@ -87,9 +87,9 @@ contract RaindexV6FlashBorrowerRealTokenTransfersTest is Test { }) ); - // OB received all inputToken from arb. + // Raindex received all inputToken from arb. assertEq(inputToken.balanceOf(address(raindex)), 100e18); - // Exchange received outputToken from arb (100e18 of the 1000e18 OB had). + // Exchange received outputToken from arb (100e18 of the 1000e18 Raindex had). assertEq(outputToken.balanceOf(address(exchange)), 100e18); // Arb contract has no remaining tokens. assertEq(inputToken.balanceOf(address(arb)), 0); diff --git a/test/abstract/RaindexV6FlashBorrower.reentrancy.t.sol b/test/abstract/RaindexV6FlashBorrower.reentrancy.t.sol index 93c761359b..93710ddd17 100644 --- a/test/abstract/RaindexV6FlashBorrower.reentrancy.t.sol +++ b/test/abstract/RaindexV6FlashBorrower.reentrancy.t.sol @@ -39,7 +39,7 @@ contract RaindexV6FlashBorrowerReentrancyTest is Test { FlashLendingMockRaindex raindex = new FlashLendingMockRaindex(); vm.etch(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, address(raindex).code); - // Mint output tokens to the etched OB so it can flash-lend them. + // Mint output tokens to the etched Raindex so it can flash-lend them. outputToken.mint(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, 100e18); GenericPoolRaindexV6FlashBorrower arb = new GenericPoolRaindexV6FlashBorrower(); diff --git a/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.nonStandardDecimals.t.sol b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.nonStandardDecimals.t.sol index 320faa9ec7..9229d27de8 100644 --- a/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.nonStandardDecimals.t.sol +++ b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.nonStandardDecimals.t.sol @@ -41,13 +41,13 @@ contract RouteProcessorRaindexV6ArbOrderTakerNonStandardDecimalsTest is Test { MockToken inputToken = new MockToken("USDC", "USDC", 6); MockToken outputToken = new MockToken("USDT", "USDT", 6); - // OB will send 100 USDT (100e6) to the taker, then pull 100 USDC. + // Raindex will send 100 USDT (100e6) to the taker, then pull 100 USDC. RealisticOrderTakerMockRaindex raindex = new RealisticOrderTakerMockRaindex(100e6); MockRouteProcessor mockRp = new MockRouteProcessor(); vm.etch(LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS, address(mockRp).code); address routeProcessor = LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS; - // OB has outputToken to send to taker. + // Raindex has outputToken to send to taker. outputToken.mint(address(raindex), 100e6); // RouteProcessor has inputToken to give back after swap. inputToken.mint(routeProcessor, 100e6); @@ -99,9 +99,9 @@ contract RouteProcessorRaindexV6ArbOrderTakerNonStandardDecimalsTest is Test { // Arb contract has no remaining tokens. assertEq(inputToken.balanceOf(address(arb)), 0, "arb inputToken"); assertEq(outputToken.balanceOf(address(arb)), 0, "arb outputToken"); - // OB swapped outputToken for inputToken. - assertEq(inputToken.balanceOf(address(raindex)), 100e6, "OB inputToken"); - assertEq(outputToken.balanceOf(address(raindex)), 0, "OB outputToken"); + // Raindex swapped outputToken for inputToken. + assertEq(inputToken.balanceOf(address(raindex)), 100e6, "Raindex inputToken"); + assertEq(outputToken.balanceOf(address(raindex)), 0, "Raindex outputToken"); // RouteProcessor sent all its inputToken. assertEq(inputToken.balanceOf(routeProcessor), 0, "RP inputToken"); assertEq(outputToken.balanceOf(routeProcessor), 0, "RP outputToken"); diff --git a/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.onTakeOrders2.t.sol b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.onTakeOrders2.t.sol index 4a34a5c00c..1288885ef6 100644 --- a/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.onTakeOrders2.t.sol +++ b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.onTakeOrders2.t.sol @@ -44,7 +44,7 @@ contract RouteProcessorRaindexV6ArbOrderTakerOnTakeOrders2Test is Test { vm.etch(LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS, address(mockRp).code); address routeProcessor = LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS; - // OB has outputToken to send to taker. + // Raindex has outputToken to send to taker. outputToken.mint(address(raindex), 100e18); // RouteProcessor has inputToken to give back after swap. inputToken.mint(routeProcessor, 100e18); @@ -89,9 +89,9 @@ contract RouteProcessorRaindexV6ArbOrderTakerOnTakeOrders2Test is Test { // Arb contract has no remaining tokens. assertEq(inputToken.balanceOf(address(arb)), 0, "arb inputToken"); assertEq(outputToken.balanceOf(address(arb)), 0, "arb outputToken"); - // OB started with outputToken, swapped for inputToken via arb. - assertEq(inputToken.balanceOf(address(raindex)), 100e18, "OB inputToken"); - assertEq(outputToken.balanceOf(address(raindex)), 0, "OB outputToken"); + // Raindex started with outputToken, swapped for inputToken via arb. + assertEq(inputToken.balanceOf(address(raindex)), 100e18, "Raindex inputToken"); + assertEq(outputToken.balanceOf(address(raindex)), 0, "Raindex outputToken"); // RouteProcessor started with inputToken, received nothing (amountIn=0). assertEq(inputToken.balanceOf(routeProcessor), 0, "RP inputToken"); assertEq(outputToken.balanceOf(routeProcessor), 0, "RP outputToken"); diff --git a/test/concrete/raindex/RaindexV6.clear.mock.t.sol b/test/concrete/raindex/RaindexV6.clear.mock.t.sol index cc62e374ea..09390f8236 100644 --- a/test/concrete/raindex/RaindexV6.clear.mock.t.sol +++ b/test/concrete/raindex/RaindexV6.clear.mock.t.sol @@ -49,7 +49,7 @@ contract RaindexV6ClearTest is RaindexV6ExternalMockTest { using Math for uint256; using LibDecimalFloat for Float; - /// Make a deposit to the OB mocking the internal transferFrom call. + /// Make a deposit to the Raindex mocking the internal transferFrom call. function _depositInternal(address depositor, address token, bytes32 vaultId, Float amount) internal { if (vaultId != bytes32(0)) { uint256 amount18 = LibDecimalFloat.toFixedDecimalLossless(amount, 18); @@ -473,7 +473,7 @@ contract RaindexV6ClearTest is RaindexV6ExternalMockTest { Float bobAmount = LibDecimalFloat.packLossless(2, 0); // Mock the interpreter.eval that is used inside clear().calculateOrderIO() - // Produce the stack output for OB + // Produce the stack output for Raindex StackItem[] memory orderStackAlice = new StackItem[](2); orderStackAlice[0] = StackItem.wrap(Float.unwrap(LibDecimalFloat.packLossless(0.99e18, -18))); // orderIORatio orderStackAlice[1] = StackItem.wrap(Float.unwrap(LibDecimalFloat.packLossless(0.5e18, -18))); // orderOutputMax @@ -823,7 +823,7 @@ contract RaindexV6ClearTest is RaindexV6ExternalMockTest { checkClearStruct.expectedError = ""; // Mock the interpreter.eval that is used inside clear().calculateOrderIO() - // Produce the stack output for OB + // Produce the stack output for Raindex checkClearStruct.orderStackAlice = new StackItem[](2); checkClearStruct.orderStackAlice[0] = StackItem.wrap(Float.unwrap(aliceIORatio)); // orderIORatio checkClearStruct.orderStackAlice[1] = StackItem.wrap(Float.unwrap(aliceOutput)); // orderOutputMax @@ -874,7 +874,7 @@ contract RaindexV6ClearTest is RaindexV6ExternalMockTest { Float bobOutput = LibDecimalFloat.packLossless(1, 0); // Mock the interpreter.eval that is used inside clear().calculateOrderIO() - // Produce the stack output for OB + // Produce the stack output for Raindex checkClearStruct.orderStackAlice = new StackItem[](2); checkClearStruct.orderStackAlice[0] = StackItem.wrap(Float.unwrap(aliceIORatio)); // orderIORatio checkClearStruct.orderStackAlice[1] = StackItem.wrap(Float.unwrap(aliceOutput)); // orderOutputMax diff --git a/test/concrete/raindex/RaindexV6.takeOrder.precision.t.sol b/test/concrete/raindex/RaindexV6.takeOrder.precision.t.sol index a615f90147..d0bf1346bd 100644 --- a/test/concrete/raindex/RaindexV6.takeOrder.precision.t.sol +++ b/test/concrete/raindex/RaindexV6.takeOrder.precision.t.sol @@ -151,7 +151,7 @@ contract RaindexV6TakeOrderPrecisionTest is RaindexV6ExternalRealTest { } } - // Older versions of OB had precision issues with this IO setup. + // Older versions of Raindex had precision issues with this IO setup. // bytes memory knownBad = "output-max io-ratio:157116.36568049186712991 0.000318235466963885;:;"; bytes constant KNOWN_BAD = bytes("output-max io-ratio:157116.36568049186712991 0.000318235466963885;:;"); diff --git a/test/lib/LibRaindexArb.finalizeArbNativeGas.t.sol b/test/lib/LibRaindexArb.finalizeArbNativeGas.t.sol index ccba68efa5..4164191a42 100644 --- a/test/lib/LibRaindexArb.finalizeArbNativeGas.t.sol +++ b/test/lib/LibRaindexArb.finalizeArbNativeGas.t.sol @@ -10,7 +10,7 @@ contract LibRaindexArbFinalizeArbNativeGasTest is Test { function testFinalizeArbSendsNativeGas() external { uint256 senderBalanceBefore = address(this).balance; - // OB has 100e18 output, pulls 100e18 input. Exchange has 100e18 input. + // Raindex has 100e18 output, pulls 100e18 input. Exchange has 100e18 input. // No token profit. 1 ether sent with arb5, returned by exchange, swept. ArbResult memory result = LibTestArb.setupAndArb(vm, 100e18, 100e18, 100e18, 100e18, LibTestArb.noopTask(), 1 ether); diff --git a/test/lib/LibRaindexArb.finalizeArbOutputTokenProfit.t.sol b/test/lib/LibRaindexArb.finalizeArbOutputTokenProfit.t.sol index e6e8813172..c647d065c6 100644 --- a/test/lib/LibRaindexArb.finalizeArbOutputTokenProfit.t.sol +++ b/test/lib/LibRaindexArb.finalizeArbOutputTokenProfit.t.sol @@ -8,19 +8,19 @@ import {LibTestArb, ArbResult} from "test/util/lib/LibTestArb.sol"; contract LibRaindexArbFinalizeArbOutputTokenProfitTest is Test { /// finalizeArb MUST transfer remaining output token profit to msg.sender. function testFinalizeArbTransfersOutputTokenProfit() external { - // OB has 100e18 output, pulls 80e18 input. Exchange has 80e18 input. + // Raindex has 100e18 output, pulls 80e18 input. Exchange has 80e18 input. // Arb swaps only 80e18 output → 80e18 input. 20e18 output profit. ArbResult memory result = LibTestArb.setupAndArb(vm, 80e18, 100e18, 80e18, 80e18, LibTestArb.noopTask(), 0); // 20e18 output token profit swept to msg.sender by finalizeArb. assertEq(result.outputToken.balanceOf(address(this)), 20e18, "sender outputToken profit"); - // No input token profit (all 80e18 went to OB). + // No input token profit (all 80e18 went to Raindex). assertEq(result.inputToken.balanceOf(address(this)), 0, "sender inputToken"); // Arb contract is empty after finalizeArb. assertEq(result.inputToken.balanceOf(address(result.arb)), 0, "arb inputToken"); assertEq(result.outputToken.balanceOf(address(result.arb)), 0, "arb outputToken"); - // OB got exactly what it pulled. - assertEq(result.inputToken.balanceOf(address(result.raindex)), 80e18, "OB inputToken"); + // Raindex got exactly what it pulled. + assertEq(result.inputToken.balanceOf(address(result.raindex)), 80e18, "Raindex inputToken"); // Exchange did a partial swap. assertEq(result.outputToken.balanceOf(address(result.exchange)), 80e18, "exchange outputToken"); } diff --git a/test/lib/LibRaindexArb.finalizeArbTaskContext.t.sol b/test/lib/LibRaindexArb.finalizeArbTaskContext.t.sol index f1160065a5..041c8c3ee7 100644 --- a/test/lib/LibRaindexArb.finalizeArbTaskContext.t.sol +++ b/test/lib/LibRaindexArb.finalizeArbTaskContext.t.sol @@ -43,7 +43,7 @@ contract LibRaindexArbFinalizeArbTaskContextTest is Test { signedContext: new SignedContextV1[](0) }); - // OB has 100e18 output, pulls 80e18 input. Exchange has 100e18 input. + // Raindex has 100e18 output, pulls 80e18 input. Exchange has 100e18 input. // 20e18 input profit, 0 output profit, 0 gas. // Task expression will revert if context values are wrong. ArbResult memory result = LibTestArb.setupAndArb(vm, 80e18, 100e18, 100e18, 100e18, task, 0); diff --git a/test/lib/LibRaindexArb.finalizeArbTokenTransfers.t.sol b/test/lib/LibRaindexArb.finalizeArbTokenTransfers.t.sol index e6b3938f90..b175424882 100644 --- a/test/lib/LibRaindexArb.finalizeArbTokenTransfers.t.sol +++ b/test/lib/LibRaindexArb.finalizeArbTokenTransfers.t.sol @@ -8,8 +8,8 @@ import {LibTestArb, ArbResult} from "test/util/lib/LibTestArb.sol"; contract LibRaindexArbFinalizeArbTokenTransfersTest is Test { /// finalizeArb MUST transfer remaining input token profit to msg.sender. function testFinalizeArbTransfersInputTokenProfit() external { - // OB has 100e18 output, pulls 80e18 input. Exchange has 100e18 input. - // Arb swaps 100e18 output → 100e18 input. OB pulls 80e18. 20e18 profit. + // Raindex has 100e18 output, pulls 80e18 input. Exchange has 100e18 input. + // Arb swaps 100e18 output → 100e18 input. Raindex pulls 80e18. 20e18 profit. ArbResult memory result = LibTestArb.setupAndArb(vm, 80e18, 100e18, 100e18, 100e18, LibTestArb.noopTask(), 0); // 20e18 input token profit swept to msg.sender by finalizeArb. @@ -17,8 +17,8 @@ contract LibRaindexArbFinalizeArbTokenTransfersTest is Test { // Arb contract is empty after finalizeArb. assertEq(result.inputToken.balanceOf(address(result.arb)), 0, "arb inputToken"); assertEq(result.outputToken.balanceOf(address(result.arb)), 0, "arb outputToken"); - // OB got exactly what it pulled. - assertEq(result.inputToken.balanceOf(address(result.raindex)), 80e18, "OB inputToken"); + // Raindex got exactly what it pulled. + assertEq(result.inputToken.balanceOf(address(result.raindex)), 80e18, "Raindex inputToken"); // Exchange did a full swap. assertEq(result.outputToken.balanceOf(address(result.exchange)), 100e18, "exchange outputToken"); } diff --git a/test/util/concrete/RealisticOrderTakerMockRaindex.sol b/test/util/concrete/RealisticOrderTakerMockRaindex.sol index bd44582a4b..94d28ccf4f 100644 --- a/test/util/concrete/RealisticOrderTakerMockRaindex.sol +++ b/test/util/concrete/RealisticOrderTakerMockRaindex.sol @@ -29,7 +29,7 @@ contract RealisticOrderTakerMockRaindex is MockRaindexBase { // Send ordersOutputToken to taker (taker's input). IERC20(ordersOutputToken).safeTransfer(msg.sender, outputAmount); - // Callback: taker swaps received tokens for the tokens the OB will pull. + // Callback: taker swaps received tokens for the tokens the Raindex will pull. IRaindexV6OrderTaker(msg.sender) .onTakeOrders2(ordersOutputToken, ordersInputToken, Float.wrap(0), Float.wrap(0), config.data); diff --git a/test/util/concrete/ReentrantMockRaindex.sol b/test/util/concrete/ReentrantMockRaindex.sol index e4a8d66863..c50bb6b0c4 100644 --- a/test/util/concrete/ReentrantMockRaindex.sol +++ b/test/util/concrete/ReentrantMockRaindex.sol @@ -17,7 +17,7 @@ import {IInterpreterV4} from "rain.interpreter.interface/interface/IInterpreterV import {IInterpreterStoreV3} from "rain.interpreter.interface/interface/IInterpreterStoreV3.sol"; import {MockRaindexBase} from "test/util/abstract/MockRaindexBase.sol"; -/// @dev Mock OB whose takeOrders4 callback re-enters arb5 on the taker. +/// @dev Mock Raindex whose takeOrders4 callback re-enters arb5 on the taker. contract ReentrantMockRaindex is MockRaindexBase { using SafeERC20 for IERC20; @@ -32,7 +32,7 @@ contract ReentrantMockRaindex is MockRaindexBase { if (!sReentered) { sReentered = true; - // Re-enter arb5 from the OB callback. + // Re-enter arb5 from the Raindex callback. GenericPoolRaindexV6ArbOrderTaker(payable(msg.sender)) .arb5( IRaindexV6(address(this)), diff --git a/test/util/lib/LibTestArb.sol b/test/util/lib/LibTestArb.sol index 318c24a0a6..76cf4a3a4f 100644 --- a/test/util/lib/LibTestArb.sol +++ b/test/util/lib/LibTestArb.sol @@ -65,16 +65,16 @@ library LibTestArb { /// Set up a standard arb scenario and execute arb5. /// /// @param vm The Vm cheatcode handle. - /// @param obPullAmount How many inputTokens the mock OB pulls from arb. - /// @param obOutputAmount How many outputTokens the mock OB has to send. + /// @param raindexPullAmount How many inputTokens the mock Raindex pulls from arb. + /// @param raindexOutputAmount How many outputTokens the mock Raindex has to send. /// @param exchangeInputAmount How many inputTokens the exchange has. /// @param swapAmount How many outputTokens the arb swaps at the exchange. /// @param task The post-arb task to run. /// @param ethValue ETH to send with arb5. function setupAndArb( Vm vm, - uint256 obPullAmount, - uint256 obOutputAmount, + uint256 raindexPullAmount, + uint256 raindexOutputAmount, uint256 exchangeInputAmount, uint256 swapAmount, TaskV2 memory task, @@ -85,10 +85,10 @@ library LibTestArb { MockToken inputToken = new MockToken("Input", "IN", 18); MockToken outputToken = new MockToken("Output", "OUT", 18); - RealisticOrderTakerMockRaindex raindex = new RealisticOrderTakerMockRaindex(obPullAmount); + RealisticOrderTakerMockRaindex raindex = new RealisticOrderTakerMockRaindex(raindexPullAmount); MockExchange exchange = new MockExchange(); - outputToken.mint(address(raindex), obOutputAmount); + outputToken.mint(address(raindex), raindexOutputAmount); inputToken.mint(address(exchange), exchangeInputAmount); GenericPoolRaindexV6ArbOrderTaker arb = new GenericPoolRaindexV6ArbOrderTaker(); @@ -142,7 +142,7 @@ library LibTestArb { /// @param vm The Vm cheatcode handle. /// @param exchange The exchange contract address. /// @param amount Token amount for the swap (18 decimals). Used as - /// obPullAmount, obOutputAmount, exchangeInputAmount, and swapAmount. + /// raindexPullAmount, raindexOutputAmount, exchangeInputAmount, and swapAmount. function setup(Vm vm, address exchange, uint256 amount) internal returns (OrderTakerSetup memory) { deployPrereqs(vm); From 631360c660f816336bf29bc4e599a9fb0ff9d57f Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Wed, 1 Apr 2026 15:45:09 +0400 Subject: [PATCH 33/69] Rename ob variable names to raindex across Rust and Solidity Co-Authored-By: Claude Opus 4.6 (1M context) --- .../local_db/pipeline/runner/manifest.rs | 2 +- crates/common/src/dotrain_order.rs | 4 +- .../common/src/raindex_client/local_db/mod.rs | 2 +- .../local_db/pipeline/runner/config.rs | 4 +- .../pipeline/runner/scheduler/native.rs | 8 ++-- .../pipeline/runner/scheduler/wasm.rs | 8 ++-- .../src/raindex_client/local_db/state.rs | 4 +- .../src/raindex_client/take_orders/result.rs | 40 +++++++++---------- crates/settings/src/local_db_manifest.rs | 10 ++--- crates/settings/src/raindex.rs | 16 ++++---- crates/settings/src/remote/manifest.rs | 2 +- crates/settings/src/yaml/raindex.rs | 24 +++++------ ...indexV6FlashBorrower.flashLoanFailed.t.sol | 4 +- ...RaindexV6FlashBorrower.mixedDecimals.t.sol | 4 +- ...exV6FlashBorrower.realTokenTransfers.t.sol | 4 +- test/lib/deploy/LibRaindexDeploy.t.sol | 8 ++-- test/util/abstract/ArbTest.sol | 4 +- test/util/lib/LibTestFlashBorrowerArb.sol | 4 +- 18 files changed, 76 insertions(+), 76 deletions(-) diff --git a/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs b/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs index 92780a7967..f14eadaef6 100644 --- a/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs +++ b/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs @@ -406,7 +406,7 @@ mod tests { let manifest = build_manifest(&successes, &exports, &lookup, &base_url, &HashMap::new()) .expect("manifest build succeeds"); let anvil = manifest.networks.get("anvil").expect("anvil network"); - let addresses: Vec<_> = anvil.raindexes.iter().map(|ob| ob.address).collect(); + let addresses: Vec<_> = anvil.raindexes.iter().map(|raindex_entry| raindex_entry.address).collect(); assert_eq!( addresses, vec![ diff --git a/crates/common/src/dotrain_order.rs b/crates/common/src/dotrain_order.rs index 98dd648fee..ba458f4ea3 100644 --- a/crates/common/src/dotrain_order.rs +++ b/crates/common/src/dotrain_order.rs @@ -628,11 +628,11 @@ impl DotrainOrder { let network_key = order_cfg.network.key.clone(); let rainlang_key = rainlang_cfg.key.clone(); - let raindex_key = order_cfg.raindex.as_ref().map(|ob| ob.key.clone()); + let raindex_key = order_cfg.raindex.as_ref().map(|raindex_cfg| raindex_cfg.key.clone()); let subgraph_key = order_cfg .raindex .as_ref() - .map(|ob| ob.subgraph.key.clone()); + .map(|raindex_cfg| raindex_cfg.subgraph.key.clone()); let order_key = order_cfg.key.clone(); let deployment_key = deployment.key.clone(); diff --git a/crates/common/src/raindex_client/local_db/mod.rs b/crates/common/src/raindex_client/local_db/mod.rs index 570a990174..5dd82b4b81 100644 --- a/crates/common/src/raindex_client/local_db/mod.rs +++ b/crates/common/src/raindex_client/local_db/mod.rs @@ -378,7 +378,7 @@ local-db-sync: bootstrap-block-threshold: 1000 sync-interval-ms: 5000 raindexes: - ob-a: + raindex-a: address: 0x00000000000000000000000000000000000000a1 network: anvil subgraph: anvil diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/config.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/config.rs index cfaac9ac36..c752c5dcfa 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/config.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/config.rs @@ -21,7 +21,7 @@ impl NetworkRunnerConfig { let filtered_raindexes: HashMap = global .raindexes .iter() - .filter(|(_, ob)| ob.network.key == network_key) + .filter(|(_, raindex_cfg)| raindex_cfg.network.key == network_key) .map(|(k, v)| (k.clone(), v.clone())) .collect(); @@ -35,7 +35,7 @@ impl NetworkRunnerConfig { let chain_id = filtered_raindexes .values() .next() - .map(|ob| ob.network.chain_id) + .map(|raindex_cfg| raindex_cfg.network.chain_id) .ok_or_else(|| { LocalDbError::CustomError(format!( "could not determine chain_id for network: {}", diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/native.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/native.rs index bb3d12fde5..1096d72eaa 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/native.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/native.rs @@ -82,10 +82,10 @@ pub fn start( sync_readiness: SyncReadiness, ) -> Result { let mut networks_map: HashMap = HashMap::new(); - for ob in settings.raindexes.values() { + for raindex_cfg in settings.raindexes.values() { networks_map - .entry(ob.network.key.clone()) - .or_insert_with(|| (*ob.network).clone()); + .entry(raindex_cfg.network.key.clone()) + .or_insert_with(|| (*raindex_cfg.network).clone()); } let mut networks: Vec = networks_map.into_values().collect(); networks.sort_by(|a, b| a.key.cmp(&b.key)); @@ -234,7 +234,7 @@ async fn run_network_loop( tracing::warn!( network = %network_key, chain_id, - ob = %format!("{:#x}", failure.ob_id.raindex_address), + raindex = %format!("{:#x}", failure.ob_id.raindex_address), stage = ?failure.stage, error = %failure.error, "sync target failed" diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/wasm.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/wasm.rs index a35db1f0d8..c19eaa5172 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/wasm.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/wasm.rs @@ -86,10 +86,10 @@ pub(crate) fn start( sync_readiness: SyncReadiness, ) -> Result { let mut networks_map: HashMap = HashMap::new(); - for ob in settings.raindexes.values() { + for raindex_cfg in settings.raindexes.values() { networks_map - .entry(ob.network.key.clone()) - .or_insert_with(|| (*ob.network).clone()); + .entry(raindex_cfg.network.key.clone()) + .or_insert_with(|| (*raindex_cfg.network).clone()); } let mut networks: Vec = networks_map.into_values().collect(); networks.sort_by(|a, b| a.key.cmp(&b.key)); @@ -244,7 +244,7 @@ async fn run_network_loop( } else { let first = &report.failures[0]; let msg = format!( - "ob {:#x} failed at {:?}: {}", + "raindex {:#x} failed at {:?}: {}", first.ob_id.raindex_address, first.stage, first.error.to_readable_msg() diff --git a/crates/common/src/raindex_client/local_db/state.rs b/crates/common/src/raindex_client/local_db/state.rs index 1fb71ae62c..1a0d4b179a 100644 --- a/crates/common/src/raindex_client/local_db/state.rs +++ b/crates/common/src/raindex_client/local_db/state.rs @@ -415,7 +415,7 @@ local-db-sync: bootstrap-block-threshold: 1000 sync-interval-ms: 5000 raindexes: - ob-a: + raindex-a: address: 0x00000000000000000000000000000000000000a1 network: anvil subgraph: anvil @@ -443,7 +443,7 @@ networks: subgraphs: anvil: https://subgraph.example/anvil raindexes: - ob-a: + raindex-a: address: 0x00000000000000000000000000000000000000a1 network: anvil subgraph: anvil diff --git a/crates/common/src/raindex_client/take_orders/result.rs b/crates/common/src/raindex_client/take_orders/result.rs index 256ec54266..9ddf4419f3 100644 --- a/crates/common/src/raindex_client/take_orders/result.rs +++ b/crates/common/src/raindex_client/take_orders/result.rs @@ -449,10 +449,10 @@ mod tests { #[test] fn test_build_calldata_result_produces_valid_calldata_buy_mode() { - let ob = Address::from([0x11u8; 20]); + let raindex_addr = Address::from([0x11u8; 20]); let max_output = Float::parse("10".to_string()).unwrap(); let ratio = Float::parse("2".to_string()).unwrap(); - let candidate = make_candidate(ob, max_output, ratio); + let candidate = make_candidate(raindex_addr, max_output, ratio); let candidates = vec![candidate]; let buy_target = Float::parse("10".to_string()).unwrap(); let price_cap = high_price_cap(); @@ -463,13 +463,13 @@ mod tests { .unwrap() .unwrap(); - let result = build_calldata_result(ob, built, mode, price_cap); + let result = build_calldata_result(raindex_addr, built, mode, price_cap); assert!(result.is_ok()); let result = result.unwrap(); assert!(result.is_ready()); let take_orders_info = result.take_orders_info().unwrap(); - assert_eq!(take_orders_info.raindex(), ob); + assert_eq!(take_orders_info.raindex(), raindex_addr); assert!(!take_orders_info.calldata().is_empty()); assert!(!take_orders_info.prices().is_empty()); @@ -484,10 +484,10 @@ mod tests { #[test] fn test_build_calldata_result_produces_valid_calldata_spend_mode() { - let ob = Address::from([0x11u8; 20]); + let raindex_addr = Address::from([0x11u8; 20]); let max_output = Float::parse("100".to_string()).unwrap(); let ratio = Float::parse("2".to_string()).unwrap(); - let candidate = make_candidate(ob, max_output, ratio); + let candidate = make_candidate(raindex_addr, max_output, ratio); let candidates = vec![candidate]; let spend_budget = Float::parse("20".to_string()).unwrap(); let price_cap = high_price_cap(); @@ -498,13 +498,13 @@ mod tests { .unwrap() .unwrap(); - let result = build_calldata_result(ob, built, mode, price_cap); + let result = build_calldata_result(raindex_addr, built, mode, price_cap); assert!(result.is_ok()); let result = result.unwrap(); assert!(result.is_ready()); let take_orders_info = result.take_orders_info().unwrap(); - assert_eq!(take_orders_info.raindex(), ob); + assert_eq!(take_orders_info.raindex(), raindex_addr); assert!(!take_orders_info.calldata().is_empty()); assert!(!take_orders_info.prices().is_empty()); @@ -519,10 +519,10 @@ mod tests { #[test] fn test_build_calldata_result_effective_price_calculation() { - let ob = Address::from([0x11u8; 20]); + let raindex_addr = Address::from([0x11u8; 20]); let max_output = Float::parse("10".to_string()).unwrap(); let ratio = Float::parse("2".to_string()).unwrap(); - let candidate = make_candidate(ob, max_output, ratio); + let candidate = make_candidate(raindex_addr, max_output, ratio); let candidates = vec![candidate]; let buy_target = Float::parse("10".to_string()).unwrap(); let price_cap = high_price_cap(); @@ -533,7 +533,7 @@ mod tests { .unwrap() .unwrap(); - let result = build_calldata_result(ob, built, mode, price_cap).unwrap(); + let result = build_calldata_result(raindex_addr, built, mode, price_cap).unwrap(); assert!(result.is_ready()); let take_orders_info = result.take_orders_info().unwrap(); @@ -546,10 +546,10 @@ mod tests { #[test] fn test_build_calldata_result_prices_match_legs() { - let ob = Address::from([0x11u8; 20]); + let raindex_addr = Address::from([0x11u8; 20]); let max_output = Float::parse("10".to_string()).unwrap(); let ratio = Float::parse("2".to_string()).unwrap(); - let candidate = make_candidate(ob, max_output, ratio); + let candidate = make_candidate(raindex_addr, max_output, ratio); let candidates = vec![candidate]; let buy_target = Float::parse("10".to_string()).unwrap(); let price_cap = high_price_cap(); @@ -561,7 +561,7 @@ mod tests { .unwrap() .unwrap(); - let result = build_calldata_result(ob, built, mode, price_cap).unwrap(); + let result = build_calldata_result(raindex_addr, built, mode, price_cap).unwrap(); assert!(result.is_ready()); let take_orders_info = result.take_orders_info().unwrap(); @@ -578,10 +578,10 @@ mod tests { #[test] fn test_build_calldata_result_expected_sell_and_max_sell_cap_buy_mode() { - let ob = Address::from([0x11u8; 20]); + let raindex_addr = Address::from([0x11u8; 20]); let max_output = Float::parse("10".to_string()).unwrap(); let ratio = Float::parse("2".to_string()).unwrap(); - let candidate = make_candidate(ob, max_output, ratio); + let candidate = make_candidate(raindex_addr, max_output, ratio); let candidates = vec![candidate]; let buy_target = Float::parse("10".to_string()).unwrap(); let price_cap = Float::parse("3".to_string()).unwrap(); @@ -592,7 +592,7 @@ mod tests { .unwrap() .unwrap(); - let result = build_calldata_result(ob, built, mode, price_cap).unwrap(); + let result = build_calldata_result(raindex_addr, built, mode, price_cap).unwrap(); assert!(result.is_ready()); let take_orders_info = result.take_orders_info().unwrap(); @@ -614,10 +614,10 @@ mod tests { #[test] fn test_build_calldata_result_expected_sell_and_max_sell_cap_spend_mode() { - let ob = Address::from([0x11u8; 20]); + let raindex_addr = Address::from([0x11u8; 20]); let max_output = Float::parse("100".to_string()).unwrap(); let ratio = Float::parse("2".to_string()).unwrap(); - let candidate = make_candidate(ob, max_output, ratio); + let candidate = make_candidate(raindex_addr, max_output, ratio); let candidates = vec![candidate]; let spend_budget = Float::parse("20".to_string()).unwrap(); let price_cap = Float::parse("3".to_string()).unwrap(); @@ -628,7 +628,7 @@ mod tests { .unwrap() .unwrap(); - let result = build_calldata_result(ob, built, mode, price_cap).unwrap(); + let result = build_calldata_result(raindex_addr, built, mode, price_cap).unwrap(); assert!(result.is_ready()); let take_orders_info = result.take_orders_info().unwrap(); diff --git a/crates/settings/src/local_db_manifest.rs b/crates/settings/src/local_db_manifest.rs index 91b0811b45..7062f8c473 100644 --- a/crates/settings/src/local_db_manifest.rs +++ b/crates/settings/src/local_db_manifest.rs @@ -106,7 +106,7 @@ impl LocalDbManifest { self.networks .values() .find(|n| n.chain_id == chain_id) - .and_then(|n| n.raindexes.iter().find(|ob| ob.address == address)) + .and_then(|n| n.raindexes.iter().find(|raindex_entry| raindex_entry.address == address)) } pub fn new() -> Self { @@ -611,10 +611,10 @@ end-block: 1 end-block-hash: "0x0abc" end-block-time-ms: 1 "#; - let ob_doc = load(ob_ok); - let ob = parse_single_raindex(0, &ob_doc, base_loc).expect("raindex parses"); - assert_eq!(ob.end_block, 1); - assert_eq!(ob.end_block_time_ms, 1); + let raindex_doc = load(ob_ok); + let raindex_entry = parse_single_raindex(0, &raindex_doc, base_loc).expect("raindex parses"); + assert_eq!(raindex_entry.end_block, 1); + assert_eq!(raindex_entry.end_block_time_ms, 1); // Bad address let ob_bad = r#" diff --git a/crates/settings/src/raindex.rs b/crates/settings/src/raindex.rs index 37bb979de7..a0b8b91a1b 100644 --- a/crates/settings/src/raindex.rs +++ b/crates/settings/src/raindex.rs @@ -861,8 +861,8 @@ raindexes: deployment-block: 123 "#; let raindexes = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); - let ob = raindexes.get("TestRaindex").unwrap(); - let remote = ob.local_db_remote.as_ref().expect("expected remote"); + let raindex_cfg = raindexes.get("TestRaindex").unwrap(); + let remote = raindex_cfg.local_db_remote.as_ref().expect("expected remote"); assert_eq!(remote.key, "TestRaindex"); assert_eq!( remote.url.to_string(), @@ -891,8 +891,8 @@ raindexes: deployment-block: 123 "#; let raindexes = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); - let ob = raindexes.get("TestRaindex").unwrap(); - let remote = ob.local_db_remote.as_ref().expect("expected remote"); + let raindex_cfg = raindexes.get("TestRaindex").unwrap(); + let remote = raindex_cfg.local_db_remote.as_ref().expect("expected remote"); assert_eq!(remote.key, "mainnet"); assert_eq!( remote.url.to_string(), @@ -919,8 +919,8 @@ raindexes: deployment-block: 123 "#; let raindexes = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); - let ob = raindexes.get("TestRaindex").unwrap(); - assert!(ob.local_db_remote.is_none()); + let raindex_cfg = raindexes.get("TestRaindex").unwrap(); + assert!(raindex_cfg.local_db_remote.is_none()); let yaml = r#" networks: @@ -939,8 +939,8 @@ raindexes: deployment-block: 123 "#; let raindexes = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); - let ob = raindexes.get("TestRaindex").unwrap(); - assert!(ob.local_db_remote.is_none()); + let raindex_cfg = raindexes.get("TestRaindex").unwrap(); + assert!(raindex_cfg.local_db_remote.is_none()); } #[test] diff --git a/crates/settings/src/remote/manifest.rs b/crates/settings/src/remote/manifest.rs index 17a511fdc6..b4fb09e9a6 100644 --- a/crates/settings/src/remote/manifest.rs +++ b/crates/settings/src/remote/manifest.rs @@ -119,7 +119,7 @@ networks: end-block: 555 end-block-hash: "0x0def" end-block-time-ms: 2000 - extra-ob: ignored + extra-raindex: ignored "#; server diff --git a/crates/settings/src/yaml/raindex.rs b/crates/settings/src/yaml/raindex.rs index 3052b84acc..86f06058a7 100644 --- a/crates/settings/src/yaml/raindex.rs +++ b/crates/settings/src/yaml/raindex.rs @@ -356,8 +356,8 @@ impl RaindexYaml { let mut raindexes: Vec<_> = self .get_raindexes()? .into_iter() - .filter(|(_, ob)| ob.network.key == network_key) - .map(|(_, ob)| ob) + .filter(|(_, raindex_cfg)| raindex_cfg.network.key == network_key) + .map(|(_, raindex_cfg)| raindex_cfg) .collect(); raindexes.sort_by(|a, b| a.key.cmp(&b.key)); @@ -378,8 +378,8 @@ impl RaindexYaml { let mut raindexes: Vec<_> = self .get_raindexes()? .into_iter() - .filter(|(_, ob)| ob.network.key == network.key) - .map(|(_, ob)| ob) + .filter(|(_, raindex_cfg)| raindex_cfg.network.key == network.key) + .map(|(_, raindex_cfg)| raindex_cfg) .collect(); raindexes.sort_by(|a, b| a.key.cmp(&b.key)); @@ -573,7 +573,7 @@ mod tests { #[test] fn test_raindex_yaml_profile_helpers() { let sources = vec![full_yaml()]; - let ob = RaindexYaml::new_with_profile( + let yaml = RaindexYaml::new_with_profile( sources.clone(), RaindexYamlValidation::default(), ContextProfile::Gui { @@ -581,18 +581,18 @@ mod tests { }, ) .unwrap(); - assert!(matches!(ob.profile, ContextProfile::Gui { .. })); + assert!(matches!(yaml.profile, ContextProfile::Gui { .. })); - let ob_default = RaindexYaml::new(sources, RaindexYamlValidation::default()).unwrap(); - assert!(matches!(ob_default.profile, ContextProfile::Strict)); + let yaml_default = RaindexYaml::new(sources, RaindexYamlValidation::default()).unwrap(); + assert!(matches!(yaml_default.profile, ContextProfile::Strict)); - let ob_strict = ob.with_profile(ContextProfile::Strict); - assert!(matches!(ob_strict.profile, ContextProfile::Strict)); + let yaml_strict = yaml.with_profile(ContextProfile::Strict); + assert!(matches!(yaml_strict.profile, ContextProfile::Strict)); } #[test] fn test_raindex_yaml_serialization_preserves_profile() { - let ob = RaindexYaml::new_with_profile( + let yaml = RaindexYaml::new_with_profile( vec![full_yaml()], RaindexYamlValidation::default(), ContextProfile::Gui { @@ -601,7 +601,7 @@ mod tests { ) .unwrap(); - let serialized = serde_json::to_string(&ob).unwrap(); + let serialized = serde_json::to_string(&yaml).unwrap(); let round_tripped: RaindexYaml = serde_json::from_str(&serialized).unwrap(); match round_tripped.profile { ContextProfile::Gui { current_deployment } => { diff --git a/test/abstract/RaindexV6FlashBorrower.flashLoanFailed.t.sol b/test/abstract/RaindexV6FlashBorrower.flashLoanFailed.t.sol index 10d283dcc8..d4b5a1e418 100644 --- a/test/abstract/RaindexV6FlashBorrower.flashLoanFailed.t.sol +++ b/test/abstract/RaindexV6FlashBorrower.flashLoanFailed.t.sol @@ -40,8 +40,8 @@ contract RaindexV6FlashBorrowerFlashLoanFailedTest is Test { MockToken inputToken = new MockToken("Input", "IN", 18); MockToken outputToken = new MockToken("Output", "OUT", 18); - FalseFlashLoanMockRaindex mockOb = new FalseFlashLoanMockRaindex(); - vm.etch(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, address(mockOb).code); + FalseFlashLoanMockRaindex mockRaindex = new FalseFlashLoanMockRaindex(); + vm.etch(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, address(mockRaindex).code); GenericPoolRaindexV6FlashBorrower arb = new GenericPoolRaindexV6FlashBorrower(); diff --git a/test/abstract/RaindexV6FlashBorrower.mixedDecimals.t.sol b/test/abstract/RaindexV6FlashBorrower.mixedDecimals.t.sol index 2a7091d4a7..f20ff335bf 100644 --- a/test/abstract/RaindexV6FlashBorrower.mixedDecimals.t.sol +++ b/test/abstract/RaindexV6FlashBorrower.mixedDecimals.t.sol @@ -38,8 +38,8 @@ contract RaindexV6FlashBorrowerMixedDecimalsTest is Test { MockToken inputToken = new MockToken("DAI", "DAI", 18); MockToken outputToken = new MockToken("USDT", "USDT", 6); - RealisticFlashLendingMockRaindex mockOb = new RealisticFlashLendingMockRaindex(); - vm.etch(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, address(mockOb).code); + RealisticFlashLendingMockRaindex mockRaindex = new RealisticFlashLendingMockRaindex(); + vm.etch(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, address(mockRaindex).code); RealisticFlashLendingMockRaindex raindex = RealisticFlashLendingMockRaindex(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS); MockExchange exchange = new MockExchange(); diff --git a/test/abstract/RaindexV6FlashBorrower.realTokenTransfers.t.sol b/test/abstract/RaindexV6FlashBorrower.realTokenTransfers.t.sol index c41522f7bd..1d9f98669a 100644 --- a/test/abstract/RaindexV6FlashBorrower.realTokenTransfers.t.sol +++ b/test/abstract/RaindexV6FlashBorrower.realTokenTransfers.t.sol @@ -37,8 +37,8 @@ contract RaindexV6FlashBorrowerRealTokenTransfersTest is Test { MockToken inputToken = new MockToken("Input", "IN", 18); MockToken outputToken = new MockToken("Output", "OUT", 18); - RealisticFlashLendingMockRaindex mockOb = new RealisticFlashLendingMockRaindex(); - vm.etch(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, address(mockOb).code); + RealisticFlashLendingMockRaindex mockRaindex = new RealisticFlashLendingMockRaindex(); + vm.etch(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, address(mockRaindex).code); RealisticFlashLendingMockRaindex raindex = RealisticFlashLendingMockRaindex(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS); MockExchange exchange = new MockExchange(); diff --git a/test/lib/deploy/LibRaindexDeploy.t.sol b/test/lib/deploy/LibRaindexDeploy.t.sol index 955f64ca9d..0e1da37d74 100644 --- a/test/lib/deploy/LibRaindexDeploy.t.sol +++ b/test/lib/deploy/LibRaindexDeploy.t.sol @@ -73,8 +73,8 @@ contract LibRaindexDeployTest is Test { /// The codehash of a freshly deployed RaindexV6 MUST match the expected /// codehash constant. function testExpectedCodeHashRaindex() external { - RaindexV6 ob = new RaindexV6(); - assertEq(address(ob).codehash, LibRaindexDeploy.RAINDEX_DEPLOYED_CODEHASH); + RaindexV6 raindex = new RaindexV6(); + assertEq(address(raindex).codehash, LibRaindexDeploy.RAINDEX_DEPLOYED_CODEHASH); } /// The codehash of a freshly deployed RaindexV6SubParser MUST match the @@ -99,8 +99,8 @@ contract LibRaindexDeployTest is Test { /// The precompiled runtime code constant for RaindexV6 MUST match the /// deployed runtime bytecode. function testRuntimeCodeRaindex() external { - RaindexV6 ob = new RaindexV6(); - assertEq(keccak256(RAINDEX_RUNTIME_CODE), keccak256(address(ob).code)); + RaindexV6 raindex = new RaindexV6(); + assertEq(keccak256(RAINDEX_RUNTIME_CODE), keccak256(address(raindex).code)); } /// The precompiled runtime code constant for RaindexV6SubParser MUST diff --git a/test/util/abstract/ArbTest.sol b/test/util/abstract/ArbTest.sol index 75b59a911e..a5632532f6 100644 --- a/test/util/abstract/ArbTest.sol +++ b/test/util/abstract/ArbTest.sol @@ -47,8 +47,8 @@ abstract contract ArbTest is Test { vm.label(iRefundoor, "iRefundoor"); // Deploy the mock then etch its code at the deterministic raindex // address so that onFlashLoan's BadLender check passes. - FlashLendingMockRaindex mockOb = new FlashLendingMockRaindex(); - vm.etch(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, address(mockOb).code); + FlashLendingMockRaindex mockRaindex = new FlashLendingMockRaindex(); + vm.etch(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, address(mockRaindex).code); iRaindex = FlashLendingMockRaindex(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS); vm.label(address(iRaindex), "iRaindex"); diff --git a/test/util/lib/LibTestFlashBorrowerArb.sol b/test/util/lib/LibTestFlashBorrowerArb.sol index 990cf3e180..210a5a987d 100644 --- a/test/util/lib/LibTestFlashBorrowerArb.sol +++ b/test/util/lib/LibTestFlashBorrowerArb.sol @@ -52,8 +52,8 @@ library LibTestFlashBorrowerArb { MockToken inputToken = new MockToken("Input", "IN", 18); MockToken outputToken = new MockToken("Output", "OUT", 18); - RealisticFlashLendingMockRaindex mockOb = new RealisticFlashLendingMockRaindex(); - vm.etch(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, address(mockOb).code); + RealisticFlashLendingMockRaindex mockRaindex = new RealisticFlashLendingMockRaindex(); + vm.etch(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, address(mockRaindex).code); IRaindexV6 raindex = IRaindexV6(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS); outputToken.mint(address(raindex), 10 * amount); From dc19dddc5b66b71c5cb6ffc40c580d2eb2990ea6 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Wed, 1 Apr 2026 17:24:54 +0400 Subject: [PATCH 34/69] Rename ob_id to raindex_id and fix remaining ob variable names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Renames the public struct field ob_id → raindex_id across all Rust crates (285 occurrences, 31 files) and obId → raindexId in TS packages. Also fixes remaining ob closure params in Svelte components. Co-Authored-By: Claude Opus 4.6 (1M context) --- crates/cli/src/commands/local_db/cli.rs | 34 ++++----- .../commands/local_db/pipeline/bootstrap.rs | 10 +-- .../local_db/pipeline/runner/environment.rs | 6 +- .../local_db/pipeline/runner/export.rs | 26 +++---- .../local_db/pipeline/runner/manifest.rs | 58 +++++++-------- .../commands/local_db/pipeline/runner/mod.rs | 70 +++++++++---------- .../src/commands/local_db/pipeline/status.rs | 12 ++-- .../src/raindex_client/local_db/orders.rs | 16 ++--- .../local_db/pipeline/bootstrap.rs | 32 ++++----- .../local_db/pipeline/runner/environment.rs | 6 +- .../local_db/pipeline/runner/mod.rs | 12 ++-- .../pipeline/runner/scheduler/native.rs | 4 +- .../pipeline/runner/scheduler/wasm.rs | 4 +- .../local_db/pipeline/status/mod.rs | 32 ++++----- .../local_db/pipeline/status/native.rs | 20 +++--- .../local_db/pipeline/status/wasm.rs | 54 +++++++------- .../query/fetch_erc20_tokens_by_addresses.rs | 4 +- .../local_db/query/fetch_last_synced_block.rs | 4 +- .../local_db/query/fetch_order_trades.rs | 4 +- .../query/fetch_order_trades_count.rs | 4 +- .../query/fetch_order_vaults_volume.rs | 4 +- .../local_db/query/fetch_store_addresses.rs | 4 +- .../query/fetch_transaction_by_hash.rs | 4 +- .../query/fetch_vault_balance_changes.rs | 4 +- .../query/update_last_synced_block.rs | 4 +- .../src/raindex_client/local_db/status.rs | 34 ++++----- .../raindex_client/local_db/transactions.rs | 12 ++-- .../src/raindex_client/local_db/vaults.rs | 10 +-- crates/common/src/raindex_client/orders.rs | 46 ++++++------ crates/common/src/raindex_client/trades.rs | 12 ++-- .../common/src/raindex_client/transactions.rs | 4 +- crates/common/src/raindex_client/vaults.rs | 32 ++++----- .../__tests__/DropdownRaindexesFilter.test.ts | 6 +- .../src/__tests__/LocalDbStatusCard.test.ts | 2 +- .../src/__tests__/LocalDbStatusModal.test.ts | 20 +++--- .../lib/components/LocalDbStatusModal.svelte | 16 ++--- .../dropdown/DropdownRaindexesFilter.svelte | 14 ++-- .../src/__tests__/localDbStatus.test.ts | 66 ++++++++--------- .../webapp/src/lib/stores/localDbStatus.ts | 4 +- 39 files changed, 355 insertions(+), 355 deletions(-) diff --git a/crates/cli/src/commands/local_db/cli.rs b/crates/cli/src/commands/local_db/cli.rs index 089e7a1e97..67a9d2dcc7 100644 --- a/crates/cli/src/commands/local_db/cli.rs +++ b/crates/cli/src/commands/local_db/cli.rs @@ -98,14 +98,14 @@ fn render_report_to(report: &ProducerRunReport, writer: &mut W) -> io: report.successes().len() )?; for outcome in report.successes() { - let ob_id = &outcome.outcome.ob_id; - match report.export_for(ob_id) { + let raindex_id = &outcome.outcome.raindex_id; + match report.export_for(raindex_id) { Some(export) => { writeln!( writer, "- chain {} raindex {:#x}: start {} → target {} | logs {} | events {} | dump {} (end block {}, hash {}, time {})", - ob_id.chain_id, - ob_id.raindex_address, + raindex_id.chain_id, + raindex_id.raindex_address, outcome.outcome.start_block, outcome.outcome.target_block, outcome.outcome.fetched_logs, @@ -120,8 +120,8 @@ fn render_report_to(report: &ProducerRunReport, writer: &mut W) -> io: writeln!( writer, "- chain {} raindex {:#x}: start {} → target {} | logs {} | events {} | dump ", - ob_id.chain_id, - ob_id.raindex_address, + raindex_id.chain_id, + raindex_id.raindex_address, outcome.outcome.start_block, outcome.outcome.target_block, outcome.outcome.fetched_logs, @@ -149,9 +149,9 @@ fn render_report_to(report: &ProducerRunReport, writer: &mut W) -> io: } fn render_failure_to(failure: &TargetFailure, writer: &mut W) -> io::Result<()> { - let ob_id = &failure.ob_id; - let address = ob_id.raindex_address; - let chain_id = ob_id.chain_id; + let raindex_id = &failure.raindex_id; + let address = raindex_id.raindex_address; + let chain_id = raindex_id.chain_id; let stage = failure.stage; let message = failure.error.to_readable_msg(); let key = failure @@ -202,7 +202,7 @@ mod tests { } fn sample_success_and_export(chain_id: u32) -> (TargetSuccess, ExportMetadata) { - let ob_id = RaindexIdentifier::new( + let raindex_id = RaindexIdentifier::new( chain_id, address!("0000000000000000000000000000000000000a11"), ); @@ -214,7 +214,7 @@ mod tests { window_overrides: WindowOverrides::default(), }; let inputs = SyncInputs { - ob_id: ob_id.clone(), + raindex_id: raindex_id.clone(), metadata_rpcs: Vec::new(), cfg: sync_config, dump_str: None, @@ -229,7 +229,7 @@ mod tests { }; let outcome = SyncOutcome { - ob_id: runner_target.inputs.ob_id.clone(), + raindex_id: runner_target.inputs.raindex_id.clone(), start_block: 200, target_block: 400, fetched_logs: 123, @@ -238,7 +238,7 @@ mod tests { let export = ExportMetadata { dump_path: PathBuf::from(format!( "./local-db/{}/{}-{}.sql.gz", - chain_id, chain_id, runner_target.inputs.ob_id.raindex_address + chain_id, chain_id, runner_target.inputs.raindex_id.raindex_address )), end_block: 400, end_block_hash: "0xdeadbeef".to_string(), @@ -252,7 +252,7 @@ mod tests { fn render_report_to_writes_success_summary() { let (success, export) = sample_success_and_export(42161); let mut exports = HashMap::new(); - exports.insert(success.outcome.ob_id.clone(), Some(export)); + exports.insert(success.outcome.raindex_id.clone(), Some(export)); let report = ProducerRunReport { successes: vec![success], failures: vec![], @@ -274,7 +274,7 @@ mod tests { fn render_report_to_handles_missing_dump() { let (success, _) = sample_success_and_export(10); let mut exports = HashMap::new(); - exports.insert(success.outcome.ob_id.clone(), None); + exports.insert(success.outcome.raindex_id.clone(), None); let report = ProducerRunReport { successes: vec![success], failures: vec![], @@ -292,7 +292,7 @@ mod tests { fn render_report_to_lists_failures() { let raindex_address = address!("0000000000000000000000000000000000000fA1"); let failure = TargetFailure { - ob_id: RaindexIdentifier::new(1, raindex_address), + raindex_id: RaindexIdentifier::new(1, raindex_address), raindex_key: Some("book".into()), stage: TargetStage::EngineRun, error: LocalDbError::CustomError("oh no".into()), @@ -316,7 +316,7 @@ mod tests { #[test] fn render_failure_to_handles_unknowns() { let failure = TargetFailure { - ob_id: RaindexIdentifier::new(0, Address::ZERO), + raindex_id: RaindexIdentifier::new(0, Address::ZERO), raindex_key: None, stage: TargetStage::EngineRun, error: LocalDbError::CustomError("boom".into()), diff --git a/crates/cli/src/commands/local_db/pipeline/bootstrap.rs b/crates/cli/src/commands/local_db/pipeline/bootstrap.rs index 0f6fc58365..dc7bf8daa7 100644 --- a/crates/cli/src/commands/local_db/pipeline/bootstrap.rs +++ b/crates/cli/src/commands/local_db/pipeline/bootstrap.rs @@ -125,7 +125,7 @@ mod tests { .with_views(); let cfg = BootstrapConfig { - ob_id: sample_ob_id(), + raindex_id: sample_ob_id(), dump_stmt: None, latest_block: 0, block_number_threshold: TEST_BLOCK_NUMBER_THRESHOLD, @@ -160,7 +160,7 @@ mod tests { .with_views(); let cfg = BootstrapConfig { - ob_id: sample_ob_id(), + raindex_id: sample_ob_id(), dump_stmt: None, latest_block: 0, block_number_threshold: TEST_BLOCK_NUMBER_THRESHOLD, @@ -194,7 +194,7 @@ mod tests { .with_views(); let cfg = BootstrapConfig { - ob_id: sample_ob_id(), + raindex_id: sample_ob_id(), dump_stmt: Some(SqlStatementBatch::from(vec![dump_stmt.clone()])), latest_block: 0, block_number_threshold: TEST_BLOCK_NUMBER_THRESHOLD, @@ -233,7 +233,7 @@ mod tests { .with_views(); let cfg = BootstrapConfig { - ob_id: sample_ob_id(), + raindex_id: sample_ob_id(), dump_stmt: Some(SqlStatementBatch::from(vec![dump_stmt.clone()])), latest_block: 0, block_number_threshold: TEST_BLOCK_NUMBER_THRESHOLD, @@ -270,7 +270,7 @@ mod tests { .with_views(); let cfg = BootstrapConfig { - ob_id: sample_ob_id(), + raindex_id: sample_ob_id(), dump_stmt: None, latest_block: 0, block_number_threshold: 1, diff --git a/crates/cli/src/commands/local_db/pipeline/runner/environment.rs b/crates/cli/src/commands/local_db/pipeline/runner/environment.rs index 62dad70621..a5485e6bed 100644 --- a/crates/cli/src/commands/local_db/pipeline/runner/environment.rs +++ b/crates/cli/src/commands/local_db/pipeline/runner/environment.rs @@ -33,14 +33,14 @@ pub fn default_environment( default_dump_downloader(), Arc::new(move |target: &RunnerTarget| { let events = DefaultEventsPipeline::with_hyperrpc( - target.inputs.ob_id.chain_id, + target.inputs.raindex_id.chain_id, hypersync_token.clone(), )?; let tokens = DefaultTokensPipeline::new(target.inputs.metadata_rpcs.clone())?; let status = ProducerStatusBus::new( debug_status, target.raindex_key.clone(), - target.inputs.ob_id.clone(), + target.inputs.raindex_id.clone(), ); Ok(EnginePipelines::new( @@ -73,7 +73,7 @@ mod tests { manifest_url: Url::parse("https://manifests.example/default.yaml").unwrap(), network_key: "anvil".to_string(), inputs: SyncInputs { - ob_id: RaindexIdentifier::new( + raindex_id: RaindexIdentifier::new( chain_id, address!("00000000000000000000000000000000000000a1"), ), diff --git a/crates/cli/src/commands/local_db/pipeline/runner/export.rs b/crates/cli/src/commands/local_db/pipeline/runner/export.rs index 50dd58b798..aafb2b16a2 100644 --- a/crates/cli/src/commands/local_db/pipeline/runner/export.rs +++ b/crates/cli/src/commands/local_db/pipeline/runner/export.rs @@ -28,17 +28,17 @@ pub(super) async fn export_dump( outcome: &SyncOutcome, out_root: &Path, ) -> Result, LocalDbError> { - let dump_sql = match export_data_only(executor, &target.inputs.ob_id).await? { + let dump_sql = match export_data_only(executor, &target.inputs.raindex_id).await? { Some(sql) => sql, None => return Ok(None), }; - let chain_folder = out_root.join(target.inputs.ob_id.chain_id.to_string()); + let chain_folder = out_root.join(target.inputs.raindex_id.chain_id.to_string()); create_dir_all(&chain_folder).await?; let filename = format!( "{}-{}.sql.gz", - target.inputs.ob_id.chain_id, target.inputs.ob_id.raindex_address + target.inputs.raindex_id.chain_id, target.inputs.raindex_id.raindex_address ); let dump_path = chain_folder.join(filename); @@ -51,12 +51,12 @@ pub(super) async fn export_dump( tokio::fs::write(&dump_path, compressed).await?; - let watermark_stmt = fetch_target_watermark_stmt(&target.inputs.ob_id); + let watermark_stmt = fetch_target_watermark_stmt(&target.inputs.raindex_id); let rows: Vec = executor.query_json(&watermark_stmt).await?; let row = rows.into_iter().next().ok_or_else(|| { LocalDbError::from(ExportError::MissingTargetWatermark { - chain_id: target.inputs.ob_id.chain_id, - raindex_address: target.inputs.ob_id.raindex_address, + chain_id: target.inputs.raindex_id.chain_id, + raindex_address: target.inputs.raindex_id.raindex_address, }) })?; @@ -137,7 +137,7 @@ mod tests { window_overrides: WindowOverrides::default(), }; - let ob_id = RaindexIdentifier { + let raindex_id = RaindexIdentifier { chain_id, raindex_address, }; @@ -147,7 +147,7 @@ mod tests { manifest_url: Url::parse("https://example.com/manifest.yaml").unwrap(), network_key: "anvil".to_string(), inputs: SyncInputs { - ob_id: ob_id.clone(), + raindex_id: raindex_id.clone(), metadata_rpcs: Vec::new(), cfg: sync_config, dump_str: None, @@ -157,7 +157,7 @@ mod tests { }; let outcome = SyncOutcome { - ob_id, + raindex_id, start_block: 900, target_block: 1000, fetched_logs: 1, @@ -181,7 +181,7 @@ mod tests { ); let expected_file = format!( "{}-{}.sql.gz", - chain_id, target.inputs.ob_id.raindex_address + chain_id, target.inputs.raindex_id.raindex_address ); assert_eq!( metadata @@ -226,7 +226,7 @@ mod tests { window_overrides: WindowOverrides::default(), }; - let ob_id = RaindexIdentifier { + let raindex_id = RaindexIdentifier { chain_id, raindex_address, }; @@ -236,7 +236,7 @@ mod tests { manifest_url: Url::parse("https://example.com/empty.yaml").unwrap(), network_key: "anvil".to_string(), inputs: SyncInputs { - ob_id: ob_id.clone(), + raindex_id: raindex_id.clone(), metadata_rpcs: Vec::new(), cfg: sync_config, dump_str: None, @@ -246,7 +246,7 @@ mod tests { }; let outcome = SyncOutcome { - ob_id, + raindex_id, start_block: 0, target_block: 0, fetched_logs: 0, diff --git a/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs b/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs index f14eadaef6..5d0ad6f49e 100644 --- a/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs +++ b/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs @@ -25,24 +25,24 @@ pub fn build_manifest( // First, record the latest successful exports. for success in successes { - let ob_id = &success.outcome.ob_id; - let export = match exports.get(ob_id).and_then(|export| export.as_ref()) { + let raindex_id = &success.outcome.raindex_id; + let export = match exports.get(raindex_id).and_then(|export| export.as_ref()) { Some(export) => export, None => continue, }; let runner_target = target_lookup - .get(ob_id) + .get(raindex_id) .ok_or_else(|| LocalDbError::MissingRunnerTarget { - chain_id: ob_id.chain_id, - raindex_address: ob_id.raindex_address, + chain_id: raindex_id.chain_id, + raindex_address: raindex_id.raindex_address, })?; - let dump_url = build_dump_url(release_base_url, ob_id.chain_id, ob_id.raindex_address)?; + let dump_url = build_dump_url(release_base_url, raindex_id.chain_id, raindex_id.raindex_address)?; let end_block_hash = Bytes::from_str(export.end_block_hash.as_str())?; let manifest_raindex = ManifestRaindex { - address: ob_id.raindex_address, + address: raindex_id.raindex_address, dump_url, end_block: export.end_block, end_block_hash, @@ -52,21 +52,21 @@ pub fn build_manifest( push_entry( &mut per_network, runner_target.network_key.clone(), - ob_id.chain_id, + raindex_id.chain_id, manifest_raindex, )?; } // Then, carry forward any existing manifest entries for targets that did // not produce a new dump in this run. - for (ob_id, runner_target) in target_lookup { + for (raindex_id, runner_target) in target_lookup { let already_recorded = per_network .get(&runner_target.network_key) .is_some_and(|(_, raindexes)| { raindexes .iter() - .any(|raindex| raindex.address == ob_id.raindex_address) + .any(|raindex| raindex.address == raindex_id.raindex_address) }); if already_recorded { continue; @@ -74,14 +74,14 @@ pub fn build_manifest( let previous_entry = previous_manifests .get(&runner_target.manifest_url) - .and_then(|manifest| manifest.find(ob_id.chain_id, ob_id.raindex_address)) + .and_then(|manifest| manifest.find(raindex_id.chain_id, raindex_id.raindex_address)) .cloned(); if let Some(raindex) = previous_entry { push_entry( &mut per_network, runner_target.network_key.clone(), - ob_id.chain_id, + raindex_id.chain_id, raindex, )?; } @@ -174,7 +174,7 @@ mod tests { manifest_url: Url::parse("https://example.com/manifest.yaml").unwrap(), network_key: network_key.to_string(), inputs: SyncInputs { - ob_id: RaindexIdentifier { + raindex_id: RaindexIdentifier { chain_id, raindex_address: address, }, @@ -199,7 +199,7 @@ mod tests { ( TargetSuccess { outcome: SyncOutcome { - ob_id: target.clone(), + raindex_id: target.clone(), start_block: 0, target_block: 1234, fetched_logs: 10, @@ -418,15 +418,15 @@ mod tests { #[test] fn build_manifest_errors_on_missing_target() { - let ob_id = RaindexIdentifier { + let raindex_id = RaindexIdentifier { chain_id: 42161, raindex_address: address!("0x0000000000000000000000000000000000000aa1"), }; let lookup: HashMap = HashMap::new(); - let (success, export) = sample_success(&ob_id, "dump.sql.gz"); + let (success, export) = sample_success(&raindex_id, "dump.sql.gz"); let successes = vec![success]; let mut exports = HashMap::new(); - exports.insert(ob_id.clone(), Some(export)); + exports.insert(raindex_id.clone(), Some(export)); let base_url = Url::parse("https://releases.example.com").unwrap(); @@ -437,8 +437,8 @@ mod tests { chain_id, raindex_address, } => { - assert_eq!(chain_id, ob_id.chain_id); - assert_eq!(raindex_address, ob_id.raindex_address); + assert_eq!(chain_id, raindex_id.chain_id); + assert_eq!(raindex_address, raindex_id.raindex_address); } other => panic!("unexpected error variant: {other:?}"), } @@ -446,22 +446,22 @@ mod tests { #[test] fn build_manifest_errors_on_invalid_end_block_hash() { - let ob_id = RaindexIdentifier { + let raindex_id = RaindexIdentifier { chain_id: 42161, raindex_address: address!("0x0000000000000000000000000000000000000dd1"), }; let mut lookup: HashMap = HashMap::new(); lookup.insert( - ob_id.clone(), - sample_runner_target("arbitrum", ob_id.chain_id, ob_id.raindex_address), + raindex_id.clone(), + sample_runner_target("arbitrum", raindex_id.chain_id, raindex_id.raindex_address), ); - let (success, mut export) = sample_success(&ob_id, "dump.sql.gz"); + let (success, mut export) = sample_success(&raindex_id, "dump.sql.gz"); export.end_block_hash = "not-a-hex-string".to_string(); let successes = vec![success]; let mut exports = HashMap::new(); - exports.insert(ob_id.clone(), Some(export)); + exports.insert(raindex_id.clone(), Some(export)); let base_url = Url::parse("https://releases.example.com").unwrap(); let err = build_manifest(&successes, &exports, &lookup, &base_url, &HashMap::new()) @@ -635,19 +635,19 @@ mod tests { #[tokio::test] async fn write_manifest_to_path_writes_yaml() { - let ob_id = RaindexIdentifier { + let raindex_id = RaindexIdentifier { chain_id: 42161, raindex_address: address!("0x0000000000000000000000000000000000000aa1"), }; let mut lookup: HashMap = HashMap::new(); lookup.insert( - ob_id.clone(), - sample_runner_target("anvil", ob_id.chain_id, ob_id.raindex_address), + raindex_id.clone(), + sample_runner_target("anvil", raindex_id.chain_id, raindex_id.raindex_address), ); - let (success, export) = sample_success(&ob_id, "dump.sql.gz"); + let (success, export) = sample_success(&raindex_id, "dump.sql.gz"); let successes = vec![success]; let mut exports = HashMap::new(); - exports.insert(ob_id.clone(), Some(export)); + exports.insert(raindex_id.clone(), Some(export)); let base_url = Url::parse("https://releases.example.com").unwrap(); let manifest = build_manifest(&successes, &exports, &lookup, &base_url, &HashMap::new()) diff --git a/crates/cli/src/commands/local_db/pipeline/runner/mod.rs b/crates/cli/src/commands/local_db/pipeline/runner/mod.rs index 207dab0a82..40090fb7e0 100644 --- a/crates/cli/src/commands/local_db/pipeline/runner/mod.rs +++ b/crates/cli/src/commands/local_db/pipeline/runner/mod.rs @@ -66,7 +66,7 @@ where let mut target_lookup = HashMap::with_capacity(targets.len()); for target in &targets { - target_lookup.insert(target.inputs.ob_id.clone(), target.clone()); + target_lookup.insert(target.inputs.raindex_id.clone(), target.clone()); } let manifest_output_path = out_root.join("manifest.yaml"); @@ -93,7 +93,7 @@ where let report = RunReport { successes: Vec::new(), failures: vec![TargetFailure { - ob_id: RaindexIdentifier::new(0, Address::ZERO), + raindex_id: RaindexIdentifier::new(0, Address::ZERO), raindex_key: None, stage: TargetStage::ManifestFetch, error, @@ -134,16 +134,16 @@ where while let Some(result) = tasks.join_next().await { match result { Ok(Ok((success, export))) => { - exports.insert(success.outcome.ob_id.clone(), export); + exports.insert(success.outcome.raindex_id.clone(), export); successes.push(success); } Ok(Err(failure)) => { error!( - address = ?failure.ob_id.raindex_address, + address = ?failure.raindex_id.raindex_address, stage = ?failure.stage, error = %failure.error, "producer job failed (chain_id={:?})", - failure.ob_id.chain_id, + failure.raindex_id.chain_id, ); failures.push(failure); } @@ -154,7 +154,7 @@ where "producer job panicked or was cancelled before completion" ); failures.push(TargetFailure { - ob_id: RaindexIdentifier::new(0, Address::ZERO), + raindex_id: RaindexIdentifier::new(0, Address::ZERO), raindex_key: None, stage: TargetStage::EngineRun, error, @@ -251,8 +251,8 @@ impl ProducerRunReport { &self.failures } - pub fn export_for(&self, ob_id: &RaindexIdentifier) -> Option<&ExportMetadata> { - self.exports.get(ob_id)?.as_ref() + pub fn export_for(&self, raindex_id: &RaindexIdentifier) -> Option<&ExportMetadata> { + self.exports.get(raindex_id)?.as_ref() } } @@ -277,10 +277,10 @@ where inputs, } = target; - let ob_id = inputs.ob_id.clone(); + let raindex_id = inputs.raindex_id.clone(); let ob_key_for_failure = raindex_key.clone(); let mk_failure = move |stage: TargetStage, error: LocalDbError| TargetFailure { - ob_id: ob_id.clone(), + raindex_id: raindex_id.clone(), raindex_key: Some(ob_key_for_failure.clone()), stage, error, @@ -328,9 +328,9 @@ where } fn db_path_for_target(out_root: &Path, target: &RunnerTarget) -> Result { - let chain_folder = out_root.join(target.inputs.ob_id.chain_id.to_string()); + let chain_folder = out_root.join(target.inputs.raindex_id.chain_id.to_string()); std::fs::create_dir_all(&chain_folder)?; - let filename = format!("{}.db", target.inputs.ob_id.raindex_address); + let filename = format!("{}.db", target.inputs.raindex_id.raindex_address); Ok(chain_folder.join(filename)) } @@ -538,14 +538,14 @@ mod tests { self.ensure_tables(db).await?; // Seed a raw event to force export_data_only to return Some, but skip watermark to trigger export failure. - let ob_id = &config.ob_id; - let raindex_address = encode_prefixed(ob_id.raindex_address); + let raindex_id = &config.raindex_id; + let raindex_address = encode_prefixed(raindex_id.raindex_address); let mut batch = SqlStatementBatch::new(); batch.add(SqlStatement::new(format!( "INSERT INTO raw_events (chain_id, raindex_address, transaction_hash, log_index, block_number, block_timestamp, address, topics, data, raw_json) \ VALUES ({}, '{}', '0xseedtx', 0, {}, 1_700_000_000, '{}', '[]', '0x00', '{{}}') \ ON CONFLICT(chain_id, raindex_address, transaction_hash, log_index) DO NOTHING;", - ob_id.chain_id, raindex_address, config.latest_block, raindex_address + raindex_id.chain_id, raindex_address, config.latest_block, raindex_address ))); db.execute_batch(&batch.ensure_transaction()).await?; @@ -699,15 +699,15 @@ mod tests { self.ensure_tables(db).await?; if self.seed_export { - let ob_id = &config.ob_id; - let raindex_address = encode_prefixed(ob_id.raindex_address); + let raindex_id = &config.raindex_id; + let raindex_address = encode_prefixed(raindex_id.raindex_address); let mut batch = SqlStatementBatch::new(); batch.add(SqlStatement::new(format!( "INSERT INTO raw_events (chain_id, raindex_address, transaction_hash, log_index, block_number, block_timestamp, address, topics, data, raw_json) \ VALUES ({}, '{}', '0xseedtx', 0, {}, 1_700_000_000, '{}', '[]', '0x00', '{{}}') \ ON CONFLICT(chain_id, raindex_address, transaction_hash, log_index) DO NOTHING;", - ob_id.chain_id, raindex_address, config.latest_block, raindex_address + raindex_id.chain_id, raindex_address, config.latest_block, raindex_address ))); batch.add(SqlStatement::new(format!( "INSERT INTO target_watermarks (chain_id, raindex_address, last_block, last_hash, updated_at) \ @@ -716,7 +716,7 @@ mod tests { SET last_block = excluded.last_block, \ last_hash = excluded.last_hash, \ updated_at = excluded.updated_at;", - ob_id.chain_id, raindex_address, config.latest_block + raindex_id.chain_id, raindex_address, config.latest_block ))); db.execute_batch(&batch.ensure_transaction()).await?; @@ -1357,14 +1357,14 @@ raindexes: let success = &report.successes[0]; assert_eq!(success.outcome.start_block, 0); assert_eq!( - success.outcome.ob_id.raindex_address, + success.outcome.raindex_id.raindex_address, address!("00000000000000000000000000000000000000a1") ); let failure = &report.failures[0]; - assert_eq!(failure.ob_id.chain_id, 42161); + assert_eq!(failure.raindex_id.chain_id, 42161); assert_eq!( - failure.ob_id.raindex_address, + failure.raindex_id.raindex_address, address!("00000000000000000000000000000000000000b2") ); assert_eq!(failure.raindex_key.as_deref(), Some("fail")); @@ -1403,7 +1403,7 @@ raindexes: assert_eq!(report.successes.len(), 0); assert_eq!(report.failures.len(), 1); let failure = &report.failures[0]; - assert_eq!(failure.ob_id.chain_id, 0); + assert_eq!(failure.raindex_id.chain_id, 0); assert!(failure.raindex_key.is_none()); assert!(matches!(failure.error, LocalDbError::TaskJoin(_))); } @@ -1434,7 +1434,7 @@ raindexes: let success_addresses: Vec
= report .successes .iter() - .map(|outcome| outcome.outcome.ob_id.raindex_address) + .map(|outcome| outcome.outcome.raindex_id.raindex_address) .collect(); assert_eq!( success_addresses, @@ -1444,7 +1444,7 @@ raindexes: let mut custom_failure = None; let mut join_failure = None; for failure in &report.failures { - match (failure.ob_id.chain_id, failure.ob_id.raindex_address) { + match (failure.raindex_id.chain_id, failure.raindex_id.raindex_address) { (42161, addr) if addr == address!("00000000000000000000000000000000000000b2") => { custom_failure = Some(failure); } @@ -1589,9 +1589,9 @@ raindexes: assert!(report.successes.is_empty()); assert_eq!(report.failures.len(), 1); let failure = &report.failures[0]; - assert_eq!(failure.ob_id.chain_id, 42161); + assert_eq!(failure.raindex_id.chain_id, 42161); assert_eq!( - failure.ob_id.raindex_address, + failure.raindex_id.raindex_address, address!("00000000000000000000000000000000000000a1") ); assert_eq!(failure.raindex_key.as_deref(), Some("ok")); @@ -1642,9 +1642,9 @@ raindexes: assert!(report.successes.is_empty()); assert_eq!(report.failures.len(), 1); let failure = &report.failures[0]; - assert_eq!(failure.ob_id.chain_id, 42161); + assert_eq!(failure.raindex_id.chain_id, 42161); assert_eq!( - failure.ob_id.raindex_address, + failure.raindex_id.raindex_address, address!("00000000000000000000000000000000000000a1") ); assert_eq!(failure.raindex_key.as_deref(), Some("ok")); @@ -1705,7 +1705,7 @@ raindexes: let failure = &report.failures[0]; assert_eq!(failure.stage, TargetStage::Export); assert_eq!( - failure.ob_id.raindex_address, + failure.raindex_id.raindex_address, address!("00000000000000000000000000000000000000a1") ); } @@ -1755,11 +1755,11 @@ raindexes: panic!("expected success, got failures: {:?}", report.failures); } let outcome = &report.successes[0]; - assert_eq!(outcome.outcome.ob_id.chain_id, 42161); + assert_eq!(outcome.outcome.raindex_id.chain_id, 42161); assert_eq!(outcome.outcome.start_block, 0); assert!( - report.export_for(&outcome.outcome.ob_id).is_none(), + report.export_for(&outcome.outcome.raindex_id).is_none(), "stub environment should not emit dumps" ); } @@ -1787,7 +1787,7 @@ raindexes: let outcome = &report.successes[0]; let metadata = report - .export_for(&outcome.outcome.ob_id) + .export_for(&outcome.outcome.raindex_id) .expect("export metadata to be present"); assert!( metadata.dump_path.exists(), @@ -1800,7 +1800,7 @@ raindexes: .expect("dump file name"); let expected_file = format!( "{}-{}.sql.gz", - outcome.outcome.ob_id.chain_id, outcome.outcome.ob_id.raindex_address + outcome.outcome.raindex_id.chain_id, outcome.outcome.raindex_id.raindex_address ); assert_eq!(file_name, expected_file); assert_eq!(metadata.end_block, outcome.outcome.target_block); @@ -1973,7 +1973,7 @@ raindexes: "{}.db", targets[0] .inputs - .ob_id + .raindex_id .raindex_address .to_string() .to_lowercase() diff --git a/crates/cli/src/commands/local_db/pipeline/status.rs b/crates/cli/src/commands/local_db/pipeline/status.rs index b20d876ed9..1315ad1946 100644 --- a/crates/cli/src/commands/local_db/pipeline/status.rs +++ b/crates/cli/src/commands/local_db/pipeline/status.rs @@ -25,15 +25,15 @@ impl From for DebugStatus { pub struct ProducerStatusBus { debug: DebugStatus, raindex_key: String, - ob_id: RaindexIdentifier, + raindex_id: RaindexIdentifier, } impl ProducerStatusBus { - pub fn new(debug: DebugStatus, raindex_key: String, ob_id: RaindexIdentifier) -> Self { + pub fn new(debug: DebugStatus, raindex_key: String, raindex_id: RaindexIdentifier) -> Self { Self { debug, raindex_key, - ob_id, + raindex_id, } } } @@ -43,7 +43,7 @@ impl Default for ProducerStatusBus { Self { debug: DebugStatus::Disabled, raindex_key: "".to_string(), - ob_id: RaindexIdentifier::new(0, Default::default()), + raindex_id: RaindexIdentifier::new(0, Default::default()), } } } @@ -54,8 +54,8 @@ impl StatusBus for ProducerStatusBus { if self.debug == DebugStatus::Enabled { info!( target: "local_db_status", - chain_id = self.ob_id.chain_id, - raindex = %self.ob_id.raindex_address, + chain_id = self.raindex_id.chain_id, + raindex = %self.raindex_id.raindex_address, raindex_key = %self.raindex_key, "{}", phase.to_message() diff --git a/crates/common/src/raindex_client/local_db/orders.rs b/crates/common/src/raindex_client/local_db/orders.rs index d35f1df4ff..2279343ef4 100644 --- a/crates/common/src/raindex_client/local_db/orders.rs +++ b/crates/common/src/raindex_client/local_db/orders.rs @@ -139,12 +139,12 @@ impl OrdersDataSource for LocalDbOrders<'_> { async fn get_by_hash( &self, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, order_hash: &B256, ) -> Result, RaindexError> { let fetch_args = FetchOrdersArgs { - chain_ids: vec![ob_id.chain_id], - raindex_addresses: vec![ob_id.raindex_address], + chain_ids: vec![raindex_id.chain_id], + raindex_addresses: vec![raindex_id.raindex_address], order_hash: Some(*order_hash), ..FetchOrdersArgs::default() }; @@ -181,30 +181,30 @@ impl OrdersDataSource for LocalDbOrders<'_> { async fn trades_list( &self, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, order_hash: &B256, start_timestamp: Option, end_timestamp: Option, _page: Option, ) -> Result, RaindexError> { let local_trades = - fetch_order_trades(self.db, ob_id, *order_hash, start_timestamp, end_timestamp).await?; + fetch_order_trades(self.db, raindex_id, *order_hash, start_timestamp, end_timestamp).await?; local_trades .into_iter() - .map(|trade| RaindexTrade::try_from_local_db_trade(ob_id.chain_id, trade)) + .map(|trade| RaindexTrade::try_from_local_db_trade(raindex_id.chain_id, trade)) .collect() } async fn trades_count( &self, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, order_hash: &B256, start_timestamp: Option, end_timestamp: Option, ) -> Result { Ok( - fetch_order_trades_count(self.db, ob_id, *order_hash, start_timestamp, end_timestamp) + fetch_order_trades_count(self.db, raindex_id, *order_hash, start_timestamp, end_timestamp) .await?, ) } diff --git a/crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs b/crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs index 3cd9e4716d..cea7adec13 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs @@ -39,10 +39,10 @@ impl ClientBootstrapAdapter { async fn is_fresh_db( self, db: &E, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, ) -> Result { let rows: Vec = - db.query_json(&fetch_target_watermark_stmt(ob_id)).await?; + db.query_json(&fetch_target_watermark_stmt(raindex_id)).await?; Ok(rows.is_empty()) } } @@ -55,10 +55,10 @@ impl BootstrapPipeline for ClientBootstrapAdapter { { let BootstrapState { last_synced_block, .. - } = self.inspect_state(db, &config.ob_id).await?; + } = self.inspect_state(db, &config.raindex_id).await?; if let Some(dump_stmt) = config.dump_stmt.as_ref() { - if self.is_fresh_db(db, &config.ob_id).await? { + if self.is_fresh_db(db, &config.raindex_id).await? { db.execute_batch(dump_stmt).await?; return Ok(()); } @@ -70,7 +70,7 @@ impl BootstrapPipeline for ClientBootstrapAdapter { ) { Ok(_) => {} Err(_) => { - self.clear_raindex_data(db, &config.ob_id).await?; + self.clear_raindex_data(db, &config.raindex_id).await?; db.execute_batch(dump_stmt).await?; } } @@ -236,7 +236,7 @@ mod tests { fn cfg_with_dump(latest_block: u64) -> BootstrapConfig { BootstrapConfig { - ob_id: sample_ob_id(), + raindex_id: sample_ob_id(), dump_stmt: Some(SqlStatementBatch::from(vec![SqlStatement::new( "--dump-sql", )])), @@ -463,7 +463,7 @@ mod tests { let tables_json = required_tables_json(); let dump_stmt = SqlStatement::new("--dump-sql"); let cfg = BootstrapConfig { - ob_id: sample_ob_id(), + raindex_id: sample_ob_id(), dump_stmt: Some(SqlStatementBatch::from(vec![dump_stmt.clone()])), latest_block: 100, block_number_threshold: TEST_BLOCK_NUMBER_THRESHOLD, @@ -472,7 +472,7 @@ mod tests { let db = MockDb::default() .with_json(&fetch_tables_stmt(), tables_json) - .with_json(&fetch_target_watermark_stmt(&cfg.ob_id), json!([])) + .with_json(&fetch_target_watermark_stmt(&cfg.raindex_id), json!([])) .with_text(&dump_stmt, "ok"); adapter.engine_run(&db, &cfg).await.unwrap(); @@ -488,7 +488,7 @@ mod tests { let latest = last_synced + u64::from(TEST_BLOCK_NUMBER_THRESHOLD) + 1; let dump_stmt = SqlStatement::new("--dump-sql"); let cfg = BootstrapConfig { - ob_id: sample_ob_id(), + raindex_id: sample_ob_id(), dump_stmt: Some(SqlStatementBatch::from(vec![dump_stmt.clone()])), latest_block: latest, block_number_threshold: TEST_BLOCK_NUMBER_THRESHOLD, @@ -499,7 +499,7 @@ mod tests { let mut db = MockDb::default() .with_json(&fetch_tables_stmt(), tables_json) .with_json( - &fetch_target_watermark_stmt(&cfg.ob_id), + &fetch_target_watermark_stmt(&cfg.raindex_id), json!([watermark_row(last_synced)]), ) .with_text(&dump_stmt, "dumped"); @@ -531,7 +531,7 @@ mod tests { let db = MockDb::default() .with_json(&fetch_tables_stmt(), tables_json) .with_json( - &fetch_target_watermark_stmt(&cfg.ob_id), + &fetch_target_watermark_stmt(&cfg.raindex_id), json!([watermark_row(last_synced)]), ); @@ -551,7 +551,7 @@ mod tests { let db = MockDb::default() .with_json(&fetch_tables_stmt(), tables_json) .with_json( - &fetch_target_watermark_stmt(&cfg.ob_id), + &fetch_target_watermark_stmt(&cfg.raindex_id), json!([watermark_row(last_synced)]), ); @@ -567,7 +567,7 @@ mod tests { let last_synced = 200_000u64; let latest = last_synced + u64::from(TEST_BLOCK_NUMBER_THRESHOLD) + 5; let cfg = BootstrapConfig { - ob_id: sample_ob_id(), + raindex_id: sample_ob_id(), dump_stmt: None, latest_block: latest, block_number_threshold: TEST_BLOCK_NUMBER_THRESHOLD, @@ -577,7 +577,7 @@ mod tests { let db = MockDb::default() .with_json(&fetch_tables_stmt(), tables_json) .with_json( - &fetch_target_watermark_stmt(&cfg.ob_id), + &fetch_target_watermark_stmt(&cfg.raindex_id), json!([watermark_row(last_synced)]), ); @@ -594,7 +594,7 @@ mod tests { let latest = last_synced + u64::from(TEST_BLOCK_NUMBER_THRESHOLD) + 42; let dump_stmt = SqlStatement::new("--dump-sql"); let cfg = BootstrapConfig { - ob_id: sample_ob_id(), + raindex_id: sample_ob_id(), dump_stmt: Some(SqlStatementBatch::from(vec![dump_stmt.clone()])), latest_block: latest, block_number_threshold: TEST_BLOCK_NUMBER_THRESHOLD, @@ -604,7 +604,7 @@ mod tests { let db = MockDb::default() .with_json(&fetch_tables_stmt(), tables_json) .with_json( - &fetch_target_watermark_stmt(&cfg.ob_id), + &fetch_target_watermark_stmt(&cfg.raindex_id), json!([watermark_row(last_synced)]), ); diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/environment.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/environment.rs index a76de8cf96..b90bb7c074 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/environment.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/environment.rs @@ -32,7 +32,7 @@ pub fn default_environment() -> RunnerEnvironment< DefaultEventsPipeline::with_regular_rpcs(target.inputs.metadata_rpcs.clone())?; let tokens = DefaultTokensPipeline::new(target.inputs.metadata_rpcs.clone())?; - let status_bus = ClientStatusBus::with_ob_id(target.inputs.ob_id.clone()); + let status_bus = ClientStatusBus::with_ob_id(target.inputs.raindex_id.clone()); Ok(EnginePipelines::new( ClientBootstrapAdapter::new(), @@ -63,7 +63,7 @@ pub fn default_environment() -> RunnerEnvironment< DefaultEventsPipeline::with_regular_rpcs(target.inputs.metadata_rpcs.clone())?; let tokens = DefaultTokensPipeline::new(target.inputs.metadata_rpcs.clone())?; - let status_bus = TracingStatusBus::with_ob_id(target.inputs.ob_id.clone()); + let status_bus = TracingStatusBus::with_ob_id(target.inputs.raindex_id.clone()); Ok(EnginePipelines::new( ClientBootstrapAdapter::new(), @@ -95,7 +95,7 @@ mod tests { network_key: "test-network".to_string(), manifest_url: Url::parse("https://manifests.example/client.yaml").unwrap(), inputs: SyncInputs { - ob_id: RaindexIdentifier { + raindex_id: RaindexIdentifier { chain_id: 1, raindex_address: address!("00000000000000000000000000000000000000c1"), }, diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs index 21b386417c..cfbf7a5a5f 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs @@ -190,7 +190,7 @@ where Ok(target) } Err(error) => Err(TargetFailure { - raindex_id: target.inputs.ob_id.clone(), + raindex_id: target.inputs.raindex_id.clone(), raindex_key: Some(target.raindex_key.clone()), stage: TargetStage::DumpDownload, error, @@ -230,7 +230,7 @@ where let futures = targets.into_iter().map(move |target| { let environment = environment.clone(); async move { - let raindex_id = target.inputs.ob_id.clone(); + let raindex_id = target.inputs.raindex_id.clone(); let engine = match environment.build_engine(&target) { Ok(engine) => engine.into_engine(), Err(error) => { @@ -1104,10 +1104,10 @@ raindexes: prepare_db_baseline(db); for target in targets { db.set_json_raw( - &fetch_target_watermark_stmt(&target.inputs.ob_id), + &fetch_target_watermark_stmt(&target.inputs.raindex_id), json!([]), ); - db.set_json_raw(&fetch_store_addresses_stmt(&target.inputs.ob_id), json!([])); + db.set_json_raw(&fetch_store_addresses_stmt(&target.inputs.raindex_id), json!([])); } } @@ -1849,11 +1849,11 @@ raindexes: assert!(report .failures .iter() - .any(|f| f.ob_id.raindex_address == RAINDEX_A)); + .any(|f| f.raindex_id.raindex_address == RAINDEX_A)); assert!(report .failures .iter() - .any(|f| f.ob_id.raindex_address == RAINDEX_B)); + .any(|f| f.raindex_id.raindex_address == RAINDEX_B)); } #[tokio::test] diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/native.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/native.rs index 1096d72eaa..b51c3f38a1 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/native.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/native.rs @@ -234,7 +234,7 @@ async fn run_network_loop( tracing::warn!( network = %network_key, chain_id, - raindex = %format!("{:#x}", failure.ob_id.raindex_address), + raindex = %format!("{:#x}", failure.raindex_id.raindex_address), stage = ?failure.stage, error = %failure.error, "sync target failed" @@ -344,7 +344,7 @@ mod tests { if should_fail { failures.fetch_add(1, Ordering::SeqCst); let failure = TargetFailure { - ob_id: RaindexIdentifier::new(1, Address::ZERO), + raindex_id: RaindexIdentifier::new(1, Address::ZERO), raindex_key: None, stage: TargetStage::EngineRun, error: LocalDbError::CustomError("runner failure".to_string()), diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/wasm.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/wasm.rs index c19eaa5172..ce791c3ce4 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/wasm.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/wasm.rs @@ -245,7 +245,7 @@ async fn run_network_loop( let first = &report.failures[0]; let msg = format!( "raindex {:#x} failed at {:?}: {}", - first.ob_id.raindex_address, + first.raindex_id.raindex_address, first.stage, first.error.to_readable_msg() ); @@ -360,7 +360,7 @@ mod wasm_tests { if should_fail { failures.set(failures.get() + 1); let failure = TargetFailure { - ob_id: RaindexIdentifier::new(1, Address::ZERO), + raindex_id: RaindexIdentifier::new(1, Address::ZERO), raindex_key: None, stage: TargetStage::EngineRun, error: LocalDbError::CustomError("runner failure".to_string()), diff --git a/crates/common/src/raindex_client/local_db/pipeline/status/mod.rs b/crates/common/src/raindex_client/local_db/pipeline/status/mod.rs index 6af276d692..51f36e0768 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/status/mod.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/status/mod.rs @@ -15,7 +15,7 @@ mod tests { use crate::raindex_client::local_db::{LocalDbStatus, RaindexSyncStatus, SchedulerState}; use alloy::primitives::address; - fn test_ob_id() -> RaindexIdentifier { + fn test_raindex_id() -> RaindexIdentifier { RaindexIdentifier::new(1, address!("0000000000000000000000000000000000001234")) } @@ -70,10 +70,10 @@ mod tests { #[test] fn raindex_sync_status_syncing_sets_correct_fields() { - let ob_id = test_ob_id(); - let status = RaindexSyncStatus::syncing(ob_id.clone(), SyncPhase::FetchingLatestBlock); + let raindex_id = test_raindex_id(); + let status = RaindexSyncStatus::syncing(raindex_id.clone(), SyncPhase::FetchingLatestBlock); - assert_eq!(status.ob_id, ob_id); + assert_eq!(status.raindex_id, raindex_id); assert_eq!(status.status, LocalDbStatus::Syncing); assert_eq!(status.scheduler_state, SchedulerState::Leader); assert_eq!( @@ -85,10 +85,10 @@ mod tests { #[test] fn raindex_sync_status_active_with_leader_sets_correct_fields() { - let ob_id = test_ob_id(); - let status = RaindexSyncStatus::active(ob_id.clone(), SchedulerState::Leader); + let raindex_id = test_raindex_id(); + let status = RaindexSyncStatus::active(raindex_id.clone(), SchedulerState::Leader); - assert_eq!(status.ob_id, ob_id); + assert_eq!(status.raindex_id, raindex_id); assert_eq!(status.status, LocalDbStatus::Active); assert_eq!(status.scheduler_state, SchedulerState::Leader); assert!(status.phase_message.is_none()); @@ -97,10 +97,10 @@ mod tests { #[test] fn raindex_sync_status_active_with_not_leader_sets_correct_fields() { - let ob_id = test_ob_id(); - let status = RaindexSyncStatus::active(ob_id.clone(), SchedulerState::NotLeader); + let raindex_id = test_raindex_id(); + let status = RaindexSyncStatus::active(raindex_id.clone(), SchedulerState::NotLeader); - assert_eq!(status.ob_id, ob_id); + assert_eq!(status.raindex_id, raindex_id); assert_eq!(status.status, LocalDbStatus::Active); assert_eq!(status.scheduler_state, SchedulerState::NotLeader); assert!(status.phase_message.is_none()); @@ -109,11 +109,11 @@ mod tests { #[test] fn raindex_sync_status_failure_sets_correct_fields() { - let ob_id = test_ob_id(); + let raindex_id = test_raindex_id(); let error_msg = "RPC connection failed".to_string(); - let status = RaindexSyncStatus::failure(ob_id.clone(), error_msg.clone()); + let status = RaindexSyncStatus::failure(raindex_id.clone(), error_msg.clone()); - assert_eq!(status.ob_id, ob_id); + assert_eq!(status.raindex_id, raindex_id); assert_eq!(status.status, LocalDbStatus::Failure); assert_eq!(status.scheduler_state, SchedulerState::Leader); assert!(status.phase_message.is_none()); @@ -122,16 +122,16 @@ mod tests { #[test] fn raindex_sync_status_new_with_all_fields() { - let ob_id = test_ob_id(); + let raindex_id = test_raindex_id(); let status = RaindexSyncStatus::new( - ob_id.clone(), + raindex_id.clone(), LocalDbStatus::Syncing, SchedulerState::Leader, Some("Custom phase".to_string()), Some("Custom error".to_string()), ); - assert_eq!(status.ob_id, ob_id); + assert_eq!(status.raindex_id, raindex_id); assert_eq!(status.status, LocalDbStatus::Syncing); assert_eq!(status.scheduler_state, SchedulerState::Leader); assert_eq!(status.phase_message, Some("Custom phase".to_string())); diff --git a/crates/common/src/raindex_client/local_db/pipeline/status/native.rs b/crates/common/src/raindex_client/local_db/pipeline/status/native.rs index 8cb21156c4..5ffbcd8cc4 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/status/native.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/status/native.rs @@ -3,28 +3,28 @@ use crate::local_db::{LocalDbError, RaindexIdentifier}; #[derive(Debug, Clone, Default)] pub struct TracingStatusBus { - ob_id: Option, + raindex_id: Option, raindex_key: Option, } impl TracingStatusBus { pub fn new() -> Self { Self { - ob_id: None, + raindex_id: None, raindex_key: None, } } - pub fn with_ob_id(ob_id: RaindexIdentifier) -> Self { + pub fn with_ob_id(raindex_id: RaindexIdentifier) -> Self { Self { - ob_id: Some(ob_id), + raindex_id: Some(raindex_id), raindex_key: None, } } - pub fn with_ob_id_and_key(ob_id: RaindexIdentifier, key: String) -> Self { + pub fn with_ob_id_and_key(raindex_id: RaindexIdentifier, key: String) -> Self { Self { - ob_id: Some(ob_id), + raindex_id: Some(raindex_id), raindex_key: Some(key), } } @@ -33,9 +33,9 @@ impl TracingStatusBus { #[async_trait::async_trait(?Send)] impl StatusBus for TracingStatusBus { async fn send(&self, phase: SyncPhase) -> Result<(), LocalDbError> { - let chain_id = self.ob_id.as_ref().map(|id| id.chain_id).unwrap_or(0); + let chain_id = self.raindex_id.as_ref().map(|id| id.chain_id).unwrap_or(0); let ob_addr = self - .ob_id + .raindex_id .as_ref() .map(|id| format!("{:#x}", id.raindex_address)) .unwrap_or_default(); @@ -66,8 +66,8 @@ mod tests { #[tokio::test] async fn tracing_status_bus_send_returns_ok() { - let ob_id = test_ob_id(); - let bus = TracingStatusBus::with_ob_id(ob_id); + let raindex_id = test_ob_id(); + let bus = TracingStatusBus::with_ob_id(raindex_id); let result = bus.send(SyncPhase::FetchingLatestBlock).await; assert!(result.is_ok()); } diff --git a/crates/common/src/raindex_client/local_db/pipeline/status/wasm.rs b/crates/common/src/raindex_client/local_db/pipeline/status/wasm.rs index 85024f4288..fc4703ac69 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/status/wasm.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/status/wasm.rs @@ -39,16 +39,16 @@ fn emit_to_callback(status: RaindexSyncStatus) { #[derive(Debug, Clone, Default)] pub struct ClientStatusBus { - ob_id: Option, + raindex_id: Option, } impl ClientStatusBus { pub fn new() -> Self { - Self { ob_id: None } + Self { raindex_id: None } } - pub fn with_ob_id(ob_id: RaindexIdentifier) -> Self { - Self { ob_id: Some(ob_id) } + pub fn with_ob_id(raindex_id: RaindexIdentifier) -> Self { + Self { raindex_id: Some(raindex_id) } } fn emit(&self, status: RaindexSyncStatus) { @@ -56,20 +56,20 @@ impl ClientStatusBus { } pub fn emit_active(&self) { - let Some(ob_id) = &self.ob_id else { + let Some(raindex_id) = &self.raindex_id else { return; }; let scheduler_state = get_scheduler_state(); - self.emit(RaindexSyncStatus::active(ob_id.clone(), scheduler_state)); + self.emit(RaindexSyncStatus::active(raindex_id.clone(), scheduler_state)); } pub fn emit_failure(&self, error: String) { - let Some(ob_id) = &self.ob_id else { + let Some(raindex_id) = &self.raindex_id else { return; }; - self.emit(RaindexSyncStatus::failure(ob_id.clone(), error)); + self.emit(RaindexSyncStatus::failure(raindex_id.clone(), error)); } } @@ -81,11 +81,11 @@ impl StatusBus for ClientStatusBus { return Ok(()); } - let Some(ob_id) = &self.ob_id else { + let Some(raindex_id) = &self.raindex_id else { return Ok(()); }; - let status = RaindexSyncStatus::syncing(ob_id.clone(), phase); + let status = RaindexSyncStatus::syncing(raindex_id.clone(), phase); self.emit(status); Ok(()) @@ -107,14 +107,14 @@ mod tests { #[test] fn client_status_bus_default_has_no_ob_id() { let bus = ClientStatusBus::new(); - assert!(bus.ob_id.is_none()); + assert!(bus.raindex_id.is_none()); } #[test] fn client_status_bus_with_ob_id_stores_identifier() { - let ob_id = test_ob_id(); - let bus = ClientStatusBus::with_ob_id(ob_id.clone()); - assert_eq!(bus.ob_id, Some(ob_id)); + let raindex_id = test_ob_id(); + let bus = ClientStatusBus::with_ob_id(raindex_id.clone()); + assert_eq!(bus.raindex_id, Some(raindex_id)); } #[tokio::test] @@ -126,9 +126,9 @@ mod tests { #[tokio::test] async fn send_skips_when_not_leader() { - let ob_id = test_ob_id(); + let raindex_id = test_ob_id(); set_scheduler_state(SchedulerState::NotLeader); - let bus = ClientStatusBus::with_ob_id(ob_id); + let bus = ClientStatusBus::with_ob_id(raindex_id); let result = bus.send(SyncPhase::FetchingLatestBlock).await; assert!(result.is_ok()); set_scheduler_state(SchedulerState::Leader); @@ -137,8 +137,8 @@ mod tests { #[tokio::test] async fn send_returns_ok_when_leader_with_ob_id() { set_scheduler_state(SchedulerState::Leader); - let ob_id = test_ob_id(); - let bus = ClientStatusBus::with_ob_id(ob_id); + let raindex_id = test_ob_id(); + let bus = ClientStatusBus::with_ob_id(raindex_id); let result = bus.send(SyncPhase::FetchingLatestBlock).await; assert!(result.is_ok()); } @@ -158,15 +158,15 @@ mod tests { #[test] fn emit_active_with_ob_id_does_not_panic() { set_scheduler_state(SchedulerState::Leader); - let ob_id = test_ob_id(); - let bus = ClientStatusBus::with_ob_id(ob_id); + let raindex_id = test_ob_id(); + let bus = ClientStatusBus::with_ob_id(raindex_id); bus.emit_active(); } #[test] fn emit_failure_with_ob_id_does_not_panic() { - let ob_id = test_ob_id(); - let bus = ClientStatusBus::with_ob_id(ob_id); + let raindex_id = test_ob_id(); + let bus = ClientStatusBus::with_ob_id(raindex_id); bus.emit_failure("test error".to_string()); } @@ -225,8 +225,8 @@ mod wasm_tests { set_status_callback(Some(callback)); set_scheduler_state(SchedulerState::Leader); - let ob_id = test_ob_id(); - let bus = ClientStatusBus::with_ob_id(ob_id.clone()); + let raindex_id = test_ob_id(); + let bus = ClientStatusBus::with_ob_id(raindex_id.clone()); bus.send(SyncPhase::FetchingLatestBlock).await.unwrap(); set_status_callback(None); @@ -235,7 +235,7 @@ mod wasm_tests { assert_eq!(emissions.len(), 1, "expected exactly one emission"); let emitted = &emissions[0]; - assert_eq!(emitted.ob_id, ob_id); + assert_eq!(emitted.raindex_id, raindex_id); assert_eq!(emitted.status, LocalDbStatus::Syncing); assert_eq!(emitted.scheduler_state, SchedulerState::Leader); assert_eq!( @@ -252,8 +252,8 @@ mod wasm_tests { set_status_callback(Some(callback)); set_scheduler_state(SchedulerState::NotLeader); - let ob_id = test_ob_id(); - let bus = ClientStatusBus::with_ob_id(ob_id); + let raindex_id = test_ob_id(); + let bus = ClientStatusBus::with_ob_id(raindex_id); bus.send(SyncPhase::FetchingLatestBlock).await.unwrap(); set_status_callback(None); diff --git a/crates/common/src/raindex_client/local_db/query/fetch_erc20_tokens_by_addresses.rs b/crates/common/src/raindex_client/local_db/query/fetch_erc20_tokens_by_addresses.rs index 7a42d7bd1f..4ecc96a5e7 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_erc20_tokens_by_addresses.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_erc20_tokens_by_addresses.rs @@ -5,10 +5,10 @@ use alloy::primitives::Address; pub async fn fetch_erc20_tokens_by_addresses( exec: &E, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, addresses: &[Address], ) -> Result, LocalDbQueryError> { - if let Some(stmt) = build_fetch_stmt(ob_id, addresses)? { + if let Some(stmt) = build_fetch_stmt(raindex_id, addresses)? { exec.query_json(&stmt).await } else { Ok(vec![]) diff --git a/crates/common/src/raindex_client/local_db/query/fetch_last_synced_block.rs b/crates/common/src/raindex_client/local_db/query/fetch_last_synced_block.rs index 2504d28075..4ab8166bb2 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_last_synced_block.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_last_synced_block.rs @@ -6,9 +6,9 @@ use crate::local_db::RaindexIdentifier; pub async fn fetch_last_synced_block( exec: &E, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, ) -> Result, LocalDbQueryError> { - exec.query_json(&fetch_last_synced_block_stmt(ob_id)).await + exec.query_json(&fetch_last_synced_block_stmt(raindex_id)).await } #[cfg(target_family = "wasm")] diff --git a/crates/common/src/raindex_client/local_db/query/fetch_order_trades.rs b/crates/common/src/raindex_client/local_db/query/fetch_order_trades.rs index e868080221..f13eb30c50 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_order_trades.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_order_trades.rs @@ -7,12 +7,12 @@ use alloy::primitives::B256; pub async fn fetch_order_trades( exec: &E, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, order_hash: B256, start_timestamp: Option, end_timestamp: Option, ) -> Result, LocalDbQueryError> { - let stmt = build_fetch_order_trades_stmt(ob_id, order_hash, start_timestamp, end_timestamp)?; + let stmt = build_fetch_order_trades_stmt(raindex_id, order_hash, start_timestamp, end_timestamp)?; exec.query_json(&stmt).await } diff --git a/crates/common/src/raindex_client/local_db/query/fetch_order_trades_count.rs b/crates/common/src/raindex_client/local_db/query/fetch_order_trades_count.rs index 7ee5dc9a3c..0587188a2a 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_order_trades_count.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_order_trades_count.rs @@ -8,12 +8,12 @@ use crate::local_db::RaindexIdentifier; pub async fn fetch_order_trades_count( exec: &E, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, order_hash: B256, start_timestamp: Option, end_timestamp: Option, ) -> Result { - let stmt = build_fetch_trade_count_stmt(ob_id, order_hash, start_timestamp, end_timestamp)?; + let stmt = build_fetch_trade_count_stmt(raindex_id, order_hash, start_timestamp, end_timestamp)?; let rows: Vec = exec.query_json(&stmt).await?; Ok(extract_trade_count(&rows)) } diff --git a/crates/common/src/raindex_client/local_db/query/fetch_order_vaults_volume.rs b/crates/common/src/raindex_client/local_db/query/fetch_order_vaults_volume.rs index cfcef3325a..7a0568a5a7 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_order_vaults_volume.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_order_vaults_volume.rs @@ -7,13 +7,13 @@ use alloy::primitives::B256; pub async fn fetch_order_vaults_volume( exec: &E, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, order_hash: B256, start_timestamp: Option, end_timestamp: Option, ) -> Result, LocalDbQueryError> { let stmt = - build_fetch_order_vaults_volume_stmt(ob_id, order_hash, start_timestamp, end_timestamp)?; + build_fetch_order_vaults_volume_stmt(raindex_id, order_hash, start_timestamp, end_timestamp)?; exec.query_json(&stmt).await } diff --git a/crates/common/src/raindex_client/local_db/query/fetch_store_addresses.rs b/crates/common/src/raindex_client/local_db/query/fetch_store_addresses.rs index aac6249674..f013bf2476 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_store_addresses.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_store_addresses.rs @@ -4,9 +4,9 @@ use crate::local_db::RaindexIdentifier; pub async fn fetch_store_addresses( exec: &E, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, ) -> Result, LocalDbQueryError> { - exec.query_json(&fetch_store_addresses_stmt(ob_id)).await + exec.query_json(&fetch_store_addresses_stmt(raindex_id)).await } #[cfg(all(test, target_family = "wasm"))] diff --git a/crates/common/src/raindex_client/local_db/query/fetch_transaction_by_hash.rs b/crates/common/src/raindex_client/local_db/query/fetch_transaction_by_hash.rs index 726cbad3bd..3c55821945 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_transaction_by_hash.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_transaction_by_hash.rs @@ -7,10 +7,10 @@ use alloy::primitives::B256; pub async fn fetch_transaction_by_hash( exec: &E, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, tx_hash: B256, ) -> Result, LocalDbQueryError> { - let stmt = build_fetch_transaction_by_hash_stmt(ob_id, tx_hash); + let stmt = build_fetch_transaction_by_hash_stmt(raindex_id, tx_hash); exec.query_json(&stmt).await } diff --git a/crates/common/src/raindex_client/local_db/query/fetch_vault_balance_changes.rs b/crates/common/src/raindex_client/local_db/query/fetch_vault_balance_changes.rs index fe416409d3..88b46ef626 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_vault_balance_changes.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_vault_balance_changes.rs @@ -9,7 +9,7 @@ use alloy::primitives::{Address, U256}; pub async fn fetch_vault_balance_changes( exec: &E, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, vault_id: U256, token: Address, owner: Address, @@ -18,7 +18,7 @@ pub async fn fetch_vault_balance_changes( let filter_kinds: Option> = filter_types.map(|filters| filters.iter().map(|f| f.to_kind()).collect()); let stmt = - build_fetch_balance_changes_stmt(ob_id, vault_id, token, owner, filter_kinds.as_deref())?; + build_fetch_balance_changes_stmt(raindex_id, vault_id, token, owner, filter_kinds.as_deref())?; exec.query_json(&stmt).await } diff --git a/crates/common/src/raindex_client/local_db/query/update_last_synced_block.rs b/crates/common/src/raindex_client/local_db/query/update_last_synced_block.rs index 0a50a92e9f..a2b0a6a119 100644 --- a/crates/common/src/raindex_client/local_db/query/update_last_synced_block.rs +++ b/crates/common/src/raindex_client/local_db/query/update_last_synced_block.rs @@ -4,10 +4,10 @@ use crate::local_db::RaindexIdentifier; pub async fn update_last_synced_block( exec: &E, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, block_number: u64, ) -> Result<(), LocalDbQueryError> { - let stmt = build_update_last_synced_block_stmt(ob_id, block_number); + let stmt = build_update_last_synced_block_stmt(raindex_id, block_number); exec.query_text(&stmt).await.map(|_| ()) } diff --git a/crates/common/src/raindex_client/local_db/status.rs b/crates/common/src/raindex_client/local_db/status.rs index ed6f8149db..717c7ae3f5 100644 --- a/crates/common/src/raindex_client/local_db/status.rs +++ b/crates/common/src/raindex_client/local_db/status.rs @@ -24,7 +24,7 @@ impl_wasm_traits!(SchedulerState); #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Tsify)] #[serde(rename_all = "camelCase")] pub struct RaindexSyncStatus { - pub ob_id: RaindexIdentifier, + pub raindex_id: RaindexIdentifier, pub status: LocalDbStatus, pub scheduler_state: SchedulerState, #[serde(skip_serializing_if = "Option::is_none")] @@ -36,14 +36,14 @@ impl_wasm_traits!(RaindexSyncStatus); impl RaindexSyncStatus { pub fn new( - ob_id: RaindexIdentifier, + raindex_id: RaindexIdentifier, status: LocalDbStatus, scheduler_state: SchedulerState, phase_message: Option, error: Option, ) -> Self { Self { - ob_id, + raindex_id, status, scheduler_state, phase_message, @@ -51,9 +51,9 @@ impl RaindexSyncStatus { } } - pub fn syncing(ob_id: RaindexIdentifier, phase: SyncPhase) -> Self { + pub fn syncing(raindex_id: RaindexIdentifier, phase: SyncPhase) -> Self { Self::new( - ob_id, + raindex_id, LocalDbStatus::Syncing, SchedulerState::Leader, Some(phase.to_message().to_string()), @@ -61,13 +61,13 @@ impl RaindexSyncStatus { ) } - pub fn active(ob_id: RaindexIdentifier, scheduler_state: SchedulerState) -> Self { - Self::new(ob_id, LocalDbStatus::Active, scheduler_state, None, None) + pub fn active(raindex_id: RaindexIdentifier, scheduler_state: SchedulerState) -> Self { + Self::new(raindex_id, LocalDbStatus::Active, scheduler_state, None, None) } - pub fn failure(ob_id: RaindexIdentifier, error: String) -> Self { + pub fn failure(raindex_id: RaindexIdentifier, error: String) -> Self { Self::new( - ob_id, + raindex_id, LocalDbStatus::Failure, SchedulerState::Leader, None, @@ -161,26 +161,26 @@ mod tests { use crate::local_db::pipeline::SyncPhase; use alloy::primitives::address; - let ob_id = crate::local_db::RaindexIdentifier::new( + let raindex_id = crate::local_db::RaindexIdentifier::new( 42161, address!("0000000000000000000000000000000000001234"), ); - let status = RaindexSyncStatus::syncing(ob_id, SyncPhase::FetchingLatestBlock); + let status = RaindexSyncStatus::syncing(raindex_id, SyncPhase::FetchingLatestBlock); let json = serde_json::to_string(&status).unwrap(); assert!( - json.contains("\"obId\":{"), - "expected obId as nested object in JSON: {}", + json.contains("\"raindexId\":{"), + "expected raindexId as nested object in JSON: {}", json ); assert!( json.contains("\"chainId\":42161"), - "expected chainId in obId in JSON: {}", + "expected chainId in raindexId in JSON: {}", json ); assert!( json.contains("\"raindexAddress\":"), - "expected raindexAddress in obId in JSON: {}", + "expected raindexAddress in raindexId in JSON: {}", json ); assert!( @@ -303,7 +303,7 @@ mod tests { #[test] fn raindex_sync_status_deserializes_from_json() { let json = r#"{ - "obId": {"chainId": 137, "raindexAddress": "0x0000000000000000000000000000000000001234"}, + "raindexId": {"chainId": 137, "raindexAddress": "0x0000000000000000000000000000000000001234"}, "status": "syncing", "schedulerState": "leader", "phaseMessage": "Fetching latest block" @@ -311,7 +311,7 @@ mod tests { let status: RaindexSyncStatus = serde_json::from_str(json).unwrap(); - assert_eq!(status.ob_id.chain_id, 137); + assert_eq!(status.raindex_id.chain_id, 137); assert_eq!(status.status, LocalDbStatus::Syncing); assert_eq!(status.scheduler_state, SchedulerState::Leader); assert_eq!( diff --git a/crates/common/src/raindex_client/local_db/transactions.rs b/crates/common/src/raindex_client/local_db/transactions.rs index 5699d0a4a4..c5e5dd5481 100644 --- a/crates/common/src/raindex_client/local_db/transactions.rs +++ b/crates/common/src/raindex_client/local_db/transactions.rs @@ -21,10 +21,10 @@ impl<'a> LocalDbTransactions<'a> { /// Returns None if no transaction with that hash is found. pub async fn get_by_tx_hash( &self, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, tx_hash: B256, ) -> Result, RaindexError> { - let stmt = build_fetch_transaction_by_hash_stmt(ob_id, tx_hash); + let stmt = build_fetch_transaction_by_hash_stmt(raindex_id, tx_hash); let results: Vec = self.db.query_json(&stmt).await?; if let Some(local_tx) = results.into_iter().next() { @@ -95,9 +95,9 @@ mod tests { let local_db = LocalDb::new(exec); let transactions = LocalDbTransactions::new(&local_db); - let ob_id = RaindexIdentifier::new(1, raindex_addr); + let raindex_id = RaindexIdentifier::new(1, raindex_addr); - let result = transactions.get_by_tx_hash(&ob_id, tx_hash).await; + let result = transactions.get_by_tx_hash(&raindex_id, tx_hash).await; assert!(result.is_ok()); let tx = result.unwrap(); @@ -117,9 +117,9 @@ mod tests { let local_db = LocalDb::new(exec); let transactions = LocalDbTransactions::new(&local_db); - let ob_id = RaindexIdentifier::new(1, raindex_addr); + let raindex_id = RaindexIdentifier::new(1, raindex_addr); - let result = transactions.get_by_tx_hash(&ob_id, tx_hash).await; + let result = transactions.get_by_tx_hash(&raindex_id, tx_hash).await; assert!(result.is_ok()); assert!(result.unwrap().is_none()); diff --git a/crates/common/src/raindex_client/local_db/vaults.rs b/crates/common/src/raindex_client/local_db/vaults.rs index ef560423d9..1092ba65d8 100644 --- a/crates/common/src/raindex_client/local_db/vaults.rs +++ b/crates/common/src/raindex_client/local_db/vaults.rs @@ -73,12 +73,12 @@ impl VaultsDataSource for LocalDbVaults<'_> { async fn get_by_id( &self, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, vault_id: &Bytes, ) -> Result, RaindexError> { let fetch_args = FetchVaultsArgs { - chain_ids: vec![ob_id.chain_id], - raindex_addresses: vec![ob_id.raindex_address], + chain_ids: vec![raindex_id.chain_id], + raindex_addresses: vec![raindex_id.raindex_address], hide_zero_balance: false, ..FetchVaultsArgs::default() }; @@ -120,10 +120,10 @@ impl VaultsDataSource for LocalDbVaults<'_> { #[cfg(not(target_family = "wasm"))] let owner_address = vault.owner(); - let ob_id = crate::local_db::RaindexIdentifier::new(vault.chain_id(), raindex_address); + let raindex_id = crate::local_db::RaindexIdentifier::new(vault.chain_id(), raindex_address); let local_changes = fetch_vault_balance_changes( self.db, - &ob_id, + &raindex_id, vault_id, token_address, owner_address, diff --git a/crates/common/src/raindex_client/orders.rs b/crates/common/src/raindex_client/orders.rs index 70faec62ad..8c231483b5 100644 --- a/crates/common/src/raindex_client/orders.rs +++ b/crates/common/src/raindex_client/orders.rs @@ -109,7 +109,7 @@ pub(crate) trait OrdersDataSource { async fn get_by_hash( &self, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, order_hash: &B256, ) -> Result, RaindexError>; @@ -129,7 +129,7 @@ pub(crate) trait OrdersDataSource { async fn trades_list( &self, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, order_hash: &B256, start_timestamp: Option, end_timestamp: Option, @@ -138,7 +138,7 @@ pub(crate) trait OrdersDataSource { async fn trades_count( &self, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, order_hash: &B256, start_timestamp: Option, end_timestamp: Option, @@ -1056,11 +1056,11 @@ impl OrdersDataSource for SubgraphOrders<'_> { async fn get_by_hash( &self, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, order_hash: &B256, ) -> Result, RaindexError> { let raindex_client = ClientRef::new(self.client.clone()); - let client = self.client.get_raindex_subgraph_client(ob_id.raindex_address)?; + let client = self.client.get_raindex_subgraph_client(raindex_id.raindex_address)?; let order = match client .order_detail_by_hash(SgBytes(order_hash.to_string())) .await @@ -1069,7 +1069,7 @@ impl OrdersDataSource for SubgraphOrders<'_> { Err(RaindexSubgraphClientError::Empty) => return Ok(None), Err(err) => return Err(err.into()), }; - let order = RaindexOrder::try_from_sg_order(raindex_client, ob_id.chain_id, order, None)?; + let order = RaindexOrder::try_from_sg_order(raindex_client, raindex_id.chain_id, order, None)?; Ok(Some(order)) } @@ -1125,13 +1125,13 @@ impl OrdersDataSource for SubgraphOrders<'_> { async fn trades_list( &self, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, order_hash: &B256, start_timestamp: Option, end_timestamp: Option, page: Option, ) -> Result, RaindexError> { - let client = self.client.get_raindex_subgraph_client(ob_id.raindex_address)?; + let client = self.client.get_raindex_subgraph_client(raindex_id.raindex_address)?; let order = client .order_detail_by_hash(SgBytes(order_hash.to_string())) @@ -1151,18 +1151,18 @@ impl OrdersDataSource for SubgraphOrders<'_> { trades .into_iter() - .map(|trade| RaindexTrade::try_from_sg_trade(ob_id.chain_id, trade)) + .map(|trade| RaindexTrade::try_from_sg_trade(raindex_id.chain_id, trade)) .collect() } async fn trades_count( &self, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, order_hash: &B256, start_timestamp: Option, end_timestamp: Option, ) -> Result { - let client = self.client.get_raindex_subgraph_client(ob_id.raindex_address)?; + let client = self.client.get_raindex_subgraph_client(raindex_id.raindex_address)?; let order = client .order_detail_by_hash(SgBytes(order_hash.to_string())) @@ -1179,27 +1179,27 @@ impl OrdersDataSource for SubgraphOrders<'_> { impl RaindexClient { pub async fn get_order_by_hash( &self, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, order_hash: B256, ) -> Result { - let raindex_cfg = self.get_raindex_by_address(ob_id.raindex_address)?; - if raindex_cfg.network.chain_id != ob_id.chain_id { + let raindex_cfg = self.get_raindex_by_address(raindex_id.raindex_address)?; + if raindex_cfg.network.chain_id != raindex_id.chain_id { return Err(RaindexError::RaindexNotFound( - ob_id.raindex_address.to_string(), - ob_id.chain_id, + raindex_id.raindex_address.to_string(), + raindex_id.chain_id, )); } - match self.query_source(ob_id.chain_id) { + match self.query_source(raindex_id.chain_id) { QuerySource::LocalDb(local_db) => { let local_source = LocalDbOrders::new(&local_db, ClientRef::new(self.clone())); let mut order = local_source - .get_by_hash(ob_id, &order_hash) + .get_by_hash(raindex_id, &order_hash) .await? .ok_or_else(|| { RaindexError::OrderNotFound( - ob_id.raindex_address.to_string(), - ob_id.chain_id, + raindex_id.raindex_address.to_string(), + raindex_id.chain_id, order_hash, ) })?; @@ -1208,12 +1208,12 @@ impl RaindexClient { } QuerySource::Subgraph => { let mut order = SubgraphOrders::new(self) - .get_by_hash(ob_id, &order_hash) + .get_by_hash(raindex_id, &order_hash) .await? .ok_or_else(|| { RaindexError::OrderNotFound( - ob_id.raindex_address.to_string(), - ob_id.chain_id, + raindex_id.raindex_address.to_string(), + raindex_id.chain_id, order_hash, ) })?; diff --git a/crates/common/src/raindex_client/trades.rs b/crates/common/src/raindex_client/trades.rs index 0952003a26..50fe31f312 100644 --- a/crates/common/src/raindex_client/trades.rs +++ b/crates/common/src/raindex_client/trades.rs @@ -138,20 +138,20 @@ impl RaindexOrder { #[cfg(not(target_family = "wasm"))] let order_hash = B256::from_str(&self.order_hash().to_string())?; - let ob_id = RaindexIdentifier::new(chain_id, raindex_addr); + let raindex_id = RaindexIdentifier::new(chain_id, raindex_addr); let raindex_client = self.get_raindex_client(); match raindex_client.query_source(chain_id) { QuerySource::LocalDb(local_db) => { let local_source = LocalDbOrders::new(&local_db, ClientRef::clone(&raindex_client)); local_source - .trades_list(&ob_id, &order_hash, start_timestamp, end_timestamp, page) + .trades_list(&raindex_id, &order_hash, start_timestamp, end_timestamp, page) .await } QuerySource::Subgraph => { let subgraph_source = SubgraphOrders::new(&raindex_client); subgraph_source - .trades_list(&ob_id, &order_hash, start_timestamp, end_timestamp, page) + .trades_list(&raindex_id, &order_hash, start_timestamp, end_timestamp, page) .await } } @@ -236,20 +236,20 @@ impl RaindexOrder { #[cfg(not(target_family = "wasm"))] let order_hash = self.order_hash(); - let ob_id = RaindexIdentifier::new(chain_id, raindex_addr); + let raindex_id = RaindexIdentifier::new(chain_id, raindex_addr); let raindex_client = self.get_raindex_client(); match raindex_client.query_source(chain_id) { QuerySource::LocalDb(local_db) => { let local_source = LocalDbOrders::new(&local_db, ClientRef::clone(&raindex_client)); local_source - .trades_count(&ob_id, &order_hash, start_timestamp, end_timestamp) + .trades_count(&raindex_id, &order_hash, start_timestamp, end_timestamp) .await } QuerySource::Subgraph => { let subgraph_source = SubgraphOrders::new(&raindex_client); subgraph_source - .trades_count(&ob_id, &order_hash, start_timestamp, end_timestamp) + .trades_count(&raindex_id, &order_hash, start_timestamp, end_timestamp) .await } } diff --git a/crates/common/src/raindex_client/transactions.rs b/crates/common/src/raindex_client/transactions.rs index 6c02be744e..43fdd88264 100644 --- a/crates/common/src/raindex_client/transactions.rs +++ b/crates/common/src/raindex_client/transactions.rs @@ -177,10 +177,10 @@ impl RaindexClient { match self.query_source(chain_id) { QuerySource::LocalDb(local_db) => { let local_source = LocalDbTransactions::new(&local_db); - let ob_id = RaindexIdentifier::new(chain_id, raindex_address); + let raindex_id = RaindexIdentifier::new(chain_id, raindex_address); for attempt in 1..=attempts { - if let Some(tx) = local_source.get_by_tx_hash(&ob_id, tx_hash).await? { + if let Some(tx) = local_source.get_by_tx_hash(&raindex_id, tx_hash).await? { return Ok(tx); } if attempt < attempts { diff --git a/crates/common/src/raindex_client/vaults.rs b/crates/common/src/raindex_client/vaults.rs index 7cbc71bb2c..743cdda2da 100644 --- a/crates/common/src/raindex_client/vaults.rs +++ b/crates/common/src/raindex_client/vaults.rs @@ -65,7 +65,7 @@ pub(crate) trait VaultsDataSource { async fn get_by_id( &self, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, vault_id: &Bytes, ) -> Result, RaindexError>; @@ -1426,38 +1426,38 @@ impl RaindexClient { impl RaindexClient { pub async fn get_vault( &self, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, vault_id: Bytes, ) -> Result { - let raindex_cfg = self.get_raindex_by_address(ob_id.raindex_address)?; - if raindex_cfg.network.chain_id != ob_id.chain_id { + let raindex_cfg = self.get_raindex_by_address(raindex_id.raindex_address)?; + if raindex_cfg.network.chain_id != raindex_id.chain_id { return Err(RaindexError::RaindexNotFound( - ob_id.raindex_address.to_string(), - ob_id.chain_id, + raindex_id.raindex_address.to_string(), + raindex_id.chain_id, )); } - match self.query_source(ob_id.chain_id) { + match self.query_source(raindex_id.chain_id) { QuerySource::LocalDb(local_db) => { let local_source = LocalDbVaults::new(&local_db, ClientRef::new(self.clone())); local_source - .get_by_id(ob_id, &vault_id) + .get_by_id(raindex_id, &vault_id) .await? .ok_or_else(|| { RaindexError::VaultNotFound( - ob_id.raindex_address.to_string(), - ob_id.chain_id, + raindex_id.raindex_address.to_string(), + raindex_id.chain_id, vault_id.to_string(), ) }) } QuerySource::Subgraph => SubgraphVaults::new(self) - .get_by_id(ob_id, &vault_id) + .get_by_id(raindex_id, &vault_id) .await? .ok_or_else(|| { RaindexError::VaultNotFound( - ob_id.raindex_address.to_string(), - ob_id.chain_id, + raindex_id.raindex_address.to_string(), + raindex_id.chain_id, vault_id.to_string(), ) }), @@ -1518,18 +1518,18 @@ impl VaultsDataSource for SubgraphVaults<'_> { async fn get_by_id( &self, - ob_id: &RaindexIdentifier, + raindex_id: &RaindexIdentifier, vault_id: &Bytes, ) -> Result, RaindexError> { let raindex_client = ClientRef::new(self.client.clone()); - let client = self.client.get_raindex_subgraph_client(ob_id.raindex_address)?; + let client = self.client.get_raindex_subgraph_client(raindex_id.raindex_address)?; let vault = match client.vault_detail(Id::new(vault_id.to_string())).await { Ok(vault) => vault, Err(RaindexSubgraphClientError::Empty) => return Ok(None), Err(err) => return Err(err.into()), }; - let vault = RaindexVault::try_from_sg_vault(raindex_client, ob_id.chain_id, vault, None)?; + let vault = RaindexVault::try_from_sg_vault(raindex_client, raindex_id.chain_id, vault, None)?; Ok(Some(vault)) } diff --git a/packages/ui-components/src/__tests__/DropdownRaindexesFilter.test.ts b/packages/ui-components/src/__tests__/DropdownRaindexesFilter.test.ts index bd144e66cd..3983088ba5 100644 --- a/packages/ui-components/src/__tests__/DropdownRaindexesFilter.test.ts +++ b/packages/ui-components/src/__tests__/DropdownRaindexesFilter.test.ts @@ -147,7 +147,7 @@ describe('DropdownRaindexesFilter', () => { test('displays "All raindexes" when all raindexes are selected', () => { const allAddresses = Array.from(mockRaindexesData.values()).map( - (ob) => ob.address + (raindex) => raindex.address ) as Address[]; render(DropdownRaindexesFilter, { @@ -163,7 +163,7 @@ describe('DropdownRaindexesFilter', () => { test('displays custom all label when all raindexes are selected', () => { const allAddresses = Array.from(mockRaindexesData.values()).map( - (ob) => ob.address + (raindex) => raindex.address ) as Address[]; const customAllLabel = 'Everything selected'; @@ -196,7 +196,7 @@ describe('DropdownRaindexesFilter', () => { test('displays plural count when multiple raindexes are selected', () => { const selectedAddresses = Array.from(mockRaindexesData.values()) .slice(0, 2) - .map((ob) => ob.address) as Address[]; + .map((raindex) => raindex.address) as Address[]; render(DropdownRaindexesFilter, { props: { diff --git a/packages/ui-components/src/__tests__/LocalDbStatusCard.test.ts b/packages/ui-components/src/__tests__/LocalDbStatusCard.test.ts index 40b0de30cc..e500d9beb9 100644 --- a/packages/ui-components/src/__tests__/LocalDbStatusCard.test.ts +++ b/packages/ui-components/src/__tests__/LocalDbStatusCard.test.ts @@ -98,7 +98,7 @@ describe('LocalDbStatusCard', () => { [ '137:0x1234567890123456789012345678901234567890', { - obId: { + raindexId: { chainId: 137, raindexAddress: '0x1234567890123456789012345678901234567890' }, diff --git a/packages/ui-components/src/__tests__/LocalDbStatusModal.test.ts b/packages/ui-components/src/__tests__/LocalDbStatusModal.test.ts index 485b935ef7..49681786a4 100644 --- a/packages/ui-components/src/__tests__/LocalDbStatusModal.test.ts +++ b/packages/ui-components/src/__tests__/LocalDbStatusModal.test.ts @@ -117,7 +117,7 @@ describe('LocalDbStatusModal', () => { [ '137:0x1234567890123456789012345678901234567890', { - obId: { + raindexId: { chainId: 137, raindexAddress: '0x1234567890123456789012345678901234567890' }, @@ -146,7 +146,7 @@ describe('LocalDbStatusModal', () => { [ '137:0x1234567890123456789012345678901234567890', { - obId: { + raindexId: { chainId: 137, raindexAddress: '0x1234567890123456789012345678901234567890' }, @@ -176,7 +176,7 @@ describe('LocalDbStatusModal', () => { [ '137:0x1234567890123456789012345678901234567890', { - obId: { + raindexId: { chainId: 137, raindexAddress: '0x1234567890123456789012345678901234567890' }, @@ -206,7 +206,7 @@ describe('LocalDbStatusModal', () => { [ '137:0x1234567890123456789012345678901234567890', { - obId: { + raindexId: { chainId: 137, raindexAddress: '0x1234567890123456789012345678901234567890' }, @@ -261,7 +261,7 @@ describe('LocalDbStatusModal', () => { [ '137:0x1111111111111111111111111111111111111111', { - obId: { + raindexId: { chainId: 137, raindexAddress: '0x1111111111111111111111111111111111111111' }, @@ -272,7 +272,7 @@ describe('LocalDbStatusModal', () => { [ '42161:0x2222222222222222222222222222222222222222', { - obId: { + raindexId: { chainId: 42161, raindexAddress: '0x2222222222222222222222222222222222222222' }, @@ -307,7 +307,7 @@ describe('LocalDbStatusModal', () => { [ '137:0x1111111111111111111111111111111111111111', { - obId: { + raindexId: { chainId: 137, raindexAddress: '0x1111111111111111111111111111111111111111' }, @@ -318,7 +318,7 @@ describe('LocalDbStatusModal', () => { [ '137:0x2222222222222222222222222222222222222222', { - obId: { + raindexId: { chainId: 137, raindexAddress: '0x2222222222222222222222222222222222222222' }, @@ -350,7 +350,7 @@ describe('LocalDbStatusModal', () => { [ '137:0x1234567890123456789012345678901234567890', { - obId: { + raindexId: { chainId: 137, raindexAddress: '0x1234567890123456789012345678901234567890' }, @@ -380,7 +380,7 @@ describe('LocalDbStatusModal', () => { [ '137:0x1234567890123456789012345678901234567890', { - obId: { + raindexId: { chainId: 137, raindexAddress: '0x1234567890123456789012345678901234567890' }, diff --git a/packages/ui-components/src/lib/components/LocalDbStatusModal.svelte b/packages/ui-components/src/lib/components/LocalDbStatusModal.svelte index a81cc04316..a08f254dff 100644 --- a/packages/ui-components/src/lib/components/LocalDbStatusModal.svelte +++ b/packages/ui-components/src/lib/components/LocalDbStatusModal.svelte @@ -25,7 +25,7 @@ ): NetworkGroup[] { const groups: NetworkGroup[] = []; for (const network of networks) { - const networkRaindexes = raindexes.filter((ob) => ob.obId.chainId === network.chainId); + const networkRaindexes = raindexes.filter((raindex) => raindex.raindexId.chainId === network.chainId); groups.push({ chainId: network.chainId, networkName: getNetworkName(network.chainId) ?? `Chain ${network.chainId}`, @@ -76,24 +76,24 @@ {#if group.raindexes.length > 0}
    - {#each group.raindexes as obStatus (obStatus.obId.raindexAddress)} + {#each group.raindexes as raindexStatus (raindexStatus.raindexId.raindexAddress)}
  • - {obStatus.obId.raindexAddress} + {raindexStatus.raindexId.raindexAddress} - {#if obStatus.status === 'syncing' && obStatus.phaseMessage && obStatus.schedulerState !== 'notLeader'} + {#if raindexStatus.status === 'syncing' && raindexStatus.phaseMessage && raindexStatus.schedulerState !== 'notLeader'}
    - {obStatus.phaseMessage} + {raindexStatus.phaseMessage}
    {/if} - {#if obStatus.status === 'failure' && obStatus.error} + {#if raindexStatus.status === 'failure' && raindexStatus.error}
    - {obStatus.error} + {raindexStatus.error}
    {/if}
    diff --git a/packages/ui-components/src/lib/components/dropdown/DropdownRaindexesFilter.svelte b/packages/ui-components/src/lib/components/dropdown/DropdownRaindexesFilter.svelte index f1f4fdeb73..a601f6568b 100644 --- a/packages/ui-components/src/lib/components/dropdown/DropdownRaindexesFilter.svelte +++ b/packages/ui-components/src/lib/components/dropdown/DropdownRaindexesFilter.svelte @@ -64,10 +64,10 @@ } else { const term = searchTerm.toLowerCase(); filteredRaindexes = availableRaindexes.filter( - (ob) => - ob.label?.toLowerCase().includes(term) || - ob.address?.toLowerCase().includes(term) || - ob.key?.toLowerCase().includes(term) + (raindex) => + raindex.label?.toLowerCase().includes(term) || + raindex.address?.toLowerCase().includes(term) || + raindex.key?.toLowerCase().includes(term) ); selectedIndex = filteredRaindexes.length > 0 ? 0 : -1; } @@ -84,9 +84,9 @@ return aSelected ? -1 : 1; }); - function getDisplayName(ob: RaindexItem): string { - const truncatedAddr = `${ob.address.slice(0, 6)}...${ob.address.slice(-4)}`; - return ob.label ? `${ob.label} (${truncatedAddr})` : truncatedAddr; + function getDisplayName(raindex: RaindexItem): string { + const truncatedAddr = `${raindex.address.slice(0, 6)}...${raindex.address.slice(-4)}`; + return raindex.label ? `${raindex.label} (${truncatedAddr})` : truncatedAddr; } function updateSelectedRaindexes(newSelection: Address[]) { diff --git a/packages/webapp/src/__tests__/localDbStatus.test.ts b/packages/webapp/src/__tests__/localDbStatus.test.ts index 14627c956d..f0c2c9a573 100644 --- a/packages/webapp/src/__tests__/localDbStatus.test.ts +++ b/packages/webapp/src/__tests__/localDbStatus.test.ts @@ -120,7 +120,7 @@ describe('localDbStatus store', () => { describe('updateRaindexStatus', () => { it('adds new raindex status to map', () => { const status: RaindexSyncStatus = { - obId: { + raindexId: { chainId: 137, raindexAddress: '0x1234567890123456789012345678901234567890' }, @@ -139,7 +139,7 @@ describe('localDbStatus store', () => { it('updates existing raindex status', () => { const initial: RaindexSyncStatus = { - obId: { + raindexId: { chainId: 137, raindexAddress: '0x1234567890123456789012345678901234567890' }, @@ -148,7 +148,7 @@ describe('localDbStatus store', () => { phaseMessage: 'Fetching latest block' }; const updated: RaindexSyncStatus = { - obId: { + raindexId: { chainId: 137, raindexAddress: '0x1234567890123456789012345678901234567890' }, @@ -166,16 +166,16 @@ describe('localDbStatus store', () => { }); it('handles multiple raindexes on same chain', () => { - const ob1: RaindexSyncStatus = { - obId: { + const raindex1: RaindexSyncStatus = { + raindexId: { chainId: 137, raindexAddress: '0x1111111111111111111111111111111111111111' }, status: 'active', schedulerState: 'leader' }; - const ob2: RaindexSyncStatus = { - obId: { + const raindex2: RaindexSyncStatus = { + raindexId: { chainId: 137, raindexAddress: '0x2222222222222222222222222222222222222222' }, @@ -183,24 +183,24 @@ describe('localDbStatus store', () => { schedulerState: 'leader' }; - updateRaindexStatus(ob1); - updateRaindexStatus(ob2); + updateRaindexStatus(raindex1); + updateRaindexStatus(raindex2); const map = get(raindexStatuses); expect(map.size).toBe(2); }); it('handles raindexes on different chains', () => { - const polygonOb: RaindexSyncStatus = { - obId: { + const polygonRaindex: RaindexSyncStatus = { + raindexId: { chainId: 137, raindexAddress: '0x1234567890123456789012345678901234567890' }, status: 'active', schedulerState: 'leader' }; - const arbitrumOb: RaindexSyncStatus = { - obId: { + const arbitrumRaindex: RaindexSyncStatus = { + raindexId: { chainId: 42161, raindexAddress: '0x1234567890123456789012345678901234567890' }, @@ -208,8 +208,8 @@ describe('localDbStatus store', () => { schedulerState: 'leader' }; - updateRaindexStatus(polygonOb); - updateRaindexStatus(arbitrumOb); + updateRaindexStatus(polygonRaindex); + updateRaindexStatus(arbitrumRaindex); const map = get(raindexStatuses); expect(map.size).toBe(2); @@ -217,7 +217,7 @@ describe('localDbStatus store', () => { it('stores error field when present', () => { const status: RaindexSyncStatus = { - obId: { + raindexId: { chainId: 137, raindexAddress: '0x1234567890123456789012345678901234567890' }, @@ -253,7 +253,7 @@ describe('localDbStatus store', () => { it('dispatches RaindexSyncStatus to updateRaindexStatus', () => { const status: RaindexSyncStatus = { - obId: { + raindexId: { chainId: 137, raindexAddress: '0x1234567890123456789012345678901234567890' }, @@ -269,14 +269,14 @@ describe('localDbStatus store', () => { expect(raindexMap.size).toBe(1); }); - it('distinguishes types by presence of obId field', () => { + it('distinguishes types by presence of raindexId field', () => { const networkStatus: NetworkSyncStatus = { chainId: 137, status: 'active', schedulerState: 'leader' }; const raindexStatus: RaindexSyncStatus = { - obId: { + raindexId: { chainId: 42161, raindexAddress: '0x1234567890123456789012345678901234567890' }, @@ -302,7 +302,7 @@ describe('localDbStatus store', () => { schedulerState: 'leader' }; const raindexStatus1: RaindexSyncStatus = { - obId: { + raindexId: { chainId: 137, raindexAddress: '0x1234567890123456789012345678901234567890' }, @@ -316,7 +316,7 @@ describe('localDbStatus store', () => { schedulerState: 'leader' }; const raindexStatus2: RaindexSyncStatus = { - obId: { + raindexId: { chainId: 42161, raindexAddress: '0xabcdefabcdefabcdefabcdefabcdefabcdefabcd' }, @@ -338,11 +338,11 @@ describe('localDbStatus store', () => { expect(networkMap.get(137)?.status).toBe('active'); expect(networkMap.get(42161)?.status).toBe('syncing'); - const obKey1 = '137:0x1234567890123456789012345678901234567890'; - const obKey2 = '42161:0xabcdefabcdefabcdefabcdefabcdefabcdefabcd'; - expect(raindexMap.get(obKey1)?.status).toBe('syncing'); - expect(raindexMap.get(obKey1)?.phaseMessage).toBe('Fetching latest block'); - expect(raindexMap.get(obKey2)?.status).toBe('active'); + const raindexKey1 = '137:0x1234567890123456789012345678901234567890'; + const raindexKey2 = '42161:0xabcdefabcdefabcdefabcdefabcdefabcdefabcd'; + expect(raindexMap.get(raindexKey1)?.status).toBe('syncing'); + expect(raindexMap.get(raindexKey1)?.phaseMessage).toBe('Fetching latest block'); + expect(raindexMap.get(raindexKey2)?.status).toBe('active'); }); it('simulates scheduler callback receiving interleaved network and raindex updates', () => { @@ -353,7 +353,7 @@ describe('localDbStatus store', () => { schedulerState: 'leader' as const }, { - obId: { + raindexId: { chainId: 137, raindexAddress: '0x1111111111111111111111111111111111111111' }, @@ -362,7 +362,7 @@ describe('localDbStatus store', () => { phaseMessage: 'Running bootstrap' }, { - obId: { + raindexId: { chainId: 137, raindexAddress: '0x1111111111111111111111111111111111111111' }, @@ -384,8 +384,8 @@ describe('localDbStatus store', () => { const raindexMap = get(raindexStatuses); expect(networkMap.get(137)?.status).toBe('active'); - const obKey = '137:0x1111111111111111111111111111111111111111'; - expect(raindexMap.get(obKey)?.status).toBe('active'); + const raindexKey = '137:0x1111111111111111111111111111111111111111'; + expect(raindexMap.get(raindexKey)?.status).toBe('active'); }); }); @@ -403,7 +403,7 @@ describe('localDbStatus store', () => { schedulerState: 'leader' }); updateRaindexStatus({ - obId: { + raindexId: { chainId: 137, raindexAddress: '0x1234567890123456789012345678901234567890' }, @@ -458,7 +458,7 @@ describe('localDbStatus store', () => { schedulerState: 'leader' }); updateRaindexStatus({ - obId: { + raindexId: { chainId: 137, raindexAddress: '0x1234567890123456789012345678901234567890' }, @@ -497,7 +497,7 @@ describe('localDbStatus store', () => { schedulerState: 'leader' }); updateRaindexStatus({ - obId: { + raindexId: { chainId: 137, raindexAddress: '0x1234567890123456789012345678901234567890' }, diff --git a/packages/webapp/src/lib/stores/localDbStatus.ts b/packages/webapp/src/lib/stores/localDbStatus.ts index 0d68a71e1e..dd103fc8eb 100644 --- a/packages/webapp/src/lib/stores/localDbStatus.ts +++ b/packages/webapp/src/lib/stores/localDbStatus.ts @@ -10,13 +10,13 @@ export const networkStatuses = writable>(new Map( export const raindexStatuses = writable>(new Map()); function raindexStatusKey(status: RaindexSyncStatus): string { - return `${status.obId.chainId}:${status.obId.raindexAddress}`; + return `${status.raindexId.chainId}:${status.raindexId.raindexAddress}`; } function isRaindexSyncStatus( status: NetworkSyncStatus | RaindexSyncStatus ): status is RaindexSyncStatus { - return 'obId' in status; + return 'raindexId' in status; } export function updateNetworkStatus(status: NetworkSyncStatus) { From 65174cbc52ab43d6540351bff686ed1308566e03 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Wed, 1 Apr 2026 18:47:21 +0400 Subject: [PATCH 35/69] Update rain.raindex.interface submodule (audit MDs deleted) Co-Authored-By: Claude Opus 4.6 (1M context) --- foundry.lock | 2 +- lib/rain.raindex.interface | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/foundry.lock b/foundry.lock index 9fe4430e83..0e9c2b06f0 100644 --- a/foundry.lock +++ b/foundry.lock @@ -6,7 +6,7 @@ "rev": "1ea41cd004a926e3a964ba5498654f3cd538f139" }, "lib/rain.raindex.interface": { - "rev": "ad4427dcb07e6df95def94999799470db89321b3" + "rev": "9e2da33b477e16bb2c2dc16b29de98d4cbe9dd94" }, "lib/sushixswap-v2": { "rev": "ca38c64cf7c3042f6427414d7bff61c54293da51" diff --git a/lib/rain.raindex.interface b/lib/rain.raindex.interface index ad4427dcb0..9e2da33b47 160000 --- a/lib/rain.raindex.interface +++ b/lib/rain.raindex.interface @@ -1 +1 @@ -Subproject commit ad4427dcb07e6df95def94999799470db89321b3 +Subproject commit 9e2da33b477e16bb2c2dc16b29de98d4cbe9dd94 From 2380b63799c8a2de6a6b4ef6577bb5490d13878a Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Wed, 1 Apr 2026 19:01:16 +0400 Subject: [PATCH 36/69] Rename Goldsky subgraph name from ob4 to raindex Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/deploy-subgraph.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-subgraph.yaml b/.github/workflows/deploy-subgraph.yaml index 972a7633e4..c0e9e51f40 100644 --- a/.github/workflows/deploy-subgraph.yaml +++ b/.github/workflows/deploy-subgraph.yaml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest env: GOLDSKY_TOKEN: ${{ secrets.CI_GOLDSKY_TOKEN }} - GOLDSKY_SUBGRAPH_NAME: ob4 + GOLDSKY_SUBGRAPH_NAME: raindex steps: - uses: actions/checkout@v4 with: From 518ee97ea91030ee32d293bf94ee7ebe58b32af7 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Wed, 1 Apr 2026 20:05:37 +0400 Subject: [PATCH 37/69] Run cargo fmt Co-Authored-By: Claude Opus 4.6 (1M context) --- crates/cli/src/commands/local_db/cli.rs | 4 +-- .../local_db/pipeline/runner/export.rs | 12 +++---- .../local_db/pipeline/runner/manifest.rs | 12 +++++-- .../commands/local_db/pipeline/runner/mod.rs | 15 ++++---- crates/common/src/add_order.rs | 10 ++---- crates/common/src/dotrain_order.rs | 8 +++-- crates/common/src/local_db/export.rs | 6 +--- crates/common/src/local_db/insert.rs | 13 +++---- .../src/local_db/pipeline/adapters/apply.rs | 24 +++++++++++-- .../local_db/pipeline/adapters/bootstrap.rs | 5 +-- .../src/local_db/pipeline/adapters/events.rs | 9 +---- .../src/local_db/pipeline/adapters/window.rs | 35 ++++++++++++++++--- crates/common/src/local_db/pipeline/engine.rs | 26 +++++++------- .../src/local_db/pipeline/runner/utils.rs | 12 ++++--- .../src/local_db/query/fetch_vaults/mod.rs | 6 +--- .../query/upsert_vault_balances/mod.rs | 7 +++- .../src/raindex_client/local_db/orders.rs | 20 ++++++++--- .../local_db/pipeline/bootstrap.rs | 5 +-- .../local_db/pipeline/runner/mod.rs | 15 ++++---- .../local_db/pipeline/status/wasm.rs | 9 +++-- .../local_db/query/fetch_last_synced_block.rs | 9 +++-- .../local_db/query/fetch_order_trades.rs | 3 +- .../query/fetch_order_trades_count.rs | 3 +- .../query/fetch_order_vaults_volume.rs | 8 +++-- .../local_db/query/fetch_store_addresses.rs | 6 ++-- .../query/fetch_transaction_by_hash.rs | 18 ++++------ .../query/fetch_vault_balance_changes.rs | 9 +++-- .../src/raindex_client/local_db/state.rs | 8 ++--- .../src/raindex_client/local_db/status.rs | 8 ++++- .../src/raindex_client/local_db/vaults.rs | 5 ++- crates/common/src/raindex_client/mod.rs | 6 ++-- crates/common/src/raindex_client/orders.rs | 25 ++++++++----- .../common/src/raindex_client/orders_list.rs | 5 +-- .../src/raindex_client/remove_orders.rs | 20 ++--------- .../raindex_client/take_orders/e2e_tests.rs | 24 +++++-------- .../src/raindex_client/take_orders/mod.rs | 7 ++-- .../raindex_client/take_orders/selection.rs | 28 +++++---------- crates/common/src/raindex_client/trades.rs | 16 +++++++-- crates/common/src/raindex_client/vaults.rs | 22 ++++++------ crates/common/src/remove_order.rs | 8 ++--- crates/common/src/take_orders/preflight.rs | 11 ++---- crates/common/src/test_helpers.rs | 14 ++------ crates/common/src/withdraw.rs | 6 ++-- crates/js_api/src/gui/order_operations.rs | 7 ++-- crates/js_api/src/gui/state_management.rs | 4 +-- crates/js_api/src/yaml/mod.rs | 6 ++-- crates/rest_api/src/routes/take_orders.rs | 20 +++-------- crates/settings/src/lib.rs | 4 +-- crates/settings/src/local_db_manifest.rs | 9 +++-- crates/settings/src/order.rs | 3 +- crates/settings/src/raindex.rs | 24 ++++++------- crates/settings/src/yaml/mod.rs | 11 +++--- crates/settings/src/yaml/raindex.rs | 5 +-- crates/subgraph/src/lib.rs | 4 +-- crates/subgraph/src/multi_raindex_client.rs | 2 +- crates/subgraph/src/raindex_client/order.rs | 2 +- .../src/raindex_client/order_trade.rs | 5 +-- crates/subgraph/src/raindex_client/token.rs | 5 +-- .../src/raindex_client/transaction.rs | 4 +-- .../src/vault_balance_changes_query.rs | 2 +- crates/test_fixtures/src/lib.rs | 3 +- 61 files changed, 317 insertions(+), 325 deletions(-) diff --git a/crates/cli/src/commands/local_db/cli.rs b/crates/cli/src/commands/local_db/cli.rs index 67a9d2dcc7..c6f8387a16 100644 --- a/crates/cli/src/commands/local_db/cli.rs +++ b/crates/cli/src/commands/local_db/cli.rs @@ -178,9 +178,7 @@ mod tests { use alloy::primitives::{address, Address}; use raindex_common::local_db::pipeline::engine::SyncInputs; use raindex_common::local_db::pipeline::runner::utils::RunnerTarget; - use raindex_common::local_db::pipeline::runner::{ - TargetFailure, TargetStage, TargetSuccess, - }; + use raindex_common::local_db::pipeline::runner::{TargetFailure, TargetStage, TargetSuccess}; use raindex_common::local_db::pipeline::{ FinalityConfig, SyncConfig, SyncOutcome, WindowOverrides, }; diff --git a/crates/cli/src/commands/local_db/pipeline/runner/export.rs b/crates/cli/src/commands/local_db/pipeline/runner/export.rs index aafb2b16a2..2f62c98bdb 100644 --- a/crates/cli/src/commands/local_db/pipeline/runner/export.rs +++ b/crates/cli/src/commands/local_db/pipeline/runner/export.rs @@ -88,10 +88,8 @@ mod tests { let temp_dir = TempDir::new().unwrap(); let db_path = temp_dir.path().join("raindex.sqlite"); let conn = Connection::open(&db_path).expect("open sqlite db"); - conn.execute_batch( - raindex_common::local_db::query::create_tables::CREATE_TABLES_SQL, - ) - .expect("create tables"); + conn.execute_batch(raindex_common::local_db::query::create_tables::CREATE_TABLES_SQL) + .expect("create tables"); let chain_id = 42161u32; let raindex_address = address!("0x0000000000000000000000000000000000000abc"); @@ -209,10 +207,8 @@ mod tests { let temp_dir = TempDir::new().unwrap(); let db_path = temp_dir.path().join("raindex.sqlite"); let conn = Connection::open(&db_path).expect("open sqlite db"); - conn.execute_batch( - raindex_common::local_db::query::create_tables::CREATE_TABLES_SQL, - ) - .expect("create tables"); + conn.execute_batch(raindex_common::local_db::query::create_tables::CREATE_TABLES_SQL) + .expect("create tables"); drop(conn); let chain_id = 10u32; diff --git a/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs b/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs index 5d0ad6f49e..dc3b2b3734 100644 --- a/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs +++ b/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs @@ -38,7 +38,11 @@ pub fn build_manifest( raindex_address: raindex_id.raindex_address, })?; - let dump_url = build_dump_url(release_base_url, raindex_id.chain_id, raindex_id.raindex_address)?; + let dump_url = build_dump_url( + release_base_url, + raindex_id.chain_id, + raindex_id.raindex_address, + )?; let end_block_hash = Bytes::from_str(export.end_block_hash.as_str())?; let manifest_raindex = ManifestRaindex { @@ -406,7 +410,11 @@ mod tests { let manifest = build_manifest(&successes, &exports, &lookup, &base_url, &HashMap::new()) .expect("manifest build succeeds"); let anvil = manifest.networks.get("anvil").expect("anvil network"); - let addresses: Vec<_> = anvil.raindexes.iter().map(|raindex_entry| raindex_entry.address).collect(); + let addresses: Vec<_> = anvil + .raindexes + .iter() + .map(|raindex_entry| raindex_entry.address) + .collect(); assert_eq!( addresses, vec![ diff --git a/crates/cli/src/commands/local_db/pipeline/runner/mod.rs b/crates/cli/src/commands/local_db/pipeline/runner/mod.rs index 40090fb7e0..eb80481b43 100644 --- a/crates/cli/src/commands/local_db/pipeline/runner/mod.rs +++ b/crates/cli/src/commands/local_db/pipeline/runner/mod.rs @@ -363,9 +363,7 @@ mod tests { use raindex_common::local_db::pipeline::{ EventsPipeline, StatusBus, SyncPhase, TokensPipeline, WindowPipeline, }; - use raindex_common::local_db::query::{ - LocalDbQueryExecutor, SqlStatement, SqlStatementBatch, - }; + use raindex_common::local_db::query::{LocalDbQueryExecutor, SqlStatement, SqlStatementBatch}; use raindex_common::local_db::{FetchConfig, LocalDbError}; use std::collections::HashMap; use std::fs::File; @@ -785,8 +783,7 @@ mod tests { _from_block: u64, _to_block: u64, _cfg: &FetchConfig, - ) -> Result, LocalDbError> - { + ) -> Result, LocalDbError> { Ok(Vec::new()) } @@ -796,8 +793,7 @@ mod tests { _from_block: u64, _to_block: u64, _cfg: &FetchConfig, - ) -> Result, LocalDbError> - { + ) -> Result, LocalDbError> { Ok(Vec::new()) } @@ -1444,7 +1440,10 @@ raindexes: let mut custom_failure = None; let mut join_failure = None; for failure in &report.failures { - match (failure.raindex_id.chain_id, failure.raindex_id.raindex_address) { + match ( + failure.raindex_id.chain_id, + failure.raindex_id.raindex_address, + ) { (42161, addr) if addr == address!("00000000000000000000000000000000000000b2") => { custom_failure = Some(failure); } diff --git a/crates/common/src/add_order.rs b/crates/common/src/add_order.rs index 2239850ea6..b09dadd0c4 100644 --- a/crates/common/src/add_order.rs +++ b/crates/common/src/add_order.rs @@ -33,9 +33,7 @@ use rain_metadata::{ }; use rain_metadata_bindings::MetaBoard::emitMetaCall; use raindex_app_settings::deployment::DeploymentCfg; -use raindex_bindings::IRaindexV6::{ - addOrder4Call, EvaluableV4, OrderConfigV4, TaskV2, IOV2, -}; +use raindex_bindings::IRaindexV6::{addOrder4Call, EvaluableV4, OrderConfigV4, TaskV2, IOV2}; use serde::{Deserialize, Serialize}; use serde_bytes::ByteBuf; use std::collections::HashMap; @@ -360,10 +358,8 @@ impl AddOrderArgs { transaction_args: TransactionArgs, ) -> Result, AddOrderArgsError> { let add_order_call = self.try_into_call(transaction_args.clone().rpcs).await?; - let params = transaction_args.try_into_write_contract_parameters( - add_order_call, - transaction_args.raindex_address, - )?; + let params = transaction_args + .try_into_write_contract_parameters(add_order_call, transaction_args.raindex_address)?; Ok(params) } diff --git a/crates/common/src/dotrain_order.rs b/crates/common/src/dotrain_order.rs index ba458f4ea3..cd6d7e67a1 100644 --- a/crates/common/src/dotrain_order.rs +++ b/crates/common/src/dotrain_order.rs @@ -313,8 +313,7 @@ impl DotrainOrder { sources.extend(settings); } - let mut raindex_yaml = - RaindexYaml::new(sources.clone(), RaindexYamlValidation::default())?; + let mut raindex_yaml = RaindexYaml::new(sources.clone(), RaindexYamlValidation::default())?; let mut dotrain_yaml = DotrainYaml::new_with_profile( sources.clone(), @@ -628,7 +627,10 @@ impl DotrainOrder { let network_key = order_cfg.network.key.clone(); let rainlang_key = rainlang_cfg.key.clone(); - let raindex_key = order_cfg.raindex.as_ref().map(|raindex_cfg| raindex_cfg.key.clone()); + let raindex_key = order_cfg + .raindex + .as_ref() + .map(|raindex_cfg| raindex_cfg.key.clone()); let subgraph_key = order_cfg .raindex .as_ref() diff --git a/crates/common/src/local_db/export.rs b/crates/common/src/local_db/export.rs index 991439408b..e9e988dfdc 100644 --- a/crates/common/src/local_db/export.rs +++ b/crates/common/src/local_db/export.rs @@ -1058,11 +1058,7 @@ mod tests { #[test] fn has_target_filters_detects_required_columns() { - let columns = vec![ - column("chain_id"), - column("raindex_address"), - column("foo"), - ]; + let columns = vec![column("chain_id"), column("raindex_address"), column("foo")]; assert!(has_target_filters(&columns)); let missing_raindex = vec![column("chain_id"), column("foo")]; diff --git a/crates/common/src/local_db/insert.rs b/crates/common/src/local_db/insert.rs index 222383858f..180e6f7b95 100644 --- a/crates/common/src/local_db/insert.rs +++ b/crates/common/src/local_db/insert.rs @@ -1587,8 +1587,7 @@ mod tests { ]; let raindex = Address::from([0x11; 20]); - let batch = - generate_erc20_token_statements(&RaindexIdentifier::new(1, raindex), &tokens); + let batch = generate_erc20_token_statements(&RaindexIdentifier::new(1, raindex), &tokens); assert_eq!(batch.len(), tokens.len()); for (statement, (expected_addr, expected_info)) in @@ -1596,9 +1595,7 @@ mod tests { { let sql = statement.sql(); assert!(sql.contains("INSERT INTO erc20_tokens")); - assert!( - sql.contains("ON CONFLICT(chain_id, raindex_address, token_address) DO UPDATE") - ); + assert!(sql.contains("ON CONFLICT(chain_id, raindex_address, token_address) DO UPDATE")); let params = statement.params(); assert_eq!(params.len(), 6); @@ -1669,8 +1666,7 @@ mod tests { )]; let raindex = Address::from([0x22; 20]); - let batch = - generate_erc20_token_statements(&RaindexIdentifier::new(5, raindex), &tokens); + let batch = generate_erc20_token_statements(&RaindexIdentifier::new(5, raindex), &tokens); assert_eq!(batch.len(), 1); let statement = &batch.statements()[0]; let sql = statement.sql(); @@ -1754,8 +1750,7 @@ mod tests { let raindex_address = Address::from([0x10; 20]); let batch = - raw_events_to_statements(&RaindexIdentifier::new(1, raindex_address), &events) - .unwrap(); + raw_events_to_statements(&RaindexIdentifier::new(1, raindex_address), &events).unwrap(); assert_eq!(batch.len(), 3); let hashes: Vec<_> = batch diff --git a/crates/common/src/local_db/pipeline/adapters/apply.rs b/crates/common/src/local_db/pipeline/adapters/apply.rs index 73a0edb444..fad3b1c284 100644 --- a/crates/common/src/local_db/pipeline/adapters/apply.rs +++ b/crates/common/src/local_db/pipeline/adapters/apply.rs @@ -501,7 +501,13 @@ mod tests { let decoded = vec![deposit_event(token)]; let err = pipeline - .build_batch(&build_target_info(&raindex_id, 1, 1), &[], &decoded, &[], &[]) + .build_batch( + &build_target_info(&raindex_id, 1, 1), + &[], + &decoded, + &[], + &[], + ) .unwrap_err(); use crate::local_db::insert::InsertError; @@ -773,7 +779,13 @@ mod tests { )]; let batch = pipeline - .build_batch(&build_target_info(&raindex_id, 1, 1), &[], &[], &[], &upserts) + .build_batch( + &build_target_info(&raindex_id, 1, 1), + &[], + &[], + &[], + &upserts, + ) .expect("batch ok"); let stmt = batch @@ -817,7 +829,13 @@ mod tests { let b = mk(10, 3); let batch = pipeline - .build_batch(&build_target_info(&raindex_id, 1, 10), &[a, b], &[], &[], &[]) + .build_batch( + &build_target_info(&raindex_id, 1, 10), + &[a, b], + &[], + &[], + &[], + ) .expect("batch ok"); let raws: Vec<_> = batch diff --git a/crates/common/src/local_db/pipeline/adapters/bootstrap.rs b/crates/common/src/local_db/pipeline/adapters/bootstrap.rs index cafffd01c6..53def3a0d4 100644 --- a/crates/common/src/local_db/pipeline/adapters/bootstrap.rs +++ b/crates/common/src/local_db/pipeline/adapters/bootstrap.rs @@ -87,8 +87,9 @@ pub trait BootstrapPipeline { .all(|&t| existing_set.contains(&t.to_ascii_lowercase())); let last_synced_block = if existing_set.contains("target_watermarks") { - let rows: Vec = - db.query_json(&fetch_target_watermark_stmt(raindex_id)).await?; + let rows: Vec = db + .query_json(&fetch_target_watermark_stmt(raindex_id)) + .await?; rows.first().map(|r| r.last_block) } else { None diff --git a/crates/common/src/local_db/pipeline/adapters/events.rs b/crates/common/src/local_db/pipeline/adapters/events.rs index ee11cd63f9..95008d14c1 100644 --- a/crates/common/src/local_db/pipeline/adapters/events.rs +++ b/crates/common/src/local_db/pipeline/adapters/events.rs @@ -58,14 +58,7 @@ impl EventsPipeline for DefaultEventsPipeline { to_block: u64, cfg: &FetchConfig, ) -> Result, LocalDbError> { - fetch_raindex_events( - &self.rpc_client, - raindex_address, - from_block, - to_block, - cfg, - ) - .await + fetch_raindex_events(&self.rpc_client, raindex_address, from_block, to_block, cfg).await } async fn fetch_stores( diff --git a/crates/common/src/local_db/pipeline/adapters/window.rs b/crates/common/src/local_db/pipeline/adapters/window.rs index d3aaff1af2..e0c3d7c5c4 100644 --- a/crates/common/src/local_db/pipeline/adapters/window.rs +++ b/crates/common/src/local_db/pipeline/adapters/window.rs @@ -204,7 +204,12 @@ mod tests { }; let pipe = DefaultWindowPipeline::new(); let (start, _) = pipe - .compute(&db, &sample_raindex_id(), &cfg(100, 0, Some(100), None), 200) + .compute( + &db, + &sample_raindex_id(), + &cfg(100, 0, Some(100), None), + 200, + ) .await .unwrap(); assert_eq!(start, 151); @@ -248,7 +253,12 @@ mod tests { let pipe = DefaultWindowPipeline::new(); // safe_head = 980 let (_, target) = pipe - .compute(&db, &sample_raindex_id(), &cfg(100, 20, None, Some(2000)), 1000) + .compute( + &db, + &sample_raindex_id(), + &cfg(100, 20, None, Some(2000)), + 1000, + ) .await .unwrap(); assert_eq!(target, 980); @@ -279,7 +289,12 @@ mod tests { }; let pipe = DefaultWindowPipeline::new(); let (start, _) = pipe - .compute(&db, &sample_raindex_id(), &cfg(100, 0, Some(150), None), 200) + .compute( + &db, + &sample_raindex_id(), + &cfg(100, 0, Some(150), None), + 200, + ) .await .unwrap(); assert_eq!(start, 151); @@ -294,7 +309,12 @@ mod tests { let pipe = DefaultWindowPipeline::new(); // safe_head = 980; end_override = 500 -> target = 500 let (_, target) = pipe - .compute(&db, &sample_raindex_id(), &cfg(100, 20, None, Some(500)), 1000) + .compute( + &db, + &sample_raindex_id(), + &cfg(100, 20, None, Some(500)), + 1000, + ) .await .unwrap(); assert_eq!(target, 500); @@ -343,7 +363,12 @@ mod tests { let pipe = DefaultWindowPipeline::new(); // base start = 201; end_override = 150; depth=0 so safe_head is high and does not clamp let (start, target) = pipe - .compute(&db, &sample_raindex_id(), &cfg(100, 0, None, Some(150)), 1000) + .compute( + &db, + &sample_raindex_id(), + &cfg(100, 0, None, Some(150)), + 1000, + ) .await .unwrap(); assert_eq!(start, 201); diff --git a/crates/common/src/local_db/pipeline/engine.rs b/crates/common/src/local_db/pipeline/engine.rs index 523a1dac55..a704c22f30 100644 --- a/crates/common/src/local_db/pipeline/engine.rs +++ b/crates/common/src/local_db/pipeline/engine.rs @@ -324,7 +324,11 @@ where self.status.send(SyncPhase::RunningPostSyncExport).await?; self.apply - .export_dump(db, &ctx.target_info.raindex_id, ctx.target_info.target_block) + .export_dump( + db, + &ctx.target_info.raindex_id, + ctx.target_info.target_block, + ) .await } } @@ -709,11 +713,7 @@ mod tests { } fn push_raindex_result(&self, result: Result, LocalDbError>) { - self.inner - .raindex_results - .lock() - .unwrap() - .push_back(result); + self.inner.raindex_results.lock().unwrap().push_back(result); } fn push_store_result(&self, result: Result, LocalDbError>) { @@ -766,11 +766,11 @@ mod tests { to_block: u64, _cfg: &FetchConfig, ) -> Result, LocalDbError> { - self.inner.raindex_calls.lock().unwrap().push(( - raindex_address, - from_block, - to_block, - )); + self.inner + .raindex_calls + .lock() + .unwrap() + .push((raindex_address, from_block, to_block)); self.inner .raindex_results .lock() @@ -1181,9 +1181,7 @@ mod tests { "0x0000000000000000000000000000000000000000000000000000000000000001" ))); harness.window.set_results(vec![Ok((10, 12))]); - harness - .events - .push_raindex_result(Ok(raindex_logs.clone())); + harness.events.push_raindex_result(Ok(raindex_logs.clone())); harness.events.push_decode_result(Ok(vec![ deposit_event(10, 1, token_a, 1), add_order_event(11, 0, store, token_a, token_b, 2), diff --git a/crates/common/src/local_db/pipeline/runner/utils.rs b/crates/common/src/local_db/pipeline/runner/utils.rs index 4c72fd1d66..23c06c75eb 100644 --- a/crates/common/src/local_db/pipeline/runner/utils.rs +++ b/crates/common/src/local_db/pipeline/runner/utils.rs @@ -89,11 +89,13 @@ pub fn build_runner_targets( manifest_end_block: 0, }; - let remote = raindex.local_db_remote.as_ref().ok_or_else(|| { - LocalDbError::MissingLocalDbRemote { - raindex_key: key.clone(), - } - })?; + let remote = + raindex + .local_db_remote + .as_ref() + .ok_or_else(|| LocalDbError::MissingLocalDbRemote { + raindex_key: key.clone(), + })?; targets.push(RunnerTarget { raindex_key: key.clone(), diff --git a/crates/common/src/local_db/query/fetch_vaults/mod.rs b/crates/common/src/local_db/query/fetch_vaults/mod.rs index 899ea05e93..d13efb9c13 100644 --- a/crates/common/src/local_db/query/fetch_vaults/mod.rs +++ b/crates/common/src/local_db/query/fetch_vaults/mod.rs @@ -91,11 +91,7 @@ pub fn build_fetch_vaults_stmt(args: &FetchVaultsArgs) -> Result SqlStatementBatch { - let change_stmt = build_stmt(INSERT_BALANCE_CHANGES_SQL, raindex_id, start_block, end_block); + let change_stmt = build_stmt( + INSERT_BALANCE_CHANGES_SQL, + raindex_id, + start_block, + end_block, + ); let running_stmt = build_stmt(UPSERT_RUNNING_SQL, raindex_id, start_block, end_block); SqlStatementBatch::from(vec![change_stmt, running_stmt]) } diff --git a/crates/common/src/raindex_client/local_db/orders.rs b/crates/common/src/raindex_client/local_db/orders.rs index 2279343ef4..809c110f8b 100644 --- a/crates/common/src/raindex_client/local_db/orders.rs +++ b/crates/common/src/raindex_client/local_db/orders.rs @@ -187,8 +187,14 @@ impl OrdersDataSource for LocalDbOrders<'_> { end_timestamp: Option, _page: Option, ) -> Result, RaindexError> { - let local_trades = - fetch_order_trades(self.db, raindex_id, *order_hash, start_timestamp, end_timestamp).await?; + let local_trades = fetch_order_trades( + self.db, + raindex_id, + *order_hash, + start_timestamp, + end_timestamp, + ) + .await?; local_trades .into_iter() @@ -203,10 +209,14 @@ impl OrdersDataSource for LocalDbOrders<'_> { start_timestamp: Option, end_timestamp: Option, ) -> Result { - Ok( - fetch_order_trades_count(self.db, raindex_id, *order_hash, start_timestamp, end_timestamp) - .await?, + Ok(fetch_order_trades_count( + self.db, + raindex_id, + *order_hash, + start_timestamp, + end_timestamp, ) + .await?) } } diff --git a/crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs b/crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs index cea7adec13..c667705d94 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs @@ -41,8 +41,9 @@ impl ClientBootstrapAdapter { db: &E, raindex_id: &RaindexIdentifier, ) -> Result { - let rows: Vec = - db.query_json(&fetch_target_watermark_stmt(raindex_id)).await?; + let rows: Vec = db + .query_json(&fetch_target_watermark_stmt(raindex_id)) + .await?; Ok(rows.is_empty()) } } diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs index cfbf7a5a5f..0a573d6908 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs @@ -865,10 +865,7 @@ mod tests { ) -> Result { let mut batch = SqlStatementBatch::new(); batch.add(SqlStatement::new("BEGIN TRANSACTION")); - batch.add(SqlStatement::new(format!( - "-- apply {}", - self.raindex_key - ))); + batch.add(SqlStatement::new(format!("-- apply {}", self.raindex_key))); batch.add(SqlStatement::new("COMMIT")); Ok(batch) } @@ -1107,7 +1104,10 @@ raindexes: &fetch_target_watermark_stmt(&target.inputs.raindex_id), json!([]), ); - db.set_json_raw(&fetch_store_addresses_stmt(&target.inputs.raindex_id), json!([])); + db.set_json_raw( + &fetch_store_addresses_stmt(&target.inputs.raindex_id), + json!([]), + ); } } @@ -1200,7 +1200,10 @@ raindexes: fn expect_raindexes(report: &RunReport, expected: &[Address]) { let outcomes = extract_outcomes(report); - let mut addrs: Vec
    = outcomes.iter().map(|o| o.raindex_id.raindex_address).collect(); + let mut addrs: Vec
    = outcomes + .iter() + .map(|o| o.raindex_id.raindex_address) + .collect(); addrs.sort(); let mut expected_sorted = expected.to_vec(); expected_sorted.sort(); diff --git a/crates/common/src/raindex_client/local_db/pipeline/status/wasm.rs b/crates/common/src/raindex_client/local_db/pipeline/status/wasm.rs index fc4703ac69..9cbeb246b1 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/status/wasm.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/status/wasm.rs @@ -48,7 +48,9 @@ impl ClientStatusBus { } pub fn with_ob_id(raindex_id: RaindexIdentifier) -> Self { - Self { raindex_id: Some(raindex_id) } + Self { + raindex_id: Some(raindex_id), + } } fn emit(&self, status: RaindexSyncStatus) { @@ -61,7 +63,10 @@ impl ClientStatusBus { }; let scheduler_state = get_scheduler_state(); - self.emit(RaindexSyncStatus::active(raindex_id.clone(), scheduler_state)); + self.emit(RaindexSyncStatus::active( + raindex_id.clone(), + scheduler_state, + )); } pub fn emit_failure(&self, error: String) { diff --git a/crates/common/src/raindex_client/local_db/query/fetch_last_synced_block.rs b/crates/common/src/raindex_client/local_db/query/fetch_last_synced_block.rs index 4ab8166bb2..98b3264b54 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_last_synced_block.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_last_synced_block.rs @@ -8,7 +8,8 @@ pub async fn fetch_last_synced_block( exec: &E, raindex_id: &RaindexIdentifier, ) -> Result, LocalDbQueryError> { - exec.query_json(&fetch_last_synced_block_stmt(raindex_id)).await + exec.query_json(&fetch_last_synced_block_stmt(raindex_id)) + .await } #[cfg(target_family = "wasm")] @@ -54,14 +55,12 @@ mod wasm_tests { #[wasm_bindgen_test] async fn wrapper_uses_raw_sql_exactly() { - let expected_stmt = - fetch_last_synced_block_stmt(&RaindexIdentifier::new(0, Address::ZERO)); + let expected_stmt = fetch_last_synced_block_stmt(&RaindexIdentifier::new(0, Address::ZERO)); let store = Rc::new(RefCell::new((String::new(), JsValue::UNDEFINED))); let callback = create_sql_capturing_callback("[]", store.clone()); let exec = JsCallbackExecutor::from_ref(&callback); let res = - super::fetch_last_synced_block(&exec, &RaindexIdentifier::new(0, Address::ZERO)) - .await; + super::fetch_last_synced_block(&exec, &RaindexIdentifier::new(0, Address::ZERO)).await; assert!(res.is_ok()); assert_eq!(store.borrow().clone().0, expected_stmt.sql); } diff --git a/crates/common/src/raindex_client/local_db/query/fetch_order_trades.rs b/crates/common/src/raindex_client/local_db/query/fetch_order_trades.rs index f13eb30c50..74ecf2866b 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_order_trades.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_order_trades.rs @@ -12,7 +12,8 @@ pub async fn fetch_order_trades( start_timestamp: Option, end_timestamp: Option, ) -> Result, LocalDbQueryError> { - let stmt = build_fetch_order_trades_stmt(raindex_id, order_hash, start_timestamp, end_timestamp)?; + let stmt = + build_fetch_order_trades_stmt(raindex_id, order_hash, start_timestamp, end_timestamp)?; exec.query_json(&stmt).await } diff --git a/crates/common/src/raindex_client/local_db/query/fetch_order_trades_count.rs b/crates/common/src/raindex_client/local_db/query/fetch_order_trades_count.rs index 0587188a2a..10a66d6413 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_order_trades_count.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_order_trades_count.rs @@ -13,7 +13,8 @@ pub async fn fetch_order_trades_count( start_timestamp: Option, end_timestamp: Option, ) -> Result { - let stmt = build_fetch_trade_count_stmt(raindex_id, order_hash, start_timestamp, end_timestamp)?; + let stmt = + build_fetch_trade_count_stmt(raindex_id, order_hash, start_timestamp, end_timestamp)?; let rows: Vec = exec.query_json(&stmt).await?; Ok(extract_trade_count(&rows)) } diff --git a/crates/common/src/raindex_client/local_db/query/fetch_order_vaults_volume.rs b/crates/common/src/raindex_client/local_db/query/fetch_order_vaults_volume.rs index 7a0568a5a7..caac4ef0ee 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_order_vaults_volume.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_order_vaults_volume.rs @@ -12,8 +12,12 @@ pub async fn fetch_order_vaults_volume( start_timestamp: Option, end_timestamp: Option, ) -> Result, LocalDbQueryError> { - let stmt = - build_fetch_order_vaults_volume_stmt(raindex_id, order_hash, start_timestamp, end_timestamp)?; + let stmt = build_fetch_order_vaults_volume_stmt( + raindex_id, + order_hash, + start_timestamp, + end_timestamp, + )?; exec.query_json(&stmt).await } diff --git a/crates/common/src/raindex_client/local_db/query/fetch_store_addresses.rs b/crates/common/src/raindex_client/local_db/query/fetch_store_addresses.rs index f013bf2476..d9bcd6dd9a 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_store_addresses.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_store_addresses.rs @@ -6,7 +6,8 @@ pub async fn fetch_store_addresses( exec: &E, raindex_id: &RaindexIdentifier, ) -> Result, LocalDbQueryError> { - exec.query_json(&fetch_store_addresses_stmt(raindex_id)).await + exec.query_json(&fetch_store_addresses_stmt(raindex_id)) + .await } #[cfg(all(test, target_family = "wasm"))] @@ -30,8 +31,7 @@ mod wasm_tests { ))); let callback = create_sql_capturing_callback("[]", store.clone()); let exec = JsCallbackExecutor::from_ref(&callback); - let res = - super::fetch_store_addresses(&exec, &RaindexIdentifier::new(1, raindex)).await; + let res = super::fetch_store_addresses(&exec, &RaindexIdentifier::new(1, raindex)).await; assert!(res.is_ok()); assert_eq!(store.borrow().clone().0, expected_stmt.sql); } diff --git a/crates/common/src/raindex_client/local_db/query/fetch_transaction_by_hash.rs b/crates/common/src/raindex_client/local_db/query/fetch_transaction_by_hash.rs index 3c55821945..dbcee73897 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_transaction_by_hash.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_transaction_by_hash.rs @@ -36,12 +36,9 @@ mod wasm_tests { let callback = create_sql_capturing_callback("[]", store.clone()); let exec = JsCallbackExecutor::from_ref(&callback); - let res = super::fetch_transaction_by_hash( - &exec, - &RaindexIdentifier::new(1, raindex), - tx_hash, - ) - .await; + let res = + super::fetch_transaction_by_hash(&exec, &RaindexIdentifier::new(1, raindex), tx_hash) + .await; assert!(res.is_ok()); assert_eq!(store.borrow().clone().0, expected_stmt.sql); } @@ -71,12 +68,9 @@ mod wasm_tests { let callback = create_sql_capturing_callback(&row_json, store.clone()); let exec = JsCallbackExecutor::from_ref(&callback); - let res = super::fetch_transaction_by_hash( - &exec, - &RaindexIdentifier::new(1, raindex), - tx_hash, - ) - .await; + let res = + super::fetch_transaction_by_hash(&exec, &RaindexIdentifier::new(1, raindex), tx_hash) + .await; assert!(res.is_ok()); let rows = res.unwrap(); assert_eq!(rows.len(), 1); diff --git a/crates/common/src/raindex_client/local_db/query/fetch_vault_balance_changes.rs b/crates/common/src/raindex_client/local_db/query/fetch_vault_balance_changes.rs index 88b46ef626..0ce3f8049f 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_vault_balance_changes.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_vault_balance_changes.rs @@ -17,8 +17,13 @@ pub async fn fetch_vault_balance_changes( ) -> Result, LocalDbQueryError> { let filter_kinds: Option> = filter_types.map(|filters| filters.iter().map(|f| f.to_kind()).collect()); - let stmt = - build_fetch_balance_changes_stmt(raindex_id, vault_id, token, owner, filter_kinds.as_deref())?; + let stmt = build_fetch_balance_changes_stmt( + raindex_id, + vault_id, + token, + owner, + filter_kinds.as_deref(), + )?; exec.query_json(&stmt).await } diff --git a/crates/common/src/raindex_client/local_db/state.rs b/crates/common/src/raindex_client/local_db/state.rs index 1a0d4b179a..a7b38cb8a7 100644 --- a/crates/common/src/raindex_client/local_db/state.rs +++ b/crates/common/src/raindex_client/local_db/state.rs @@ -423,8 +423,8 @@ raindexes: "#, version = SpecVersion::current() ); - let yaml = RaindexYaml::new(vec![yaml_str], RaindexYamlValidation::default()) - .expect("valid yaml"); + let yaml = + RaindexYaml::new(vec![yaml_str], RaindexYamlValidation::default()).expect("valid yaml"); let ids = LocalDbState::compute_chain_ids(&yaml); assert_eq!(ids, HashSet::from([42161])); assert!(!ids.contains(&137)); @@ -451,8 +451,8 @@ raindexes: "#, version = SpecVersion::current() ); - let yaml = RaindexYaml::new(vec![yaml_str], RaindexYamlValidation::default()) - .expect("valid yaml"); + let yaml = + RaindexYaml::new(vec![yaml_str], RaindexYamlValidation::default()).expect("valid yaml"); let ids = LocalDbState::compute_chain_ids(&yaml); assert!(ids.is_empty()); } diff --git a/crates/common/src/raindex_client/local_db/status.rs b/crates/common/src/raindex_client/local_db/status.rs index 717c7ae3f5..18382981db 100644 --- a/crates/common/src/raindex_client/local_db/status.rs +++ b/crates/common/src/raindex_client/local_db/status.rs @@ -62,7 +62,13 @@ impl RaindexSyncStatus { } pub fn active(raindex_id: RaindexIdentifier, scheduler_state: SchedulerState) -> Self { - Self::new(raindex_id, LocalDbStatus::Active, scheduler_state, None, None) + Self::new( + raindex_id, + LocalDbStatus::Active, + scheduler_state, + None, + None, + ) } pub fn failure(raindex_id: RaindexIdentifier, error: String) -> Self { diff --git a/crates/common/src/raindex_client/local_db/vaults.rs b/crates/common/src/raindex_client/local_db/vaults.rs index 1092ba65d8..ce2b9b54b6 100644 --- a/crates/common/src/raindex_client/local_db/vaults.rs +++ b/crates/common/src/raindex_client/local_db/vaults.rs @@ -275,7 +275,10 @@ mod tests { Address::from_str("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB").unwrap(); let data_source = LocalDbVaults::new(&local_db, Rc::new(client)); let retrieved = data_source - .get_by_id(&RaindexIdentifier::new(42161, raindex_addr), &vault_id_bytes) + .get_by_id( + &RaindexIdentifier::new(42161, raindex_addr), + &vault_id_bytes, + ) .await .expect("local vault retrieval should succeed") .expect("vault should be found"); diff --git a/crates/common/src/raindex_client/mod.rs b/crates/common/src/raindex_client/mod.rs index cfbb8a07cb..3fe7e30b15 100644 --- a/crates/common/src/raindex_client/mod.rs +++ b/crates/common/src/raindex_client/mod.rs @@ -47,9 +47,9 @@ use wasm_bindgen_utils::{impl_wasm_traits, prelude::*, wasm_export}; pub mod add_orders; pub mod local_db; pub mod order_quotes; -pub mod raindex_yaml; pub mod orders; pub mod orders_list; +pub mod raindex_yaml; pub mod remove_orders; pub mod take_orders; pub mod trades; @@ -260,9 +260,7 @@ impl RaindexClient { &self, raindex_address: Address, ) -> Result { - let raindex = self - .raindex_yaml - .get_raindex_by_address(raindex_address)?; + let raindex = self.raindex_yaml.get_raindex_by_address(raindex_address)?; Ok(RaindexSubgraphClient::new(raindex.subgraph.url.clone())) } diff --git a/crates/common/src/raindex_client/orders.rs b/crates/common/src/raindex_client/orders.rs index 8c231483b5..2662766bca 100644 --- a/crates/common/src/raindex_client/orders.rs +++ b/crates/common/src/raindex_client/orders.rs @@ -36,8 +36,8 @@ use rain_metadata::{KnownMagic, RainMetaDocumentV1Item}; use raindex_subgraph_client::{ types::{ common::{ - SgBigInt, SgBytes, SgOrder, SgOrderAsIO, SgRaindex, SgOrdersListFilterArgs, - SgOrdersTokensFilterArgs, SgVault, + SgBigInt, SgBytes, SgOrder, SgOrderAsIO, SgOrdersListFilterArgs, + SgOrdersTokensFilterArgs, SgRaindex, SgVault, }, Id, }, @@ -463,7 +463,8 @@ impl RaindexOrder { } #[wasm_export(skip)] pub fn get_raindex_subgraph_client(&self) -> Result { - self.raindex_client.get_raindex_subgraph_client(self.raindex) + self.raindex_client + .get_raindex_subgraph_client(self.raindex) } #[wasm_export(skip)] pub fn get_rpc_urls(&self) -> Result, RaindexError> { @@ -1060,7 +1061,9 @@ impl OrdersDataSource for SubgraphOrders<'_> { order_hash: &B256, ) -> Result, RaindexError> { let raindex_client = ClientRef::new(self.client.clone()); - let client = self.client.get_raindex_subgraph_client(raindex_id.raindex_address)?; + let client = self + .client + .get_raindex_subgraph_client(raindex_id.raindex_address)?; let order = match client .order_detail_by_hash(SgBytes(order_hash.to_string())) .await @@ -1069,7 +1072,8 @@ impl OrdersDataSource for SubgraphOrders<'_> { Err(RaindexSubgraphClientError::Empty) => return Ok(None), Err(err) => return Err(err.into()), }; - let order = RaindexOrder::try_from_sg_order(raindex_client, raindex_id.chain_id, order, None)?; + let order = + RaindexOrder::try_from_sg_order(raindex_client, raindex_id.chain_id, order, None)?; Ok(Some(order)) } @@ -1131,7 +1135,9 @@ impl OrdersDataSource for SubgraphOrders<'_> { end_timestamp: Option, page: Option, ) -> Result, RaindexError> { - let client = self.client.get_raindex_subgraph_client(raindex_id.raindex_address)?; + let client = self + .client + .get_raindex_subgraph_client(raindex_id.raindex_address)?; let order = client .order_detail_by_hash(SgBytes(order_hash.to_string())) @@ -1162,7 +1168,9 @@ impl OrdersDataSource for SubgraphOrders<'_> { start_timestamp: Option, end_timestamp: Option, ) -> Result { - let client = self.client.get_raindex_subgraph_client(raindex_id.raindex_address)?; + let client = self + .client + .get_raindex_subgraph_client(raindex_id.raindex_address)?; let order = client .order_detail_by_hash(SgBytes(order_hash.to_string())) @@ -1537,8 +1545,7 @@ mod tests { ContentEncoding, ContentLanguage, ContentType, KnownMagic, RainMetaDocumentV1Item, }; use raindex_subgraph_client::types::common::{ - SgAddOrder, SgBigInt, SgBytes, SgErc20, SgOrderAsIO, SgRaindex, SgTransaction, - SgVault, + SgAddOrder, SgBigInt, SgBytes, SgErc20, SgOrderAsIO, SgRaindex, SgTransaction, SgVault, }; use raindex_subgraph_client::utils::float::*; use serde_bytes::ByteBuf; diff --git a/crates/common/src/raindex_client/orders_list.rs b/crates/common/src/raindex_client/orders_list.rs index dda1bff8fd..1e0dfba056 100644 --- a/crates/common/src/raindex_client/orders_list.rs +++ b/crates/common/src/raindex_client/orders_list.rs @@ -116,10 +116,7 @@ mod tests { .unwrap(); client .get_order_by_hash( - &RaindexIdentifier::new( - 1, - Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), - ), + &RaindexIdentifier::new(1, Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap()), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) .await diff --git a/crates/common/src/raindex_client/remove_orders.rs b/crates/common/src/raindex_client/remove_orders.rs index 996696ce20..de7ef3ad95 100644 --- a/crates/common/src/raindex_client/remove_orders.rs +++ b/crates/common/src/raindex_client/remove_orders.rs @@ -229,9 +229,7 @@ mod tests { }, local_db::RaindexIdentifier, raindex_client::local_db::LocalDb, - raindex_client::tests::{ - get_test_yaml, new_with_local_db, CHAIN_ID_1_RAINDEX_ADDRESS, - }, + raindex_client::tests::{get_test_yaml, new_with_local_db, CHAIN_ID_1_RAINDEX_ADDRESS}, }; use alloy::primitives::{b256, Address, Bytes, U256}; use async_trait::async_trait; @@ -759,13 +757,7 @@ mod tests { .await; let res = client - .get_remove_orders_for_transaction( - 137, - raindex_address, - tx_hash, - Some(3), - Some(1), - ) + .get_remove_orders_for_transaction(137, raindex_address, tx_hash, Some(3), Some(1)) .await .unwrap(); @@ -815,13 +807,7 @@ mod tests { .await; let err = client - .get_remove_orders_for_transaction( - 137, - raindex_address, - tx_hash, - Some(2), - Some(1), - ) + .get_remove_orders_for_transaction(137, raindex_address, tx_hash, Some(2), Some(1)) .await .unwrap_err(); diff --git a/crates/common/src/raindex_client/take_orders/e2e_tests.rs b/crates/common/src/raindex_client/take_orders/e2e_tests.rs index ddc73a1eaa..650ff5e155 100644 --- a/crates/common/src/raindex_client/take_orders/e2e_tests.rs +++ b/crates/common/src/raindex_client/take_orders/e2e_tests.rs @@ -978,13 +978,11 @@ async fn test_cross_raindex_selection_picks_best_book() { ) .await; - let dotrain_a = - create_dotrain_config_for_raindex(&setup, setup.raindex_a, "0x01", "5", "2"); + let dotrain_a = create_dotrain_config_for_raindex(&setup, setup.raindex_a, "0x01", "5", "2"); let (order_bytes_a, order_hash_a, _order_v4_a) = deploy_order_to_raindex(&setup, setup.raindex_a, dotrain_a).await; - let dotrain_b = - create_dotrain_config_for_raindex(&setup, setup.raindex_b, "0x02", "8", "2"); + let dotrain_b = create_dotrain_config_for_raindex(&setup, setup.raindex_b, "0x02", "8", "2"); let (order_bytes_b, order_hash_b, order_v4_b) = deploy_order_to_raindex(&setup, setup.raindex_b, dotrain_b).await; @@ -1130,13 +1128,11 @@ async fn test_cross_raindex_selection_flips_when_economics_flip() { ) .await; - let dotrain_a = - create_dotrain_config_for_raindex(&setup, setup.raindex_a, "0x01", "10", "2"); + let dotrain_a = create_dotrain_config_for_raindex(&setup, setup.raindex_a, "0x01", "10", "2"); let (order_bytes_a, order_hash_a, order_v4_a) = deploy_order_to_raindex(&setup, setup.raindex_a, dotrain_a).await; - let dotrain_b = - create_dotrain_config_for_raindex(&setup, setup.raindex_b, "0x02", "3", "2"); + let dotrain_b = create_dotrain_config_for_raindex(&setup, setup.raindex_b, "0x02", "3", "2"); let (order_bytes_b, order_hash_b, _order_v4_b) = deploy_order_to_raindex(&setup, setup.raindex_b, dotrain_b).await; @@ -1272,13 +1268,11 @@ async fn test_cross_raindex_economic_selection_prefers_best_yield() { ) .await; - let dotrain_a = - create_dotrain_config_for_raindex(&setup, setup.raindex_a, "0x01", "5", "1"); + let dotrain_a = create_dotrain_config_for_raindex(&setup, setup.raindex_a, "0x01", "5", "1"); let (order_bytes_a, order_hash_a, order_v4_a) = deploy_order_to_raindex(&setup, setup.raindex_a, dotrain_a).await; - let dotrain_b = - create_dotrain_config_for_raindex(&setup, setup.raindex_b, "0x02", "8", "1.5"); + let dotrain_b = create_dotrain_config_for_raindex(&setup, setup.raindex_b, "0x02", "8", "1.5"); let (order_bytes_b, order_hash_b, _order_v4_b) = deploy_order_to_raindex(&setup, setup.raindex_b, dotrain_b).await; @@ -2081,13 +2075,11 @@ async fn test_spend_mode_cross_raindex_selection() { ) .await; - let dotrain_a = - create_dotrain_config_for_raindex(&setup, setup.raindex_a, "0x01", "50", "2"); + let dotrain_a = create_dotrain_config_for_raindex(&setup, setup.raindex_a, "0x01", "50", "2"); let (order_bytes_a, order_hash_a, _order_v4_a) = deploy_order_to_raindex(&setup, setup.raindex_a, dotrain_a).await; - let dotrain_b = - create_dotrain_config_for_raindex(&setup, setup.raindex_b, "0x02", "80", "2"); + let dotrain_b = create_dotrain_config_for_raindex(&setup, setup.raindex_b, "0x02", "80", "2"); let (order_bytes_b, order_hash_b, order_v4_b) = deploy_order_to_raindex(&setup, setup.raindex_b, dotrain_b).await; diff --git a/crates/common/src/raindex_client/take_orders/mod.rs b/crates/common/src/raindex_client/take_orders/mod.rs index 3faee065e2..86ebeeafcf 100644 --- a/crates/common/src/raindex_client/take_orders/mod.rs +++ b/crates/common/src/raindex_client/take_orders/mod.rs @@ -97,11 +97,8 @@ impl RaindexClient { ) .await?; - let (best_raindex, best_sim) = selection::select_best_raindex_simulation( - candidates.clone(), - req.mode, - req.price_cap, - )?; + let (best_raindex, best_sim) = + selection::select_best_raindex_simulation(candidates.clone(), req.mode, req.price_cap)?; let mut built = build_take_orders_config_from_simulation(best_sim.clone(), req.mode, req.price_cap)? diff --git a/crates/common/src/raindex_client/take_orders/selection.rs b/crates/common/src/raindex_client/take_orders/selection.rs index f8adb7624e..1f1673080d 100644 --- a/crates/common/src/raindex_client/take_orders/selection.rs +++ b/crates/common/src/raindex_client/take_orders/selection.rs @@ -268,11 +268,8 @@ mod tests { for _ in 0..20 { let candidates = vec![higher_candidate.clone(), lower_candidate.clone()]; - let result = select_best_raindex_simulation( - candidates, - buy_up_to(buy_target), - high_price_cap(), - ); + let result = + select_best_raindex_simulation(candidates, buy_up_to(buy_target), high_price_cap()); assert!(result.is_ok()); let (winner, sim) = result.unwrap(); @@ -303,11 +300,8 @@ mod tests { for _ in 0..20 { let candidates = vec![worse_candidate.clone(), better_candidate.clone()]; - let result = select_best_raindex_simulation( - candidates, - buy_up_to(buy_target), - high_price_cap(), - ); + let result = + select_best_raindex_simulation(candidates, buy_up_to(buy_target), high_price_cap()); assert!(result.is_ok()); let (winner, sim) = result.unwrap(); @@ -330,11 +324,8 @@ mod tests { let candidates = vec![candidate]; let spend_budget = Float::parse("100".to_string()).unwrap(); - let result = select_best_raindex_simulation( - candidates, - spend_up_to(spend_budget), - high_price_cap(), - ); + let result = + select_best_raindex_simulation(candidates, spend_up_to(spend_budget), high_price_cap()); assert!(result.is_ok()); let (addr, sim) = result.unwrap(); @@ -362,11 +353,8 @@ mod tests { let candidates = vec![bad_rate_candidate, good_rate_candidate]; let spend_budget = Float::parse("100".to_string()).unwrap(); - let result = select_best_raindex_simulation( - candidates, - spend_up_to(spend_budget), - high_price_cap(), - ); + let result = + select_best_raindex_simulation(candidates, spend_up_to(spend_budget), high_price_cap()); assert!(result.is_ok()); let (winner, sim) = result.unwrap(); diff --git a/crates/common/src/raindex_client/trades.rs b/crates/common/src/raindex_client/trades.rs index 50fe31f312..80e6b9b001 100644 --- a/crates/common/src/raindex_client/trades.rs +++ b/crates/common/src/raindex_client/trades.rs @@ -145,13 +145,25 @@ impl RaindexOrder { QuerySource::LocalDb(local_db) => { let local_source = LocalDbOrders::new(&local_db, ClientRef::clone(&raindex_client)); local_source - .trades_list(&raindex_id, &order_hash, start_timestamp, end_timestamp, page) + .trades_list( + &raindex_id, + &order_hash, + start_timestamp, + end_timestamp, + page, + ) .await } QuerySource::Subgraph => { let subgraph_source = SubgraphOrders::new(&raindex_client); subgraph_source - .trades_list(&raindex_id, &order_hash, start_timestamp, end_timestamp, page) + .trades_list( + &raindex_id, + &order_hash, + start_timestamp, + end_timestamp, + page, + ) .await } } diff --git a/crates/common/src/raindex_client/vaults.rs b/crates/common/src/raindex_client/vaults.rs index 743cdda2da..2b28d254c1 100644 --- a/crates/common/src/raindex_client/vaults.rs +++ b/crates/common/src/raindex_client/vaults.rs @@ -29,9 +29,8 @@ use raindex_subgraph_client::{ performance::vol::{VaultVolume, VolumeDetails}, types::{ common::{ - SgBigInt, SgBytes, SgErc20, SgOrderAsIO, SgRaindex, SgTradeVaultBalanceChange, - SgVault, SgVaultBalanceChangeType, SgVaultBalanceChangeUnwrapped, - SgVaultsListFilterArgs, + SgBigInt, SgBytes, SgErc20, SgOrderAsIO, SgRaindex, SgTradeVaultBalanceChange, SgVault, + SgVaultBalanceChangeType, SgVaultBalanceChangeUnwrapped, SgVaultsListFilterArgs, }, Id, }, @@ -321,7 +320,8 @@ impl RaindexVaultToken { impl RaindexVault { #[wasm_export(skip)] pub fn get_raindex_subgraph_client(&self) -> Result { - self.raindex_client.get_raindex_subgraph_client(self.raindex) + self.raindex_client + .get_raindex_subgraph_client(self.raindex) } /// Fetches balance change history for a vault @@ -1365,11 +1365,8 @@ impl RaindexClient { ) -> Result { let raindex_address = Address::from_str(&raindex_address)?; let vault_id = Bytes::from_str(&vault_id)?; - self.get_vault( - &RaindexIdentifier::new(chain_id, raindex_address), - vault_id, - ) - .await + self.get_vault(&RaindexIdentifier::new(chain_id, raindex_address), vault_id) + .await } /// Fetches all unique tokens that exist in vaults. @@ -1522,14 +1519,17 @@ impl VaultsDataSource for SubgraphVaults<'_> { vault_id: &Bytes, ) -> Result, RaindexError> { let raindex_client = ClientRef::new(self.client.clone()); - let client = self.client.get_raindex_subgraph_client(raindex_id.raindex_address)?; + let client = self + .client + .get_raindex_subgraph_client(raindex_id.raindex_address)?; let vault = match client.vault_detail(Id::new(vault_id.to_string())).await { Ok(vault) => vault, Err(RaindexSubgraphClientError::Empty) => return Ok(None), Err(err) => return Err(err.into()), }; - let vault = RaindexVault::try_from_sg_vault(raindex_client, raindex_id.chain_id, vault, None)?; + let vault = + RaindexVault::try_from_sg_vault(raindex_client, raindex_id.chain_id, vault, None)?; Ok(Some(vault)) } diff --git a/crates/common/src/remove_order.rs b/crates/common/src/remove_order.rs index 0c39be66b0..12e334f318 100644 --- a/crates/common/src/remove_order.rs +++ b/crates/common/src/remove_order.rs @@ -7,9 +7,7 @@ use alloy_ethers_typecast::WritableClientError; #[cfg(not(target_family = "wasm"))] use alloy_ethers_typecast::{WriteTransaction, WriteTransactionStatus}; use raindex_bindings::IRaindexV6::removeOrder3Call; -use raindex_subgraph_client::types::{ - common::SgOrder, order_detail_traits::OrderDetailError, -}; +use raindex_subgraph_client::types::{common::SgOrder, order_detail_traits::OrderDetailError}; use serde::{Deserialize, Serialize}; use thiserror::Error; @@ -80,9 +78,7 @@ mod tests { use super::*; use alloy::primitives::Address; use raindex_bindings::IRaindexV6::removeOrder3Call; - use raindex_subgraph_client::types::common::{ - SgBigInt, SgBytes, SgErc20, SgRaindex, SgVault, - }; + use raindex_subgraph_client::types::common::{SgBigInt, SgBytes, SgErc20, SgRaindex, SgVault}; use raindex_subgraph_client::utils::float::*; fn get_order() -> SgOrder { diff --git a/crates/common/src/take_orders/preflight.rs b/crates/common/src/take_orders/preflight.rs index 3c545d5fda..f5e72154bb 100644 --- a/crates/common/src/take_orders/preflight.rs +++ b/crates/common/src/take_orders/preflight.rs @@ -207,14 +207,9 @@ pub async fn find_failing_order_index( data: config.data.clone(), }; - let result = simulate_take_orders( - provider, - raindex, - taker, - &single_order_config, - block_number, - ) - .await; + let result = + simulate_take_orders(provider, raindex, taker, &single_order_config, block_number) + .await; if result.is_err() { return Some(idx); diff --git a/crates/common/src/test_helpers.rs b/crates/common/src/test_helpers.rs index ead17c7f72..9b727ca9d5 100644 --- a/crates/common/src/test_helpers.rs +++ b/crates/common/src/test_helpers.rs @@ -178,9 +178,7 @@ _ _: 0 0; pub mod local_evm { use alloy::primitives::{Address, B256, U256}; use rain_math_float::Float; - use raindex_subgraph_client::types::common::{ - SgBigInt, SgBytes, SgErc20, SgRaindex, SgVault, - }; + use raindex_subgraph_client::types::common::{SgBigInt, SgBytes, SgErc20, SgRaindex, SgVault}; use raindex_test_fixtures::LocalEvm; pub struct TestSetup { @@ -596,11 +594,7 @@ pub mod candidates { use super::orders::make_basic_order; - pub fn make_candidate( - raindex: Address, - max_output: Float, - ratio: Float, - ) -> TakeOrderCandidate { + pub fn make_candidate(raindex: Address, max_output: Float, ratio: Float) -> TakeOrderCandidate { TakeOrderCandidate { raindex, order: make_basic_order(Address::from([4u8; 20]), Address::from([5u8; 20])), @@ -909,9 +903,7 @@ amount price: {max_output} {ratio}; pub mod subgraph { use alloy::primitives::{Address, B256}; use raindex_app_settings::spec_version::SpecVersion; - use raindex_subgraph_client::types::common::{ - SgBigInt, SgBytes, SgOrder, SgRaindex, SgVault, - }; + use raindex_subgraph_client::types::common::{SgBigInt, SgBytes, SgOrder, SgRaindex, SgVault}; use serde_json::json; use super::local_evm::{MultiRaindexTestSetup, TestSetup}; diff --git a/crates/common/src/withdraw.rs b/crates/common/src/withdraw.rs index f02d19cc90..8fe61c9c0f 100644 --- a/crates/common/src/withdraw.rs +++ b/crates/common/src/withdraw.rs @@ -39,10 +39,8 @@ impl WithdrawArgs { let (ledger_client, _) = transaction_args.clone().try_into_ledger_client().await?; let withdraw_call: withdraw4Call = self.clone().into(); - let params = transaction_args.try_into_write_contract_parameters( - withdraw_call, - transaction_args.raindex_address, - )?; + let params = transaction_args + .try_into_write_contract_parameters(withdraw_call, transaction_args.raindex_address)?; WriteTransaction::new(ledger_client, params, 4, transaction_status_changed) .execute() diff --git a/crates/js_api/src/gui/order_operations.rs b/crates/js_api/src/gui/order_operations.rs index 1463426c61..209f3021ce 100644 --- a/crates/js_api/src/gui/order_operations.rs +++ b/crates/js_api/src/gui/order_operations.rs @@ -13,9 +13,7 @@ use raindex_app_settings::{ order::{OrderIOCfg, VaultType}, raindex::RaindexCfg, }; -use raindex_bindings::{ - IRaindexV6::deposit4Call, Raindex::multicallCall, IERC20::approveCall, -}; +use raindex_bindings::{IRaindexV6::deposit4Call, Raindex::multicallCall, IERC20::approveCall}; use raindex_common::{ add_order::AddOrderArgs, deposit::DepositArgs, erc20::ERC20, transaction::TransactionArgs, }; @@ -855,8 +853,7 @@ impl DotrainOrderGui { fn get_metaboard_client(&self) -> Result { let deployment = self.get_current_deployment()?; let raindex_yaml = self.dotrain_order.raindex_yaml(); - let metaboard_cfg = - raindex_yaml.get_metaboard(&deployment.deployment.order.network.key)?; + let metaboard_cfg = raindex_yaml.get_metaboard(&deployment.deployment.order.network.key)?; Ok(MetaboardSubgraphClient::new(metaboard_cfg.url.clone())) } diff --git a/crates/js_api/src/gui/state_management.rs b/crates/js_api/src/gui/state_management.rs index 0d1a34d5f7..89c88345ff 100644 --- a/crates/js_api/src/gui/state_management.rs +++ b/crates/js_api/src/gui/state_management.rs @@ -547,9 +547,7 @@ mod tests { }; use alloy::primitives::{Address, U256}; use js_sys::{eval, Reflect}; - use raindex_app_settings::{ - network::NetworkCfg, order::VaultType, yaml::YamlParsableHash, - }; + use raindex_app_settings::{network::NetworkCfg, order::VaultType, yaml::YamlParsableHash}; use raindex_common::dotrain::RainDocument; use raindex_common::dotrain_order::DotrainOrder; use std::str::FromStr; diff --git a/crates/js_api/src/yaml/mod.rs b/crates/js_api/src/yaml/mod.rs index c2039e085b..596e2ea335 100644 --- a/crates/js_api/src/yaml/mod.rs +++ b/crates/js_api/src/yaml/mod.rs @@ -116,8 +116,7 @@ impl RaindexYaml { #[wasm_export(param_description = "The hexadecimal address of the raindex contract")] raindex_address: &str, ) -> Result { - let address = - Address::from_str(raindex_address).map_err(RaindexYamlError::FromHexError)?; + let address = Address::from_str(raindex_address).map_err(RaindexYamlError::FromHexError)?; Ok(self.yaml.get_raindex_by_address(address)?) } @@ -405,8 +404,7 @@ pub(crate) mod tests { #[wasm_bindgen_test] async fn test_get_tokens_multiple_networks() { - let mut raindex_yaml = - RaindexYaml::new(vec![get_yaml_multiple_networks()], None).unwrap(); + let mut raindex_yaml = RaindexYaml::new(vec![get_yaml_multiple_networks()], None).unwrap(); let tokens = raindex_yaml.get_tokens().await.unwrap(); assert_eq!(tokens.len(), 2); diff --git a/crates/rest_api/src/routes/take_orders.rs b/crates/rest_api/src/routes/take_orders.rs index 9aece4aba9..c3814b499e 100644 --- a/crates/rest_api/src/routes/take_orders.rs +++ b/crates/rest_api/src/routes/take_orders.rs @@ -148,9 +148,7 @@ async fn execute_take_orders( if let Some(approval_info) = result.approval_info() { let amount = approval_info.amount().format().map_err(|e| { - ApiError::Raindex(raindex_common::raindex_client::RaindexError::Float( - e, - )) + ApiError::Raindex(raindex_common::raindex_client::RaindexError::Float(e)) })?; Ok(TakeOrdersApiResponse::NeedsApproval(ApprovalApiResponse { @@ -162,9 +160,7 @@ async fn execute_take_orders( })) } else if let Some(take_orders_info) = result.take_orders_info() { let effective_price = take_orders_info.effective_price().format().map_err(|e| { - ApiError::Raindex(raindex_common::raindex_client::RaindexError::Float( - e, - )) + ApiError::Raindex(raindex_common::raindex_client::RaindexError::Float(e)) })?; let prices: Result, _> = take_orders_info @@ -172,23 +168,17 @@ async fn execute_take_orders( .iter() .map(|p| { p.format().map_err(|e| { - ApiError::Raindex(raindex_common::raindex_client::RaindexError::Float( - e, - )) + ApiError::Raindex(raindex_common::raindex_client::RaindexError::Float(e)) }) }) .collect(); let expected_sell = take_orders_info.expected_sell().format().map_err(|e| { - ApiError::Raindex(raindex_common::raindex_client::RaindexError::Float( - e, - )) + ApiError::Raindex(raindex_common::raindex_client::RaindexError::Float(e)) })?; let max_sell_cap = take_orders_info.max_sell_cap().format().map_err(|e| { - ApiError::Raindex(raindex_common::raindex_client::RaindexError::Float( - e, - )) + ApiError::Raindex(raindex_common::raindex_client::RaindexError::Float(e)) })?; Ok(TakeOrdersApiResponse::Ready(TakeOrdersReadyResponse { diff --git a/crates/settings/src/lib.rs b/crates/settings/src/lib.rs index 5370fbc896..a58c6fff8c 100644 --- a/crates/settings/src/lib.rs +++ b/crates/settings/src/lib.rs @@ -9,8 +9,8 @@ pub mod local_db_sync; pub mod metaboard; pub mod network; pub mod order; -pub mod raindex; pub mod plot_source; +pub mod raindex; pub mod rainlang; pub mod remote; pub mod remote_networks; @@ -30,8 +30,8 @@ pub(crate) use gui::*; pub(crate) use local_db_sync::*; pub(crate) use network::*; pub(crate) use order::*; -pub(crate) use raindex::*; pub(crate) use plot_source::*; +pub(crate) use raindex::*; pub(crate) use rainlang::*; pub(crate) use remote_networks::*; pub(crate) use scenario::*; diff --git a/crates/settings/src/local_db_manifest.rs b/crates/settings/src/local_db_manifest.rs index 7062f8c473..cc4ca5f262 100644 --- a/crates/settings/src/local_db_manifest.rs +++ b/crates/settings/src/local_db_manifest.rs @@ -106,7 +106,11 @@ impl LocalDbManifest { self.networks .values() .find(|n| n.chain_id == chain_id) - .and_then(|n| n.raindexes.iter().find(|raindex_entry| raindex_entry.address == address)) + .and_then(|n| { + n.raindexes + .iter() + .find(|raindex_entry| raindex_entry.address == address) + }) } pub fn new() -> Self { @@ -612,7 +616,8 @@ end-block-hash: "0x0abc" end-block-time-ms: 1 "#; let raindex_doc = load(ob_ok); - let raindex_entry = parse_single_raindex(0, &raindex_doc, base_loc).expect("raindex parses"); + let raindex_entry = + parse_single_raindex(0, &raindex_doc, base_loc).expect("raindex parses"); assert_eq!(raindex_entry.end_block, 1); assert_eq!(raindex_entry.end_block_time_ms, 1); diff --git a/crates/settings/src/order.rs b/crates/settings/src/order.rs index 8f10781460..09ddb579f2 100644 --- a/crates/settings/src/order.rs +++ b/crates/settings/src/order.rs @@ -350,8 +350,7 @@ impl OrderCfg { } if let Some(raindex_key) = optional_string(order_yaml, "raindex") { - let key = - RaindexCfg::parse_network_key(documents.clone(), &raindex_key)?; + let key = RaindexCfg::parse_network_key(documents.clone(), &raindex_key)?; if let Some(ref existing_key) = network_key { if *existing_key != key { diff --git a/crates/settings/src/raindex.rs b/crates/settings/src/raindex.rs index a0b8b91a1b..d09528b98f 100644 --- a/crates/settings/src/raindex.rs +++ b/crates/settings/src/raindex.rs @@ -584,8 +584,7 @@ raindexes: let yaml = r#" raindexes: test "#; - let error = - RaindexCfg::parse_network_key(vec![get_document(yaml)], "order1").unwrap_err(); + let error = RaindexCfg::parse_network_key(vec![get_document(yaml)], "order1").unwrap_err(); assert_eq!( error, YamlError::Field { @@ -602,8 +601,7 @@ raindexes: test raindexes: - test "#; - let error = - RaindexCfg::parse_network_key(vec![get_document(yaml)], "order1").unwrap_err(); + let error = RaindexCfg::parse_network_key(vec![get_document(yaml)], "order1").unwrap_err(); assert_eq!( error, YamlError::Field { @@ -620,8 +618,7 @@ raindexes: raindexes: - test: test "#; - let error = - RaindexCfg::parse_network_key(vec![get_document(yaml)], "order1").unwrap_err(); + let error = RaindexCfg::parse_network_key(vec![get_document(yaml)], "order1").unwrap_err(); assert_eq!( error, YamlError::Field { @@ -698,10 +695,7 @@ raindexes: "#; let raindexes = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); assert_eq!(raindexes.len(), 3); - assert_eq!( - raindexes.get("TestRaindex1").unwrap().deployment_block, - 0 - ); + assert_eq!(raindexes.get("TestRaindex1").unwrap().deployment_block, 0); assert_eq!( raindexes.get("TestRaindex2").unwrap().deployment_block, 18446744073709551615 @@ -862,7 +856,10 @@ raindexes: "#; let raindexes = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); let raindex_cfg = raindexes.get("TestRaindex").unwrap(); - let remote = raindex_cfg.local_db_remote.as_ref().expect("expected remote"); + let remote = raindex_cfg + .local_db_remote + .as_ref() + .expect("expected remote"); assert_eq!(remote.key, "TestRaindex"); assert_eq!( remote.url.to_string(), @@ -892,7 +889,10 @@ raindexes: "#; let raindexes = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); let raindex_cfg = raindexes.get("TestRaindex").unwrap(); - let remote = raindex_cfg.local_db_remote.as_ref().expect("expected remote"); + let remote = raindex_cfg + .local_db_remote + .as_ref() + .expect("expected remote"); assert_eq!(remote.key, "mainnet"); assert_eq!( remote.url.to_string(), diff --git a/crates/settings/src/yaml/mod.rs b/crates/settings/src/yaml/mod.rs index 51bffb2eb0..8ec8b58fe4 100644 --- a/crates/settings/src/yaml/mod.rs +++ b/crates/settings/src/yaml/mod.rs @@ -7,8 +7,8 @@ pub mod raindex; use crate::{ remote_networks::ParseRemoteNetworksError, remote_tokens::ParseRemoteTokensError, NetworkCfg, ParseDeploymentConfigSourceError, ParseNetworkConfigSourceError, ParseOrderConfigSourceError, - ParseRaindexConfigSourceError, ParseRainlangConfigSourceError, - ParseScenarioConfigSourceError, ParseTokenConfigSourceError, TokenCfg, + ParseRaindexConfigSourceError, ParseRainlangConfigSourceError, ParseScenarioConfigSourceError, + ParseTokenConfigSourceError, TokenCfg, }; use alloy::primitives::ruint::ParseError as RuintParseError; use context::{Context, ContextError, ContextProfile}; @@ -250,10 +250,9 @@ impl PartialEq for YamlError { (Self::ParseTokenConfigSourceError(e1), Self::ParseTokenConfigSourceError(e2)) => { e1 == e2 } - ( - Self::ParseRaindexConfigSourceError(e1), - Self::ParseRaindexConfigSourceError(e2), - ) => e1 == e2, + (Self::ParseRaindexConfigSourceError(e1), Self::ParseRaindexConfigSourceError(e2)) => { + e1 == e2 + } ( Self::ParseRainlangConfigSourceError(e1), Self::ParseRainlangConfigSourceError(e2), diff --git a/crates/settings/src/yaml/raindex.rs b/crates/settings/src/yaml/raindex.rs index 86f06058a7..d2facc5fb5 100644 --- a/crates/settings/src/yaml/raindex.rs +++ b/crates/settings/src/yaml/raindex.rs @@ -370,10 +370,7 @@ impl RaindexYaml { Ok(raindexes) } - pub fn get_raindexes_by_chain_id( - &self, - chain_id: u32, - ) -> Result, YamlError> { + pub fn get_raindexes_by_chain_id(&self, chain_id: u32) -> Result, YamlError> { let network = self.get_network_by_chain_id(chain_id)?; let mut raindexes: Vec<_> = self .get_raindexes()? diff --git a/crates/subgraph/src/lib.rs b/crates/subgraph/src/lib.rs index e0c120f4f0..fb36ac1b6f 100644 --- a/crates/subgraph/src/lib.rs +++ b/crates/subgraph/src/lib.rs @@ -1,8 +1,8 @@ mod cynic_client; mod multi_raindex_client; -mod raindex_client; mod pagination; pub mod performance; +mod raindex_client; pub mod types; pub mod utils; pub mod validate; @@ -12,5 +12,5 @@ mod vault_balance_changes_query; pub mod schema {} pub use multi_raindex_client::{MultiRaindexSubgraphClient, MultiSubgraphArgs}; -pub use raindex_client::{RaindexSubgraphClient, RaindexSubgraphClientError}; pub use pagination::{PageQueryClient, SgPaginationArgs}; +pub use raindex_client::{RaindexSubgraphClient, RaindexSubgraphClientError}; diff --git a/crates/subgraph/src/multi_raindex_client.rs b/crates/subgraph/src/multi_raindex_client.rs index ed173cb629..f5a86b0c1b 100644 --- a/crates/subgraph/src/multi_raindex_client.rs +++ b/crates/subgraph/src/multi_raindex_client.rs @@ -158,7 +158,7 @@ impl MultiRaindexSubgraphClient { mod tests { use super::*; use crate::types::common::{ - SgBigInt, SgBytes, SgErc20, SgOrder, SgRaindex, SgOrdersListFilterArgs, SgVault, + SgBigInt, SgBytes, SgErc20, SgOrder, SgOrdersListFilterArgs, SgRaindex, SgVault, }; use crate::utils::float::*; use httpmock::prelude::*; diff --git a/crates/subgraph/src/raindex_client/order.rs b/crates/subgraph/src/raindex_client/order.rs index fa2dc68c65..ff9a750fa4 100644 --- a/crates/subgraph/src/raindex_client/order.rs +++ b/crates/subgraph/src/raindex_client/order.rs @@ -178,7 +178,7 @@ impl RaindexSubgraphClient { mod tests { use super::*; use crate::types::common::{ - SgBigInt, SgBytes, SgOrder, SgRaindex, SgOrdersListFilterArgs, SgOrdersTokensFilterArgs, + SgBigInt, SgBytes, SgOrder, SgOrdersListFilterArgs, SgOrdersTokensFilterArgs, SgRaindex, }; use crate::utils::float::*; use cynic::Id; diff --git a/crates/subgraph/src/raindex_client/order_trade.rs b/crates/subgraph/src/raindex_client/order_trade.rs index 21cfaa7fce..20a5700957 100644 --- a/crates/subgraph/src/raindex_client/order_trade.rs +++ b/crates/subgraph/src/raindex_client/order_trade.rs @@ -2,10 +2,7 @@ use super::*; impl RaindexSubgraphClient { /// Fetch single order take - pub async fn order_trade_detail( - &self, - id: Id, - ) -> Result { + pub async fn order_trade_detail(&self, id: Id) -> Result { let data = self .query::(SgIdQueryVariables { id: &id }) .await?; diff --git a/crates/subgraph/src/raindex_client/token.rs b/crates/subgraph/src/raindex_client/token.rs index d636b9882e..ed607b2315 100644 --- a/crates/subgraph/src/raindex_client/token.rs +++ b/crates/subgraph/src/raindex_client/token.rs @@ -94,10 +94,7 @@ mod tests { let result = client.tokens_list_all().await; assert!( - matches!( - result, - Err(RaindexSubgraphClientError::CynicClientError(_)) - ), + matches!(result, Err(RaindexSubgraphClientError::CynicClientError(_))), "Should return network error when GraphQL request fails" ); } diff --git a/crates/subgraph/src/raindex_client/transaction.rs b/crates/subgraph/src/raindex_client/transaction.rs index 3f41a3507a..e0ac9a7c50 100644 --- a/crates/subgraph/src/raindex_client/transaction.rs +++ b/crates/subgraph/src/raindex_client/transaction.rs @@ -8,9 +8,7 @@ impl RaindexSubgraphClient { let data = self .query::(SgIdQueryVariables { id: &id }) .await?; - let transaction = data - .transaction - .ok_or(RaindexSubgraphClientError::Empty)?; + let transaction = data.transaction.ok_or(RaindexSubgraphClientError::Empty)?; Ok(transaction) } diff --git a/crates/subgraph/src/vault_balance_changes_query.rs b/crates/subgraph/src/vault_balance_changes_query.rs index 02735a8feb..1460ecafa1 100644 --- a/crates/subgraph/src/vault_balance_changes_query.rs +++ b/crates/subgraph/src/vault_balance_changes_query.rs @@ -68,7 +68,7 @@ mod tests { use super::*; use crate::cynic_client::CynicClientError; use crate::types::common::{ - SgBigInt, SgBytes, SgDeposit, SgErc20, SgRaindex, SgPaginationWithIdQueryVariables, + SgBigInt, SgBytes, SgDeposit, SgErc20, SgPaginationWithIdQueryVariables, SgRaindex, SgTransaction, SgVaultBalanceChangeVault, SgWithdrawal, }; use httpmock::prelude::*; diff --git a/crates/test_fixtures/src/lib.rs b/crates/test_fixtures/src/lib.rs index 61726134b4..d16030cb62 100644 --- a/crates/test_fixtures/src/lib.rs +++ b/crates/test_fixtures/src/lib.rs @@ -56,8 +56,7 @@ pub struct LocalEvm { pub raindex: Raindex::RaindexInstance, /// Alloy raindex subparser contract instance deployed on this blockchain - pub raindex_subparser: - RaindexSubParser::RaindexSubParserInstance, + pub raindex_subparser: RaindexSubParser::RaindexSubParserInstance, /// Alloy interpreter contract instance deployed on this blockchain pub interpreter: Interpreter::InterpreterInstance, From 49eb1c813563f44afb1e1af5af242ea270d63c7a Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Wed, 1 Apr 2026 20:07:00 +0400 Subject: [PATCH 38/69] Run forge fmt Co-Authored-By: Claude Opus 4.6 (1M context) --- script/BuildPointers.sol | 5 +---- script/Deploy.sol | 4 +--- src/concrete/parser/RaindexV6SubParser.sol | 3 +-- src/lib/deploy/LibRaindexDeploy.sol | 5 +---- .../RaindexV6FlashBorrower.reentrancy.t.sol | 3 +-- ...RaindexV6ArbOrderTaker.lossyRounding.t.sol | 4 +--- ...xV6ArbOrderTaker.nonStandardDecimals.t.sol | 4 +--- ...RaindexV6ArbOrderTaker.onTakeOrders2.t.sol | 4 +--- ...xV6ArbOrderTaker.onTakeOrders2Direct.t.sol | 4 +--- ...ocessorRaindexV6ArbOrderTaker.sender.t.sol | 4 +--- .../raindex/RaindexV6.clear.context.t.sol | 4 +--- .../RaindexV6.clear.handleIO.revert.t.sol | 4 +--- .../raindex/RaindexV6.clear.mock.t.sol | 5 ++--- .../RaindexV6.takeOrder.minimumIO.t.sol | 4 +--- test/lib/deploy/LibRaindexDeploy.t.sol | 20 +++++-------------- ...DeployNetworksJsonStartBlockArbitrum.t.sol | 4 +--- ...xDeployNetworksJsonStartBlockPolygon.t.sol | 4 +--- test/lib/deploy/LibRaindexDeployProd.t.sol | 4 +--- ...uteProcessorRaindexV6ArbOrderTakerTest.sol | 4 +--- test/util/lib/LibEtchRaindex.sol | 3 +-- test/util/lib/LibTestArb.sol | 7 ++++--- 21 files changed, 29 insertions(+), 74 deletions(-) diff --git a/script/BuildPointers.sol b/script/BuildPointers.sol index ca4d77caae..7fe742e1bd 100644 --- a/script/BuildPointers.sol +++ b/script/BuildPointers.sol @@ -37,10 +37,7 @@ contract BuildPointers is Script { string.concat( addressConstantString(deployed), LibCodeGen.bytesConstantString( - vm, - "/// @dev The creation bytecode of the contract.", - "CREATION_CODE", - type(RaindexV6).creationCode + vm, "/// @dev The creation bytecode of the contract.", "CREATION_CODE", type(RaindexV6).creationCode ), LibCodeGen.bytesConstantString( vm, "/// @dev The runtime bytecode of the contract.", "RUNTIME_CODE", deployed.code diff --git a/script/Deploy.sol b/script/Deploy.sol index 1f6202bce2..9c0e2c463d 100644 --- a/script/Deploy.sol +++ b/script/Deploy.sol @@ -85,9 +85,7 @@ contract Deploy is Script { vm.startBroadcast(deployerPrivateKey); bytes memory subParserDescribedByMeta = vm.readFileBinary("meta/RaindexV6SubParser.rain.meta"); LibDescribedByMeta.emitForDescribedAddress( - metaboard, - RaindexV6SubParser(LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS), - subParserDescribedByMeta + metaboard, RaindexV6SubParser(LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS), subParserDescribedByMeta ); vm.stopBroadcast(); } else if (suite == DEPLOYMENT_SUITE_ROUTE_PROCESSOR) { diff --git a/src/concrete/parser/RaindexV6SubParser.sol b/src/concrete/parser/RaindexV6SubParser.sol index fc98d38291..32baeba7c2 100644 --- a/src/concrete/parser/RaindexV6SubParser.sol +++ b/src/concrete/parser/RaindexV6SubParser.sol @@ -207,8 +207,7 @@ contract RaindexV6SubParser is BaseRainterpreterSubParser { internal view returns (bool, bytes memory, bytes32[] memory)[](CONTEXT_CALLING_CONTEXT_ROWS); contextCallingContextParsers[CONTEXT_CALLING_CONTEXT_ROW_ORDER_HASH] = LibRaindexSubParser.subParserOrderHash; - contextCallingContextParsers[CONTEXT_CALLING_CONTEXT_ROW_ORDER_OWNER] = - LibRaindexSubParser.subParserOrderOwner; + contextCallingContextParsers[CONTEXT_CALLING_CONTEXT_ROW_ORDER_OWNER] = LibRaindexSubParser.subParserOrderOwner; contextCallingContextParsers[CONTEXT_CALLING_CONTEXT_ROW_ORDER_COUNTERPARTY] = LibRaindexSubParser.subParserOrderCounterparty; diff --git a/src/lib/deploy/LibRaindexDeploy.sol b/src/lib/deploy/LibRaindexDeploy.sol index a5f89c8927..db5e7dfdc2 100644 --- a/src/lib/deploy/LibRaindexDeploy.sol +++ b/src/lib/deploy/LibRaindexDeploy.sol @@ -2,10 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2020 Rain Open Source Software Ltd pragma solidity ^0.8.25; -import { - BYTECODE_HASH as RAINDEX_HASH, - DEPLOYED_ADDRESS as RAINDEX_ADDR -} from "../../generated/RaindexV6.pointers.sol"; +import {BYTECODE_HASH as RAINDEX_HASH, DEPLOYED_ADDRESS as RAINDEX_ADDR} from "../../generated/RaindexV6.pointers.sol"; import { BYTECODE_HASH as SUB_PARSER_HASH, DEPLOYED_ADDRESS as SUB_PARSER_ADDR diff --git a/test/abstract/RaindexV6FlashBorrower.reentrancy.t.sol b/test/abstract/RaindexV6FlashBorrower.reentrancy.t.sol index 93710ddd17..fc0672db6e 100644 --- a/test/abstract/RaindexV6FlashBorrower.reentrancy.t.sol +++ b/test/abstract/RaindexV6FlashBorrower.reentrancy.t.sol @@ -45,8 +45,7 @@ contract RaindexV6FlashBorrowerReentrancyTest is Test { GenericPoolRaindexV6FlashBorrower arb = new GenericPoolRaindexV6FlashBorrower(); // Deploy the reentrant exchange that will call arb4 when invoked. - ReentrantExchange exchange = - new ReentrantExchange(arb, IRaindexV6(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS)); + ReentrantExchange exchange = new ReentrantExchange(arb, IRaindexV6(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS)); IOV2[] memory validInputs = new IOV2[](1); validInputs[0] = IOV2(address(inputToken), bytes32(0)); diff --git a/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.lossyRounding.t.sol b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.lossyRounding.t.sol index 591c1bebc4..b126499459 100644 --- a/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.lossyRounding.t.sol +++ b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.lossyRounding.t.sol @@ -5,9 +5,7 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {IRouteProcessor} from "sushixswap-v2/src/interfaces/IRouteProcessor.sol"; -import { - RouteProcessorRaindexV6ArbOrderTaker -} from "../../../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; +import {RouteProcessorRaindexV6ArbOrderTaker} from "../../../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; import {Float} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {LibDecimalFloat} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; diff --git a/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.nonStandardDecimals.t.sol b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.nonStandardDecimals.t.sol index 9229d27de8..aecc70a974 100644 --- a/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.nonStandardDecimals.t.sol +++ b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.nonStandardDecimals.t.sol @@ -5,9 +5,7 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import { - RouteProcessorRaindexV6ArbOrderTaker -} from "../../../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; +import {RouteProcessorRaindexV6ArbOrderTaker} from "../../../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; import { IRaindexV6, TakeOrdersConfigV5, diff --git a/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.onTakeOrders2.t.sol b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.onTakeOrders2.t.sol index 1288885ef6..0e5bfa1570 100644 --- a/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.onTakeOrders2.t.sol +++ b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.onTakeOrders2.t.sol @@ -5,9 +5,7 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import { - RouteProcessorRaindexV6ArbOrderTaker -} from "../../../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; +import {RouteProcessorRaindexV6ArbOrderTaker} from "../../../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; import { IRaindexV6, TakeOrdersConfigV5, diff --git a/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.onTakeOrders2Direct.t.sol b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.onTakeOrders2Direct.t.sol index 68ed882f28..75c84c4ca1 100644 --- a/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.onTakeOrders2Direct.t.sol +++ b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.onTakeOrders2Direct.t.sol @@ -4,9 +4,7 @@ pragma solidity =0.8.25; import {Test} from "forge-std/Test.sol"; -import { - RouteProcessorRaindexV6ArbOrderTaker -} from "../../../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; +import {RouteProcessorRaindexV6ArbOrderTaker} from "../../../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; import {Float} from "rain.raindex.interface/interface/IRaindexV6.sol"; import {LibRainDeploy} from "rain.deploy/lib/LibRainDeploy.sol"; import {LibTOFUTokenDecimals} from "rain.tofu.erc20-decimals/lib/LibTOFUTokenDecimals.sol"; diff --git a/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sender.t.sol b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sender.t.sol index 9ddfdbe9bb..0355db8a1b 100644 --- a/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sender.t.sol +++ b/test/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sender.t.sol @@ -15,9 +15,7 @@ import { TaskV2, SignedContextV1 } from "rain.raindex.interface/interface/IRaindexV6.sol"; -import { - RouteProcessorRaindexV6ArbOrderTaker -} from "../../../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; +import {RouteProcessorRaindexV6ArbOrderTaker} from "../../../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; import {LibDecimalFloat, Float} from "rain.math.float/lib/LibDecimalFloat.sol"; import {LibInterpreterDeploy} from "rain.interpreter/lib/deploy/LibInterpreterDeploy.sol"; diff --git a/test/concrete/raindex/RaindexV6.clear.context.t.sol b/test/concrete/raindex/RaindexV6.clear.context.t.sol index ecd96c62ba..5b5f4eed74 100644 --- a/test/concrete/raindex/RaindexV6.clear.context.t.sol +++ b/test/concrete/raindex/RaindexV6.clear.context.t.sol @@ -126,9 +126,7 @@ contract RaindexV6ClearOrderContextTest is RaindexV6ExternalRealTest { mockVault0Output(token, owner, absoluteAmount); } else { vm.mockCall( - token, - abi.encodeWithSelector(IERC20.transferFrom.selector, owner, address(iRaindex)), - abi.encode(true) + token, abi.encodeWithSelector(IERC20.transferFrom.selector, owner, address(iRaindex)), abi.encode(true) ); vm.prank(owner); iRaindex.deposit4(token, vaultId, LibDecimalFloat.packLossless(amount, exponent), new TaskV2[](0)); diff --git a/test/concrete/raindex/RaindexV6.clear.handleIO.revert.t.sol b/test/concrete/raindex/RaindexV6.clear.handleIO.revert.t.sol index 33b9853844..2e05b98edf 100644 --- a/test/concrete/raindex/RaindexV6.clear.handleIO.revert.t.sol +++ b/test/concrete/raindex/RaindexV6.clear.handleIO.revert.t.sol @@ -62,9 +62,7 @@ contract RaindexV6ClearHandleIORevertTest is RaindexV6ExternalRealTest { mockVault0Output(outputToken, owner, uint256(int256(type(int224).max))); } else { vm.prank(owner); - iRaindex.deposit4( - outputToken, vaultId, LibDecimalFloat.packLossless(type(int224).max, 0), new TaskV2[](0) - ); + iRaindex.deposit4(outputToken, vaultId, LibDecimalFloat.packLossless(type(int224).max, 0), new TaskV2[](0)); Float balance = iRaindex.vaultBalance2(owner, outputToken, vaultId); assertTrue(balance.eq(LibDecimalFloat.packLossless(type(int224).max, 0))); } diff --git a/test/concrete/raindex/RaindexV6.clear.mock.t.sol b/test/concrete/raindex/RaindexV6.clear.mock.t.sol index 09390f8236..27830a9d40 100644 --- a/test/concrete/raindex/RaindexV6.clear.mock.t.sol +++ b/test/concrete/raindex/RaindexV6.clear.mock.t.sol @@ -181,9 +181,8 @@ contract RaindexV6ClearTest is RaindexV6ExternalMockTest { assertTrue(aliceBountyBalance.isZero()); } { - Float bobBountyBalance = iRaindex.vaultBalance2( - clear.bountyBot, clear.bobConfig.validOutputs[0].token, clear.bobBountyVaultId - ); + Float bobBountyBalance = + iRaindex.vaultBalance2(clear.bountyBot, clear.bobConfig.validOutputs[0].token, clear.bobBountyVaultId); assertTrue(bobBountyBalance.isZero()); } diff --git a/test/concrete/raindex/RaindexV6.takeOrder.minimumIO.t.sol b/test/concrete/raindex/RaindexV6.takeOrder.minimumIO.t.sol index 2ca8402783..d1c1fbd9da 100644 --- a/test/concrete/raindex/RaindexV6.takeOrder.minimumIO.t.sol +++ b/test/concrete/raindex/RaindexV6.takeOrder.minimumIO.t.sol @@ -23,9 +23,7 @@ contract RaindexV6TakeOrderMinimumIOTest is RaindexV6ExternalRealTest { abi.encode(true) ); vm.prank(alice); - iRaindex.deposit4( - address(iToken1), bytes32(uint256(0x01)), LibDecimalFloat.packLossless(1, 0), new TaskV2[](0) - ); + iRaindex.deposit4(address(iToken1), bytes32(uint256(0x01)), LibDecimalFloat.packLossless(1, 0), new TaskV2[](0)); // Order outputs 1e-18 at ratio 1. OrderV4 memory order = LibTestTakeOrder.addOrderWithExpression( diff --git a/test/lib/deploy/LibRaindexDeploy.t.sol b/test/lib/deploy/LibRaindexDeploy.t.sol index 0e1da37d74..3e84ce7643 100644 --- a/test/lib/deploy/LibRaindexDeploy.t.sol +++ b/test/lib/deploy/LibRaindexDeploy.t.sol @@ -25,9 +25,7 @@ import { } from "../../../src/generated/RouteProcessor4.pointers.sol"; import {ROUTE_PROCESSOR_4_CREATION_CODE} from "../../../src/lib/deploy/LibRouteProcessor4CreationCode.sol"; import {GenericPoolRaindexV6ArbOrderTaker} from "../../../src/concrete/arb/GenericPoolRaindexV6ArbOrderTaker.sol"; -import { - RouteProcessorRaindexV6ArbOrderTaker -} from "../../../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; +import {RouteProcessorRaindexV6ArbOrderTaker} from "../../../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; import {GenericPoolRaindexV6FlashBorrower} from "../../../src/concrete/arb/GenericPoolRaindexV6FlashBorrower.sol"; import { RUNTIME_CODE as GENERIC_POOL_ARB_OT_RUNTIME_CODE, @@ -179,9 +177,7 @@ contract LibRaindexDeployTest is Test { assertEq(deployedAddress, LibRaindexDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_ADDRESS); assertTrue(address(deployedAddress).code.length > 0, "Deployed address has no code"); - assertEq( - address(deployedAddress).codehash, LibRaindexDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_CODEHASH - ); + assertEq(address(deployedAddress).codehash, LibRaindexDeploy.ROUTE_PROCESSOR_ARB_ORDER_TAKER_DEPLOYED_CODEHASH); } /// Deploying GenericPoolRaindexV6FlashBorrower via Zoltu MUST produce @@ -241,9 +237,7 @@ contract LibRaindexDeployTest is Test { /// The generated deployed address for GenericPoolRaindexV6ArbOrderTaker /// MUST match the deploy library constant. function testGeneratedDeployedAddressGenericPoolArbOrderTaker() external pure { - assertEq( - GENERIC_POOL_ARB_OT_GENERATED_ADDRESS, LibRaindexDeploy.GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_ADDRESS - ); + assertEq(GENERIC_POOL_ARB_OT_GENERATED_ADDRESS, LibRaindexDeploy.GENERIC_POOL_ARB_ORDER_TAKER_DEPLOYED_ADDRESS); } /// The generated deployed address for RouteProcessorRaindexV6ArbOrderTaker @@ -284,9 +278,7 @@ contract LibRaindexDeployTest is Test { LibEtchRaindex.etchRaindex(vm); assertEq(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS.codehash, LibRaindexDeploy.RAINDEX_DEPLOYED_CODEHASH); - assertEq( - LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS.codehash, LibRaindexDeploy.SUB_PARSER_DEPLOYED_CODEHASH - ); + assertEq(LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS.codehash, LibRaindexDeploy.SUB_PARSER_DEPLOYED_CODEHASH); assertEq( LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS.codehash, LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_CODEHASH @@ -300,9 +292,7 @@ contract LibRaindexDeployTest is Test { LibEtchRaindex.etchRaindex(vm); assertEq(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS.codehash, LibRaindexDeploy.RAINDEX_DEPLOYED_CODEHASH); - assertEq( - LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS.codehash, LibRaindexDeploy.SUB_PARSER_DEPLOYED_CODEHASH - ); + assertEq(LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS.codehash, LibRaindexDeploy.SUB_PARSER_DEPLOYED_CODEHASH); assertEq( LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS.codehash, LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_CODEHASH diff --git a/test/lib/deploy/LibRaindexDeployNetworksJsonStartBlockArbitrum.t.sol b/test/lib/deploy/LibRaindexDeployNetworksJsonStartBlockArbitrum.t.sol index ec7e0bc7cb..81fc963ae7 100644 --- a/test/lib/deploy/LibRaindexDeployNetworksJsonStartBlockArbitrum.t.sol +++ b/test/lib/deploy/LibRaindexDeployNetworksJsonStartBlockArbitrum.t.sol @@ -13,9 +13,7 @@ contract LibRaindexDeployNetworksJsonStartBlockArbitrumTest is Test { string memory json = vm.readFile("subgraph/networks.json"); uint256 startBlock = vm.parseJsonUint(json, ".arbitrum-one.Raindex.startBlock"); assertEq( - startBlock, - LibRaindexDeploy.RAINDEX_START_BLOCK_ARBITRUM, - "networks.json startBlock mismatch: arbitrum-one" + startBlock, LibRaindexDeploy.RAINDEX_START_BLOCK_ARBITRUM, "networks.json startBlock mismatch: arbitrum-one" ); } } diff --git a/test/lib/deploy/LibRaindexDeployNetworksJsonStartBlockPolygon.t.sol b/test/lib/deploy/LibRaindexDeployNetworksJsonStartBlockPolygon.t.sol index 8721a6dcba..b65cc15131 100644 --- a/test/lib/deploy/LibRaindexDeployNetworksJsonStartBlockPolygon.t.sol +++ b/test/lib/deploy/LibRaindexDeployNetworksJsonStartBlockPolygon.t.sol @@ -12,8 +12,6 @@ contract LibRaindexDeployNetworksJsonStartBlockPolygonTest is Test { function testNetworksJsonStartBlockPolygon() external view { string memory json = vm.readFile("subgraph/networks.json"); uint256 startBlock = vm.parseJsonUint(json, ".matic.Raindex.startBlock"); - assertEq( - startBlock, LibRaindexDeploy.RAINDEX_START_BLOCK_POLYGON, "networks.json startBlock mismatch: matic" - ); + assertEq(startBlock, LibRaindexDeploy.RAINDEX_START_BLOCK_POLYGON, "networks.json startBlock mismatch: matic"); } } diff --git a/test/lib/deploy/LibRaindexDeployProd.t.sol b/test/lib/deploy/LibRaindexDeployProd.t.sol index 5d36ed37b2..9a549f6383 100644 --- a/test/lib/deploy/LibRaindexDeployProd.t.sol +++ b/test/lib/deploy/LibRaindexDeployProd.t.sol @@ -15,9 +15,7 @@ contract LibRaindexDeployProdTest is Test { assertEq(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS.codehash, LibRaindexDeploy.RAINDEX_DEPLOYED_CODEHASH); assertTrue(LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS.code.length > 0, "SubParser not deployed"); - assertEq( - LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS.codehash, LibRaindexDeploy.SUB_PARSER_DEPLOYED_CODEHASH - ); + assertEq(LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS.codehash, LibRaindexDeploy.SUB_PARSER_DEPLOYED_CODEHASH); assertTrue(LibRaindexDeploy.ROUTE_PROCESSOR_DEPLOYED_ADDRESS.code.length > 0, "RouteProcessor4 not deployed"); assertEq( diff --git a/test/util/abstract/RouteProcessorRaindexV6ArbOrderTakerTest.sol b/test/util/abstract/RouteProcessorRaindexV6ArbOrderTakerTest.sol index 79c2eaf0cf..17ea7b508a 100644 --- a/test/util/abstract/RouteProcessorRaindexV6ArbOrderTakerTest.sol +++ b/test/util/abstract/RouteProcessorRaindexV6ArbOrderTakerTest.sol @@ -3,9 +3,7 @@ pragma solidity =0.8.25; import {ArbTest} from "./ArbTest.sol"; -import { - RouteProcessorRaindexV6ArbOrderTaker -} from "../../../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; +import {RouteProcessorRaindexV6ArbOrderTaker} from "../../../src/concrete/arb/RouteProcessorRaindexV6ArbOrderTaker.sol"; contract RouteProcessorRaindexV6ArbOrderTakerTest is ArbTest { function buildArb() internal override returns (address payable) { diff --git a/test/util/lib/LibEtchRaindex.sol b/test/util/lib/LibEtchRaindex.sol index a5f9a79f08..a8f59f78cf 100644 --- a/test/util/lib/LibEtchRaindex.sol +++ b/test/util/lib/LibEtchRaindex.sol @@ -20,8 +20,7 @@ library LibEtchRaindex { if (LibRaindexDeploy.RAINDEX_DEPLOYED_CODEHASH != LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS.codehash) { vm.etch(LibRaindexDeploy.RAINDEX_DEPLOYED_ADDRESS, RAINDEX_RUNTIME_CODE); } - if (LibRaindexDeploy.SUB_PARSER_DEPLOYED_CODEHASH != LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS.codehash) - { + if (LibRaindexDeploy.SUB_PARSER_DEPLOYED_CODEHASH != LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS.codehash) { vm.etch(LibRaindexDeploy.SUB_PARSER_DEPLOYED_ADDRESS, SUB_PARSER_RUNTIME_CODE); } if ( diff --git a/test/util/lib/LibTestArb.sol b/test/util/lib/LibTestArb.sol index 76cf4a3a4f..769abfa41d 100644 --- a/test/util/lib/LibTestArb.sol +++ b/test/util/lib/LibTestArb.sol @@ -130,9 +130,10 @@ library LibTestArb { arb.arb5{value: ethValue}(IRaindexV6(address(raindex)), takeOrdersConfig, task); - return ArbResult({ - arb: arb, inputToken: inputToken, outputToken: outputToken, raindex: raindex, exchange: exchange - }); + return + ArbResult({ + arb: arb, inputToken: inputToken, outputToken: outputToken, raindex: raindex, exchange: exchange + }); } /// Set up an order-taker arb scenario without executing it. From 3c6326dbc9cfcbaaa92d1d7647c436d2fdf768cf Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Wed, 1 Apr 2026 20:42:39 +0400 Subject: [PATCH 39/69] Update test fixtures to DB schema version 3 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../local_db/pipeline/runner/environment.rs | 2 +- .../src/local_db/pipeline/runner/remotes.rs | 8 ++-- crates/settings/src/local_db_manifest.rs | 38 +++++++++---------- crates/settings/src/remote/manifest.rs | 10 ++--- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/crates/common/src/local_db/pipeline/runner/environment.rs b/crates/common/src/local_db/pipeline/runner/environment.rs index 9908ecc419..0f80a0e0aa 100644 --- a/crates/common/src/local_db/pipeline/runner/environment.rs +++ b/crates/common/src/local_db/pipeline/runner/environment.rs @@ -725,7 +725,7 @@ raindexes: let manifest_yaml = format!( r#" manifest-version: {version} -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 diff --git a/crates/common/src/local_db/pipeline/runner/remotes.rs b/crates/common/src/local_db/pipeline/runner/remotes.rs index 3327ddbc80..0b0b5a022b 100644 --- a/crates/common/src/local_db/pipeline/runner/remotes.rs +++ b/crates/common/src/local_db/pipeline/runner/remotes.rs @@ -261,7 +261,7 @@ raindexes: let manifest_one = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 @@ -275,7 +275,7 @@ networks: let manifest_two = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: goerli: chain-id: 5 @@ -325,13 +325,13 @@ networks: let manifest_one = format!( r#" manifest-version: {MANIFEST_VERSION} -db-schema-version: 2 +db-schema-version: 3 networks: {{}} "# ); let manifest_two = r#" manifest-version: 2 -db-schema-version: 2 +db-schema-version: 3 networks: {} "#; diff --git a/crates/settings/src/local_db_manifest.rs b/crates/settings/src/local_db_manifest.rs index cc4ca5f262..59ca5748d6 100644 --- a/crates/settings/src/local_db_manifest.rs +++ b/crates/settings/src/local_db_manifest.rs @@ -535,7 +535,7 @@ mod tests { // OK header let yaml_ok = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: {} "#; let doc = load(yaml_ok); @@ -546,7 +546,7 @@ networks: {} // Incompatible manifest version let yaml_bad = r#" manifest-version: 999 -db-schema-version: 2 +db-schema-version: 3 networks: {} "#; let err = parse_manifest_header(&load(yaml_bad), "manifest").unwrap_err(); @@ -584,7 +584,7 @@ networks: {} fn test_networks_helper_empty_key_rejected() { let yaml = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: "": chain-id: 1 @@ -645,7 +645,7 @@ end-block-time-ms: 1 #[test] fn test_missing_manifest_version() { let yaml = r#" -db-schema-version: 2 +db-schema-version: 3 networks: {} "#; let err = parse_manifest_doc(&load(yaml)).unwrap_err(); @@ -666,7 +666,7 @@ networks: {} fn test_missing_networks_defaults_to_empty() { let yaml = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 "#; let manifest = parse_manifest_doc(&load(yaml)).unwrap(); assert!(manifest.networks.is_empty()); @@ -696,7 +696,7 @@ networks: {} fn test_zero_or_invalid_manifest_and_schema_versions() { let yaml_zero_manifest = r#" manifest-version: 0 -db-schema-version: 2 +db-schema-version: 3 networks: {} "#; let err = parse_manifest_doc(&load(yaml_zero_manifest)).unwrap_err(); @@ -715,7 +715,7 @@ networks: {} fn test_network_missing_chain_id_and_invalid() { let yaml_missing = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: {} "#; @@ -724,7 +724,7 @@ networks: let yaml_zero = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 0 @@ -738,7 +738,7 @@ networks: fn test_raindexes_required_and_type() { let yaml_missing = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 @@ -748,7 +748,7 @@ networks: let yaml_non_list = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 @@ -763,7 +763,7 @@ networks: // Full, valid baseline let good = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 @@ -779,7 +779,7 @@ networks: // Now omit each required field individually let missing_address = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 @@ -796,7 +796,7 @@ networks: let missing_dump = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 @@ -813,7 +813,7 @@ networks: let missing_end_block = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 @@ -830,7 +830,7 @@ networks: let missing_end_hash = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 @@ -847,7 +847,7 @@ networks: let missing_end_time = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 @@ -867,7 +867,7 @@ networks: fn test_find_across_networks_and_negatives() { let yaml = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 @@ -925,7 +925,7 @@ networks: fn test_incompatible_manifest_version_rejected() { let yaml = r#" manifest-version: 999 -db-schema-version: 2 +db-schema-version: 3 networks: {} "#; let err = parse_manifest_doc(&load(yaml)).unwrap_err(); @@ -945,7 +945,7 @@ networks: {} fn test_empty_network_key_is_rejected() { let yaml = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: "": chain-id: 1 diff --git a/crates/settings/src/remote/manifest.rs b/crates/settings/src/remote/manifest.rs index b4fb09e9a6..54015a7e18 100644 --- a/crates/settings/src/remote/manifest.rs +++ b/crates/settings/src/remote/manifest.rs @@ -56,7 +56,7 @@ mod tests { let server = MockServer::start_async().await; let yaml = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 @@ -107,7 +107,7 @@ networks: let server = MockServer::start_async().await; let yaml = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 extra-root: ignored networks: goerli: @@ -169,7 +169,7 @@ networks: let server = MockServer::start_async().await; let yaml = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 @@ -215,7 +215,7 @@ networks: let yaml_one = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 @@ -229,7 +229,7 @@ networks: let yaml_two = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: goerli: chain-id: 5 From be021eb835c7577ea100829eb0b5c93ad1cdfb61 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Wed, 1 Apr 2026 21:25:01 +0400 Subject: [PATCH 40/69] Update serialized state snapshots for renamed fields Co-Authored-By: Claude Opus 4.6 (1M context) --- crates/js_api/src/gui/state_management.rs | 2 +- packages/raindex/test/js_api/gui.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/js_api/src/gui/state_management.rs b/crates/js_api/src/gui/state_management.rs index 89c88345ff..fb3b8ae836 100644 --- a/crates/js_api/src/gui/state_management.rs +++ b/crates/js_api/src/gui/state_management.rs @@ -553,7 +553,7 @@ mod tests { use std::str::FromStr; use wasm_bindgen_test::wasm_bindgen_test; - const SERIALIZED_STATE: &str = "H4sIAAAAAAAA_21QXWvCMBRt3NgY7EkGexrsByy0aXWzwh4Ev4qgKH6AL6JttNKY1Bqx4p_wJ2v1pmLxPtxzbs7JvTfJadd4A5wtubfkC0w0FU-AxDCyJhPBgaGlTJEXQCkCyq1H3R4776t3qDZiRTGncieiQN37AvSlDMu6zoQ7Zb7YyHLJKBX1KHTxNmKHxIGSjNToWr_5ATRfGMbHTEJ59ApyP9nh20LPqm61zy_Jabe425akI4hto6xqpqpp2z9A4-pv2Cn8tQbxvLGddTvDRX3tBGMyao6Z4xV7vus4k8iq9Oq7_0_1F5RRV-JLU-zRkIn9inJ5AjfkymPKAQAA"; + const SERIALIZED_STATE: &str = "H4sIAAAAAAAA_21Qy27CMBCMadWqUk-oUk-V-gG1EoeiJki9tEK8BFwgAi4oBEOiGDsE84j4CT4ZAusgIvawM-sZ765d0C7xAjgJ-DTgc0w0FQ-AxDDyJhPBgaFlTJEnQClCykv3ut133lavUK3EgmJO5VbEobr3AehLGVV0nQnPZb5YyYplWGU9jjy8jtk-daA0IzW62qu_AS1-O7tDLqEiega5l-7wWUKPqm51Ti8paNe42ZZkI4hto7xqZqpp219AcU3MfjbjRpgktbbc-oMlHzl_5dANOoTM3Xbc7f9bTlTFzeHvu_oLyqgn8bkpntKIiWRBuTwC_jr8_soBAAA="; fn encode_state(state: &SerializedGuiState) -> String { let bytes = bincode::serialize(state).unwrap(); diff --git a/packages/raindex/test/js_api/gui.test.ts b/packages/raindex/test/js_api/gui.test.ts index f4f42eb6e3..d6fad4e54a 100644 --- a/packages/raindex/test/js_api/gui.test.ts +++ b/packages/raindex/test/js_api/gui.test.ts @@ -1027,7 +1027,7 @@ describe('Rain Raindex JS API Package Bindgen Tests - Gui', async function () { describe('state management tests', async () => { let serializedState = - 'H4sIAAAAAAAA_21QzUrEMBBuqiiIBxGvguDV2GxCy-6yXpSVQlFQi38X6bZhu26a1DZViw_h0asvsPgEXr35POJNi0ndsjuHfJP5vsnMF2D8xapCSXMJByMejfgQqBoyVqbZ-4AV1FSVJc2IMeUtQ8eiQhvtOg0JriULClsIgXmP4eZNL5iLhEJO5YPIxrpvU2EsZdq1LCbCgMUil902attWloawyNhTpQDVCfTovu9uqPS59zXZ_uxN3l_st-9LE3c-XkOwDpYV7Vc7bGGgbfu_PkzjP5rfUA9wHAfM-KpZQsiOSml5FHj9m9I9ZHeDW37qnYcH-Mx2OyfXBRtGJDnehx7BF_Dxam9N9QgZ0wxGNGWiTCiXP9NL3cfLAQAA'; + 'H4sIAAAAAAAA_21Qu07DMBSNAwIJMSDEioTESojrNKZUZQC1AsRjSSqFsU3dpNS1jePwEB_ByMoPVHwBKxvfg9ggwg5E7R18ru851_ceA-s3VjUqkimnP2KDEUuArkFr5T9726M5sXVlyTB8TFjNMrGo0Ye7uCJBpWRBYw1CMO8xVL2ZBTM-IQ4j6o7Lsenb1JgqJZquS3ncoynPVLMBG74rRezkkj4WClCcwIzuhCcbOn1qfU63P1rTt2f_9Suy0f77SwzWwbKmw2KHLQSM7fDHh239RfUbygEYYzDjq2Q9z9vRKTodJkfX8VDuBe0ooFF6DLsi6bdF9z64wZeH51d10rk4S3JSP1jTPVylRDoDIih_mBCmvgEOtPhuywEAAA=='; let dotrain3: string; let gui: DotrainOrderGui; beforeAll(async () => { From a028d1a0d278fd9df364e5b08537cadd66890ff5 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Wed, 1 Apr 2026 22:07:28 +0400 Subject: [PATCH 41/69] Fix test assertions for DB schema version 3 and YAML version 6 Co-Authored-By: Claude Opus 4.6 (1M context) --- crates/js_api/src/gui/state_management.rs | 2 +- crates/settings/src/local_db_manifest.rs | 2 +- crates/settings/src/remote/manifest.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/js_api/src/gui/state_management.rs b/crates/js_api/src/gui/state_management.rs index fb3b8ae836..c90c936de9 100644 --- a/crates/js_api/src/gui/state_management.rs +++ b/crates/js_api/src/gui/state_management.rs @@ -696,7 +696,7 @@ mod tests { #[wasm_bindgen_test] async fn test_new_from_state_invalid_dotrain() { let dotrain = r#" - version: 5 + version: 6 networks: test: rpcs: diff --git a/crates/settings/src/local_db_manifest.rs b/crates/settings/src/local_db_manifest.rs index 59ca5748d6..2bffeee983 100644 --- a/crates/settings/src/local_db_manifest.rs +++ b/crates/settings/src/local_db_manifest.rs @@ -541,7 +541,7 @@ networks: {} let doc = load(yaml_ok); let (mv, sv) = parse_manifest_header(&doc, "manifest").expect("header parses"); assert_eq!(mv, 1); - assert_eq!(sv, 2); + assert_eq!(sv, 3); // Incompatible manifest version let yaml_bad = r#" diff --git a/crates/settings/src/remote/manifest.rs b/crates/settings/src/remote/manifest.rs index 54015a7e18..499d55a06f 100644 --- a/crates/settings/src/remote/manifest.rs +++ b/crates/settings/src/remote/manifest.rs @@ -82,7 +82,7 @@ networks: .unwrap(); assert_eq!(manifest.manifest_version, 1); - assert_eq!(manifest.db_schema_version, 2); + assert_eq!(manifest.db_schema_version, 3); let net = manifest.networks.get("mainnet").unwrap(); assert_eq!(net.chain_id, 1); assert_eq!(net.raindexes.len(), 1); From b406ea0f520b94a2a1b57b4487d0e8a8f0996f4e Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Thu, 2 Apr 2026 11:03:05 +0400 Subject: [PATCH 42/69] Fix CLI short option conflict and manifest version assertions - raindex_address short flag set to -a to avoid clash with -r (rpcs) - Fix remaining db_schema_version assertions in CLI tests Co-Authored-By: Claude Opus 4.6 (1M context) --- crates/cli/src/commands/local_db/pipeline/runner/manifest.rs | 4 ++-- crates/cli/src/transaction.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs b/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs index dc3b2b3734..81db2ac580 100644 --- a/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs +++ b/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs @@ -309,7 +309,7 @@ mod tests { .expect("manifest build succeeds"); assert_eq!(manifest.manifest_version, 1); - assert_eq!(manifest.db_schema_version, 2); + assert_eq!(manifest.db_schema_version, 3); assert_eq!(manifest.networks.len(), 2); let anvil = manifest.networks.get("anvil").expect("anvil network"); @@ -495,7 +495,7 @@ mod tests { assert!(manifest.networks.is_empty()); assert_eq!(manifest.manifest_version, 1); - assert_eq!(manifest.db_schema_version, 2); + assert_eq!(manifest.db_schema_version, 3); } #[test] diff --git a/crates/cli/src/transaction.rs b/crates/cli/src/transaction.rs index c11d7f9de4..64f4483d01 100644 --- a/crates/cli/src/transaction.rs +++ b/crates/cli/src/transaction.rs @@ -4,7 +4,7 @@ use raindex_common::transaction::TransactionArgs; #[derive(Args, Clone)] pub struct CliTransactionArgs { - #[arg(short, long, help = "Raindex contract address")] + #[arg(short = 'a', long, help = "Raindex contract address")] pub raindex_address: Address, #[arg( From e9bca4ec5fd6b87e7857b42c6fcf49111a1f4511 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Thu, 2 Apr 2026 13:04:05 +0400 Subject: [PATCH 43/69] Remove short flag from raindex_address CLI arg to avoid conflicts Co-Authored-By: Claude Opus 4.6 (1M context) --- crates/cli/src/transaction.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cli/src/transaction.rs b/crates/cli/src/transaction.rs index 64f4483d01..603ba5de21 100644 --- a/crates/cli/src/transaction.rs +++ b/crates/cli/src/transaction.rs @@ -4,7 +4,7 @@ use raindex_common::transaction::TransactionArgs; #[derive(Args, Clone)] pub struct CliTransactionArgs { - #[arg(short = 'a', long, help = "Raindex contract address")] + #[arg(long, help = "Raindex contract address")] pub raindex_address: Address, #[arg( From 14e1a2a0c26438a736fd6c311226d42286bbcf5f Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Thu, 2 Apr 2026 13:14:02 +0400 Subject: [PATCH 44/69] Use main deployment key for deterministic deploys on all branches Zoltu factory produces deterministic addresses regardless of deployer key, so there's no reason to use a dev key on non-main branches. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/manual-sol-artifacts.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/manual-sol-artifacts.yaml b/.github/workflows/manual-sol-artifacts.yaml index 68b804ed59..f50e495e56 100644 --- a/.github/workflows/manual-sol-artifacts.yaml +++ b/.github/workflows/manual-sol-artifacts.yaml @@ -52,7 +52,7 @@ jobs: env: DEPLOYMENT_SUITE: ${{ inputs.suite }} DEPLOY_BROADCAST: "1" - DEPLOYMENT_KEY: ${{ github.ref == 'refs/heads/main' && secrets.PRIVATE_KEY || secrets.PRIVATE_KEY_DEV }} + DEPLOYMENT_KEY: ${{ secrets.PRIVATE_KEY }} ETH_RPC_URL: ${{ secrets.CI_DEPLOY_BASE_RPC_URL || vars.CI_DEPLOY_BASE_RPC_URL || '' }} CI_DEPLOY_ARBITRUM_RPC_URL: ${{ secrets.CI_DEPLOY_ARBITRUM_RPC_URL || vars.CI_DEPLOY_ARBITRUM_RPC_URL || '' }} From a99e3e51a19b97eb55610c5d7d0e69f79527de6d Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Thu, 2 Apr 2026 15:25:13 +0400 Subject: [PATCH 45/69] Run prettier on ui-components Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/__tests__/DropdownRaindexesFilter.test.ts | 4 +--- .../src/lib/components/LocalDbStatusCard.svelte | 6 +----- .../src/lib/components/LocalDbStatusModal.svelte | 4 +++- .../src/lib/components/detail/VaultDetail.svelte | 7 +------ packages/ui-components/src/lib/utils/constructHashLink.ts | 7 +------ 5 files changed, 7 insertions(+), 21 deletions(-) diff --git a/packages/ui-components/src/__tests__/DropdownRaindexesFilter.test.ts b/packages/ui-components/src/__tests__/DropdownRaindexesFilter.test.ts index 3983088ba5..75a63d5e60 100644 --- a/packages/ui-components/src/__tests__/DropdownRaindexesFilter.test.ts +++ b/packages/ui-components/src/__tests__/DropdownRaindexesFilter.test.ts @@ -125,9 +125,7 @@ describe('DropdownRaindexesFilter', () => { await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); await waitFor(() => { - expect( - screen.getByText(`Cannot load raindexes list: ${errorMessage}`) - ).toBeInTheDocument(); + expect(screen.getByText(`Cannot load raindexes list: ${errorMessage}`)).toBeInTheDocument(); }); }); }); diff --git a/packages/ui-components/src/lib/components/LocalDbStatusCard.svelte b/packages/ui-components/src/lib/components/LocalDbStatusCard.svelte index 907d967b77..7ea2a8170a 100644 --- a/packages/ui-components/src/lib/components/LocalDbStatusCard.svelte +++ b/packages/ui-components/src/lib/components/LocalDbStatusCard.svelte @@ -1,9 +1,5 @@ From 1a72e2591c9d82cba43ed6e0ca7bfda23c32dad3 Mon Sep 17 00:00:00 2001 From: gildlab Date: Tue, 19 May 2026 18:31:31 +0000 Subject: [PATCH 61/69] fix: rename ob4-* Goldsky subgraph URLs in test fixtures and doc examples --- crates/cli/src/commands/chart.rs | 2 +- crates/js_api/src/registry.rs | 4 +- crates/rest_api/src/routes/take_orders.rs | 4 +- .../test/js_api/dotrainRegistry.test.ts | 660 ++++++++++-------- 4 files changed, 390 insertions(+), 280 deletions(-) diff --git a/crates/cli/src/commands/chart.rs b/crates/cli/src/commands/chart.rs index 6fd0f74f1a..df4c5e42f7 100644 --- a/crates/cli/src/commands/chart.rs +++ b/crates/cli/src/commands/chart.rs @@ -81,7 +81,7 @@ networks: chain-id: 14 currency: "FLR" subgraphs: - flare: "https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-flare/2024-12-13-9dc7/gn" + flare: "https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/raindex-flare/2024-12-13-9dc7/gn" metaboards: flare: "https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-flare-0x893BBFB7/0.1/gn" raindexes: diff --git a/crates/js_api/src/registry.rs b/crates/js_api/src/registry.rs index 2b863584d9..250fd78484 100644 --- a/crates/js_api/src/registry.rs +++ b/crates/js_api/src/registry.rs @@ -793,8 +793,8 @@ networks: chain-id: 8453 currency: ETH subgraphs: - flare: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-flare/0.8/gn - base: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-base/0.9/gn + flare: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/raindex-flare/0.8/gn + base: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/raindex-base/0.9/gn metaboards: flare: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-flare-0x893BBFB7/0.1/gn base: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-base-0x59401C93/0.1/gn diff --git a/crates/rest_api/src/routes/take_orders.rs b/crates/rest_api/src/routes/take_orders.rs index c3814b499e..1528e2abc2 100644 --- a/crates/rest_api/src/routes/take_orders.rs +++ b/crates/rest_api/src/routes/take_orders.rs @@ -12,7 +12,7 @@ use utoipa::ToSchema; pub struct BuyRequest { /// YAML configuration containing network RPC endpoints, subgraph URLs, and raindex addresses #[schema( - example = "networks:\n base:\n rpc: https://mainnet.base.org\n chain-id: 8453\nsubgraphs:\n base: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-base/0.9/gn\nraindexes:\n base:\n address: 0xd2938e7c9fe3597f78832ce780feb61945c377d7\n network: base\n subgraph: base" + example = "networks:\n base:\n rpc: https://mainnet.base.org\n chain-id: 8453\nsubgraphs:\n base: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/raindex-base/0.9/gn\nraindexes:\n base:\n address: 0xd2938e7c9fe3597f78832ce780feb61945c377d7\n network: base\n subgraph: base" )] pub yaml_content: String, /// Address that will execute the transaction @@ -44,7 +44,7 @@ pub struct BuyRequest { pub struct SellRequest { /// YAML configuration containing network RPC endpoints, subgraph URLs, and raindex addresses #[schema( - example = "networks:\n base:\n rpc: https://mainnet.base.org\n chain-id: 8453\nsubgraphs:\n base: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-base/0.9/gn\nraindexes:\n base:\n address: 0xd2938e7c9fe3597f78832ce780feb61945c377d7\n network: base\n subgraph: base" + example = "networks:\n base:\n rpc: https://mainnet.base.org\n chain-id: 8453\nsubgraphs:\n base: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/raindex-base/0.9/gn\nraindexes:\n base:\n address: 0xd2938e7c9fe3597f78832ce780feb61945c377d7\n network: base\n subgraph: base" )] pub yaml_content: String, /// Address that will execute the transaction diff --git a/packages/raindex/test/js_api/dotrainRegistry.test.ts b/packages/raindex/test/js_api/dotrainRegistry.test.ts index 8881730d6f..ebc175b628 100644 --- a/packages/raindex/test/js_api/dotrainRegistry.test.ts +++ b/packages/raindex/test/js_api/dotrainRegistry.test.ts @@ -1,18 +1,26 @@ -import assert from 'assert'; -import { afterAll, beforeAll, beforeEach, describe, it } from 'vitest'; -import { WasmEncodedResult, DotrainRegistry, RaindexYaml, RaindexClient } from '../../dist/cjs'; -import { getLocal } from 'mockttp'; +import assert from "assert"; +import { afterAll, beforeAll, beforeEach, describe, it } from "vitest"; +import { + WasmEncodedResult, + DotrainRegistry, + RaindexYaml, + RaindexClient, +} from "../../dist/cjs"; +import { getLocal } from "mockttp"; const SPEC_VERSION = RaindexYaml.getCurrentSpecVersion().value; -const extractWasmEncodedData = (result: WasmEncodedResult, errorMessage?: string): T => { - if (result.error) { - assert.fail(errorMessage ?? result.error.msg); - } - if (typeof void 0 === typeof result.value) { - return result.value as T; - } - return result.value; +const extractWasmEncodedData = ( + result: WasmEncodedResult, + errorMessage?: string, +): T => { + if (result.error) { + assert.fail(errorMessage ?? result.error.msg); + } + if (typeof void 0 === typeof result.value) { + return result.value as T; + } + return result.value; }; const MOCK_SETTINGS_CONTENT = ` @@ -29,8 +37,8 @@ networks: chain-id: 8453 currency: ETH subgraphs: - flare: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-flare/0.8/gn - base: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-base/0.9/gn + flare: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/raindex-flare/0.8/gn + base: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/raindex-base/0.9/gn metaboards: flare: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-flare-0x893BBFB7/0.1/gn base: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-base-0x59401C93/0.1/gn @@ -157,250 +165,344 @@ _ _: 1 1; #handle-add-order :;`; -describe('Raindex JS API Package Bindgen Tests - Dotrain Registry', async function () { - const mockServer = getLocal(); - beforeAll(async () => { - await mockServer.start(8231); - }); - afterAll(async () => { - await mockServer.stop(); - }); - beforeEach(() => { - mockServer.reset(); - }); - - describe('DotrainRegistry Constructor', () => { - it('should create registry and fetch all content successfully', async () => { - const registryContent = `http://localhost:8231/settings.yaml +describe("Raindex JS API Package Bindgen Tests - Dotrain Registry", async function () { + const mockServer = getLocal(); + beforeAll(async () => { + await mockServer.start(8231); + }); + afterAll(async () => { + await mockServer.stop(); + }); + beforeEach(() => { + mockServer.reset(); + }); + + describe("DotrainRegistry Constructor", () => { + it("should create registry and fetch all content successfully", async () => { + const registryContent = `http://localhost:8231/settings.yaml fixed-limit http://localhost:8231/fixed-limit.rain auction-dca http://localhost:8231/auction-dca.rain`; - await mockServer.forGet('/registry.txt').thenReply(200, registryContent); - await mockServer.forGet('/settings.yaml').thenReply(200, MOCK_SETTINGS_CONTENT); - await mockServer.forGet('/fixed-limit.rain').thenReply(200, FIRST_DOTRAIN_CONTENT); - await mockServer.forGet('/auction-dca.rain').thenReply(200, SECOND_DOTRAIN_CONTENT); - - const result = await DotrainRegistry.new('http://localhost:8231/registry.txt'); - const registry = extractWasmEncodedData(result); - - assert.strictEqual(registry.registryUrl, 'http://localhost:8231/registry.txt'); - assert.strictEqual(registry.settingsUrl, 'http://localhost:8231/settings.yaml'); - assert.strictEqual(registry.registry, registryContent); - assert.strictEqual(registry.settings, MOCK_SETTINGS_CONTENT); - - const orderUrls = registry.orderUrls; - assert.strictEqual(orderUrls.size, 2); - assert.strictEqual(orderUrls.get('fixed-limit'), 'http://localhost:8231/fixed-limit.rain'); - assert.strictEqual(orderUrls.get('auction-dca'), 'http://localhost:8231/auction-dca.rain'); - - const orders = registry.orders; - assert.strictEqual(orders.size, 2); - assert(orders.has('fixed-limit')); - assert(orders.has('auction-dca')); - }); - - it('should handle invalid registry format', async () => { - const invalidContent = 'invalid format without proper structure'; - await mockServer.forGet('/invalid.txt').thenReply(200, invalidContent); - - const result = await DotrainRegistry.new('http://localhost:8231/invalid.txt'); - assert(result.error); - }); - - it('should handle empty registry file', async () => { - await mockServer.forGet('/empty.txt').thenReply(200, ''); - - const result = await DotrainRegistry.new('http://localhost:8231/empty.txt'); - assert(result.error); - assert(result.error.readableMsg.includes('Invalid registry format')); - }); - - it('should handle settings fetch error', async () => { - const registryContent = - 'http://localhost:8231/nonexistent-settings.yaml\norder1 http://localhost:8231/order1.rain'; - await mockServer.forGet('/registry.txt').thenReply(200, registryContent); - await mockServer.forGet('/nonexistent-settings.yaml').thenReply(404); - - const result = await DotrainRegistry.new('http://localhost:8231/registry.txt'); - assert(result.error); - }); - - it('should validate registry format without fetching orders', async () => { - const registryContent = `http://localhost:8231/settings.yaml + await mockServer.forGet("/registry.txt").thenReply(200, registryContent); + await mockServer + .forGet("/settings.yaml") + .thenReply(200, MOCK_SETTINGS_CONTENT); + await mockServer + .forGet("/fixed-limit.rain") + .thenReply(200, FIRST_DOTRAIN_CONTENT); + await mockServer + .forGet("/auction-dca.rain") + .thenReply(200, SECOND_DOTRAIN_CONTENT); + + const result = await DotrainRegistry.new( + "http://localhost:8231/registry.txt", + ); + const registry = extractWasmEncodedData(result); + + assert.strictEqual( + registry.registryUrl, + "http://localhost:8231/registry.txt", + ); + assert.strictEqual( + registry.settingsUrl, + "http://localhost:8231/settings.yaml", + ); + assert.strictEqual(registry.registry, registryContent); + assert.strictEqual(registry.settings, MOCK_SETTINGS_CONTENT); + + const orderUrls = registry.orderUrls; + assert.strictEqual(orderUrls.size, 2); + assert.strictEqual( + orderUrls.get("fixed-limit"), + "http://localhost:8231/fixed-limit.rain", + ); + assert.strictEqual( + orderUrls.get("auction-dca"), + "http://localhost:8231/auction-dca.rain", + ); + + const orders = registry.orders; + assert.strictEqual(orders.size, 2); + assert(orders.has("fixed-limit")); + assert(orders.has("auction-dca")); + }); + + it("should handle invalid registry format", async () => { + const invalidContent = "invalid format without proper structure"; + await mockServer.forGet("/invalid.txt").thenReply(200, invalidContent); + + const result = await DotrainRegistry.new( + "http://localhost:8231/invalid.txt", + ); + assert(result.error); + }); + + it("should handle empty registry file", async () => { + await mockServer.forGet("/empty.txt").thenReply(200, ""); + + const result = await DotrainRegistry.new( + "http://localhost:8231/empty.txt", + ); + assert(result.error); + assert(result.error.readableMsg.includes("Invalid registry format")); + }); + + it("should handle settings fetch error", async () => { + const registryContent = + "http://localhost:8231/nonexistent-settings.yaml\norder1 http://localhost:8231/order1.rain"; + await mockServer.forGet("/registry.txt").thenReply(200, registryContent); + await mockServer.forGet("/nonexistent-settings.yaml").thenReply(404); + + const result = await DotrainRegistry.new( + "http://localhost:8231/registry.txt", + ); + assert(result.error); + }); + + it("should validate registry format without fetching orders", async () => { + const registryContent = `http://localhost:8231/settings.yaml fixed-limit http://localhost:8231/fixed-limit.rain`; - await mockServer.forGet('/registry.txt').thenReply(200, registryContent); + await mockServer.forGet("/registry.txt").thenReply(200, registryContent); - const result = await DotrainRegistry.validate('http://localhost:8231/registry.txt'); - const value = extractWasmEncodedData(result); - assert.strictEqual(value, undefined); - }); + const result = await DotrainRegistry.validate( + "http://localhost:8231/registry.txt", + ); + const value = extractWasmEncodedData(result); + assert.strictEqual(value, undefined); + }); - it('should fail validation for invalid registry format', async () => { - await mockServer.forGet('/invalid-registry.txt').thenReply(200, 'invalid'); + it("should fail validation for invalid registry format", async () => { + await mockServer + .forGet("/invalid-registry.txt") + .thenReply(200, "invalid"); - const result = await DotrainRegistry.validate('http://localhost:8231/invalid-registry.txt'); - assert(result.error); - }); - }); + const result = await DotrainRegistry.validate( + "http://localhost:8231/invalid-registry.txt", + ); + assert(result.error); + }); + }); - describe('DotrainRegistry Order Management', () => { - let registry: DotrainRegistry; + describe("DotrainRegistry Order Management", () => { + let registry: DotrainRegistry; - beforeEach(async () => { - const registryContent = `http://localhost:8231/settings.yaml + beforeEach(async () => { + const registryContent = `http://localhost:8231/settings.yaml fixed-limit http://localhost:8231/fixed-limit.rain auction-dca http://localhost:8231/auction-dca.rain`; - await mockServer.forGet('/registry.txt').thenReply(200, registryContent); - await mockServer.forGet('/settings.yaml').thenReply(200, MOCK_SETTINGS_CONTENT); - await mockServer.forGet('/fixed-limit.rain').thenReply(200, FIRST_DOTRAIN_CONTENT); - await mockServer.forGet('/auction-dca.rain').thenReply(200, SECOND_DOTRAIN_CONTENT); - - const result = await DotrainRegistry.new('http://localhost:8231/registry.txt'); - registry = extractWasmEncodedData(result); - }); - - it('should get order keys', () => { - const keys = extractWasmEncodedData(registry.getOrderKeys()); - - assert.strictEqual(keys.length, 2); - assert(keys.includes('fixed-limit')); - assert(keys.includes('auction-dca')); - }); - - it('should get all order details', () => { - const orderDetails = extractWasmEncodedData(registry.getAllOrderDetails()); - - assert.strictEqual(orderDetails.valid.size, 2); - assert.strictEqual(orderDetails.invalid.size, 0); - assert(orderDetails.valid.has('fixed-limit')); - assert(orderDetails.valid.has('auction-dca')); - - const fixedLimitDetails = orderDetails.valid.get('fixed-limit'); - assert(fixedLimitDetails); - assert.strictEqual(fixedLimitDetails.name, 'Test builder'); - assert.strictEqual(fixedLimitDetails.description, 'Test description'); - assert.strictEqual(fixedLimitDetails.short_description, 'Test short description'); - }); - - it('should handle mixed valid and invalid orders', async () => { - mockServer.reset(); - - const registryContent = `http://localhost:8231/settings.yaml + await mockServer.forGet("/registry.txt").thenReply(200, registryContent); + await mockServer + .forGet("/settings.yaml") + .thenReply(200, MOCK_SETTINGS_CONTENT); + await mockServer + .forGet("/fixed-limit.rain") + .thenReply(200, FIRST_DOTRAIN_CONTENT); + await mockServer + .forGet("/auction-dca.rain") + .thenReply(200, SECOND_DOTRAIN_CONTENT); + + const result = await DotrainRegistry.new( + "http://localhost:8231/registry.txt", + ); + registry = extractWasmEncodedData(result); + }); + + it("should get order keys", () => { + const keys = extractWasmEncodedData(registry.getOrderKeys()); + + assert.strictEqual(keys.length, 2); + assert(keys.includes("fixed-limit")); + assert(keys.includes("auction-dca")); + }); + + it("should get all order details", () => { + const orderDetails = extractWasmEncodedData( + registry.getAllOrderDetails(), + ); + + assert.strictEqual(orderDetails.valid.size, 2); + assert.strictEqual(orderDetails.invalid.size, 0); + assert(orderDetails.valid.has("fixed-limit")); + assert(orderDetails.valid.has("auction-dca")); + + const fixedLimitDetails = orderDetails.valid.get("fixed-limit"); + assert(fixedLimitDetails); + assert.strictEqual(fixedLimitDetails.name, "Test builder"); + assert.strictEqual(fixedLimitDetails.description, "Test description"); + assert.strictEqual( + fixedLimitDetails.short_description, + "Test short description", + ); + }); + + it("should handle mixed valid and invalid orders", async () => { + mockServer.reset(); + + const registryContent = `http://localhost:8231/settings.yaml valid-order http://localhost:8231/valid.rain invalid-order http://localhost:8231/invalid.rain`; - await mockServer.forGet('/registry.txt').thenReply(200, registryContent); - await mockServer.forGet('/settings.yaml').thenReply(200, MOCK_SETTINGS_CONTENT); - await mockServer.forGet('/valid.rain').thenReply(200, FIRST_DOTRAIN_CONTENT); - await mockServer.forGet('/invalid.rain').thenReply(200, 'not a dotrain file'); - - const registryResult = await DotrainRegistry.new('http://localhost:8231/registry.txt'); - const mixedRegistry = extractWasmEncodedData(registryResult); - - const orderDetails = extractWasmEncodedData(mixedRegistry.getAllOrderDetails()); - - assert.strictEqual(orderDetails.valid.size, 1); - assert.strictEqual(orderDetails.invalid.size, 1); - assert(orderDetails.valid.has('valid-order')); - assert(orderDetails.invalid.has('invalid-order')); - }); - - it('should get deployment details for specific order', () => { - const deploymentDetails = extractWasmEncodedData( - registry.getDeploymentDetails('fixed-limit') - ); - - assert.strictEqual(deploymentDetails.size, 2); - assert(deploymentDetails.has('flare')); - assert(deploymentDetails.has('base')); - - const flareDetails = deploymentDetails.get('flare'); - assert(flareDetails); - assert.strictEqual(flareDetails.name, 'Flare order name'); - assert.strictEqual(flareDetails.description, 'Flare order description'); - - const baseDetails = deploymentDetails.get('base'); - assert(baseDetails); - assert.strictEqual(baseDetails.name, 'Base order name'); - assert.strictEqual(baseDetails.description, 'Base order description'); - }); - - it('should handle deployment details for non-existent order', () => { - const result = registry.getDeploymentDetails('non-existent'); - assert(result.error); - assert(result.error.readableMsg.includes("order key 'non-existent' was not found")); - }); - }); - - describe('DotrainRegistry Builder Creation', () => { - let registry: DotrainRegistry; - - beforeEach(async () => { - const registryContent = `http://localhost:8231/settings.yaml + await mockServer.forGet("/registry.txt").thenReply(200, registryContent); + await mockServer + .forGet("/settings.yaml") + .thenReply(200, MOCK_SETTINGS_CONTENT); + await mockServer + .forGet("/valid.rain") + .thenReply(200, FIRST_DOTRAIN_CONTENT); + await mockServer + .forGet("/invalid.rain") + .thenReply(200, "not a dotrain file"); + + const registryResult = await DotrainRegistry.new( + "http://localhost:8231/registry.txt", + ); + const mixedRegistry = extractWasmEncodedData(registryResult); + + const orderDetails = extractWasmEncodedData( + mixedRegistry.getAllOrderDetails(), + ); + + assert.strictEqual(orderDetails.valid.size, 1); + assert.strictEqual(orderDetails.invalid.size, 1); + assert(orderDetails.valid.has("valid-order")); + assert(orderDetails.invalid.has("invalid-order")); + }); + + it("should get deployment details for specific order", () => { + const deploymentDetails = extractWasmEncodedData( + registry.getDeploymentDetails("fixed-limit"), + ); + + assert.strictEqual(deploymentDetails.size, 2); + assert(deploymentDetails.has("flare")); + assert(deploymentDetails.has("base")); + + const flareDetails = deploymentDetails.get("flare"); + assert(flareDetails); + assert.strictEqual(flareDetails.name, "Flare order name"); + assert.strictEqual(flareDetails.description, "Flare order description"); + + const baseDetails = deploymentDetails.get("base"); + assert(baseDetails); + assert.strictEqual(baseDetails.name, "Base order name"); + assert.strictEqual(baseDetails.description, "Base order description"); + }); + + it("should handle deployment details for non-existent order", () => { + const result = registry.getDeploymentDetails("non-existent"); + assert(result.error); + assert( + result.error.readableMsg.includes( + "order key 'non-existent' was not found", + ), + ); + }); + }); + + describe("DotrainRegistry Builder Creation", () => { + let registry: DotrainRegistry; + + beforeEach(async () => { + const registryContent = `http://localhost:8231/settings.yaml fixed-limit http://localhost:8231/fixed-limit.rain`; - await mockServer.forGet('/registry.txt').thenReply(200, registryContent); - await mockServer.forGet('/settings.yaml').thenReply(200, MOCK_SETTINGS_CONTENT); - await mockServer.forGet('/fixed-limit.rain').thenReply(200, FIRST_DOTRAIN_CONTENT); - - registry = extractWasmEncodedData( - await DotrainRegistry.new('http://localhost:8231/registry.txt') - ); - }); - - it('should create builder for valid order and deployment', async () => { - const builder = extractWasmEncodedData( - await registry.getOrderBuilder('fixed-limit', 'flare', null, null) - ); - - const currentDeployment = extractWasmEncodedData(builder.getCurrentDeployment()); - - assert.strictEqual(currentDeployment.name, 'Flare order name'); - assert.strictEqual(currentDeployment.description, 'Flare order description'); - }); - - it('should create builder with state update callback', async () => { - const stateCallback = () => {}; - - const builder = extractWasmEncodedData( - await registry.getOrderBuilder('fixed-limit', 'base', null, stateCallback) - ); - - const currentDeployment = extractWasmEncodedData(builder.getCurrentDeployment()); - - assert.strictEqual(currentDeployment.name, 'Base order name'); - assert.strictEqual(currentDeployment.description, 'Base order description'); - }); - - it('should restore builder from serialized state when provided', async () => { - let builder = extractWasmEncodedData( - await registry.getOrderBuilder('fixed-limit', 'flare', null, null) - ); - - builder.setFieldValue('test-binding', '42'); - const serializedState = extractWasmEncodedData(builder.serializeState()); - - builder = extractWasmEncodedData( - await registry.getOrderBuilder('fixed-limit', 'flare', serializedState, null) - ); - - const fieldValue = extractWasmEncodedData<{ value: string }>( - builder.getFieldValue('test-binding') - ); - - assert.strictEqual(fieldValue.value, '42'); - }); - - it('should handle builder creation for non-existent order', async () => { - const result = await registry.getOrderBuilder('non-existent', 'flare', null, null); - assert(result.error); - assert(result.error.readableMsg.includes("order key 'non-existent' was not found")); - }); - }); - - const MOCK_SETTINGS_WITH_TOKENS = ` + await mockServer.forGet("/registry.txt").thenReply(200, registryContent); + await mockServer + .forGet("/settings.yaml") + .thenReply(200, MOCK_SETTINGS_CONTENT); + await mockServer + .forGet("/fixed-limit.rain") + .thenReply(200, FIRST_DOTRAIN_CONTENT); + + registry = extractWasmEncodedData( + await DotrainRegistry.new("http://localhost:8231/registry.txt"), + ); + }); + + it("should create builder for valid order and deployment", async () => { + const builder = extractWasmEncodedData( + await registry.getOrderBuilder("fixed-limit", "flare", null, null), + ); + + const currentDeployment = extractWasmEncodedData( + builder.getCurrentDeployment(), + ); + + assert.strictEqual(currentDeployment.name, "Flare order name"); + assert.strictEqual( + currentDeployment.description, + "Flare order description", + ); + }); + + it("should create builder with state update callback", async () => { + const stateCallback = () => {}; + + const builder = extractWasmEncodedData( + await registry.getOrderBuilder( + "fixed-limit", + "base", + null, + stateCallback, + ), + ); + + const currentDeployment = extractWasmEncodedData( + builder.getCurrentDeployment(), + ); + + assert.strictEqual(currentDeployment.name, "Base order name"); + assert.strictEqual( + currentDeployment.description, + "Base order description", + ); + }); + + it("should restore builder from serialized state when provided", async () => { + let builder = extractWasmEncodedData( + await registry.getOrderBuilder("fixed-limit", "flare", null, null), + ); + + builder.setFieldValue("test-binding", "42"); + const serializedState = extractWasmEncodedData( + builder.serializeState(), + ); + + builder = extractWasmEncodedData( + await registry.getOrderBuilder( + "fixed-limit", + "flare", + serializedState, + null, + ), + ); + + const fieldValue = extractWasmEncodedData<{ value: string }>( + builder.getFieldValue("test-binding"), + ); + + assert.strictEqual(fieldValue.value, "42"); + }); + + it("should handle builder creation for non-existent order", async () => { + const result = await registry.getOrderBuilder( + "non-existent", + "flare", + null, + null, + ); + assert(result.error); + assert( + result.error.readableMsg.includes( + "order key 'non-existent' was not found", + ), + ); + }); + }); + + const MOCK_SETTINGS_WITH_TOKENS = ` version: ${SPEC_VERSION} networks: mainnet: @@ -435,7 +537,7 @@ registrys: network: mainnet `; - const MOCK_DOTRAIN_SIMPLE = ` + const MOCK_DOTRAIN_SIMPLE = ` builder: name: Test Order description: Test description @@ -476,45 +578,53 @@ _ _: 0 0; :; `; - describe('DotrainRegistry getRaindexYaml', () => { - it('should return RaindexYaml instance from settings', async () => { - const registryContent = `http://localhost:8231/settings.yaml + describe("DotrainRegistry getRaindexYaml", () => { + it("should return RaindexYaml instance from settings", async () => { + const registryContent = `http://localhost:8231/settings.yaml test-order http://localhost:8231/order.rain`; - await mockServer.forGet('/registry.txt').thenReply(200, registryContent); - await mockServer.forGet('/settings.yaml').thenReply(200, MOCK_SETTINGS_WITH_TOKENS); - await mockServer.forGet('/order.rain').thenReply(200, MOCK_DOTRAIN_SIMPLE); - - const registry = extractWasmEncodedData( - await DotrainRegistry.new('http://localhost:8231/registry.txt') - ); - - const raindexYamlResult = registry.getRaindexYaml(); - const raindexYaml = extractWasmEncodedData(raindexYamlResult); - - assert.ok(raindexYaml, 'RaindexYaml instance should be returned'); - assert.strictEqual(typeof raindexYaml.getTokens, 'function'); - assert.strictEqual(typeof raindexYaml.getRaindexByAddress, 'function'); - }); - }); - - describe('DotrainRegistry getRaindexClient', () => { - it('should return RaindexClient instance from settings', async () => { - const registryContent = `http://localhost:8231/settings.yaml + await mockServer.forGet("/registry.txt").thenReply(200, registryContent); + await mockServer + .forGet("/settings.yaml") + .thenReply(200, MOCK_SETTINGS_WITH_TOKENS); + await mockServer + .forGet("/order.rain") + .thenReply(200, MOCK_DOTRAIN_SIMPLE); + + const registry = extractWasmEncodedData( + await DotrainRegistry.new("http://localhost:8231/registry.txt"), + ); + + const raindexYamlResult = registry.getRaindexYaml(); + const raindexYaml = extractWasmEncodedData(raindexYamlResult); + + assert.ok(raindexYaml, "RaindexYaml instance should be returned"); + assert.strictEqual(typeof raindexYaml.getTokens, "function"); + assert.strictEqual(typeof raindexYaml.getRaindexByAddress, "function"); + }); + }); + + describe("DotrainRegistry getRaindexClient", () => { + it("should return RaindexClient instance from settings", async () => { + const registryContent = `http://localhost:8231/settings.yaml test-order http://localhost:8231/order.rain`; - await mockServer.forGet('/registry.txt').thenReply(200, registryContent); - await mockServer.forGet('/settings.yaml').thenReply(200, MOCK_SETTINGS_WITH_TOKENS); - await mockServer.forGet('/order.rain').thenReply(200, MOCK_DOTRAIN_SIMPLE); + await mockServer.forGet("/registry.txt").thenReply(200, registryContent); + await mockServer + .forGet("/settings.yaml") + .thenReply(200, MOCK_SETTINGS_WITH_TOKENS); + await mockServer + .forGet("/order.rain") + .thenReply(200, MOCK_DOTRAIN_SIMPLE); - const registry = extractWasmEncodedData( - await DotrainRegistry.new('http://localhost:8231/registry.txt') - ); + const registry = extractWasmEncodedData( + await DotrainRegistry.new("http://localhost:8231/registry.txt"), + ); - const raindexClientResult = await registry.getRaindexClient(); - const raindexClient = extractWasmEncodedData(raindexClientResult); + const raindexClientResult = await registry.getRaindexClient(); + const raindexClient = extractWasmEncodedData(raindexClientResult); - assert.ok(raindexClient, 'RaindexClient instance should be returned'); - }); - }); + assert.ok(raindexClient, "RaindexClient instance should be returned"); + }); + }); }); From ca3fd0fd2178596f233b3fb104f6fb0ad3ed9f4b Mon Sep 17 00:00:00 2001 From: gildlab Date: Tue, 19 May 2026 19:36:34 +0000 Subject: [PATCH 62/69] fix: restore accidentally truncated crates/subgraph/src/raindex_client/order_trade.rs Commit cd18389a5 wiped this file from 990 lines to 0 (impl block deleted), which broke crates/subgraph/src/raindex_client/performance.rs:12 since it calls order_trades_list_all on RaindexSubgraphClient. Restore the file as it was at cd18389a5^ and re-apply OrderbookSubgraphClientError -> Raindex rename. --- .../src/raindex_client/order_trade.rs | 990 ++++++++++++++++++ 1 file changed, 990 insertions(+) diff --git a/crates/subgraph/src/raindex_client/order_trade.rs b/crates/subgraph/src/raindex_client/order_trade.rs index 8b13789179..a8980d20b2 100644 --- a/crates/subgraph/src/raindex_client/order_trade.rs +++ b/crates/subgraph/src/raindex_client/order_trade.rs @@ -1 +1,991 @@ +use super::*; +impl RaindexSubgraphClient { + /// Fetch single order take + pub async fn order_trade_detail(&self, id: Id) -> Result { + let data = self + .query::(SgIdQueryVariables { id: &id }) + .await?; + let order_take = data.trade.ok_or(RaindexSubgraphClientError::Empty)?; + + Ok(order_take) + } + + /// Fetch all order takes paginated for a single order + pub async fn order_trades_list( + &self, + order_id: cynic::Id, + pagination_args: SgPaginationArgs, + start_timestamp: Option, + end_timestamp: Option, + ) -> Result, RaindexSubgraphClientError> { + let pagination_variables = Self::parse_pagination_args(pagination_args); + let data = self + .query::( + SgPaginationWithTimestampQueryVariables { + id: SgBytes(order_id.inner().to_string()), + first: pagination_variables.first, + skip: pagination_variables.skip, + timestamp_gte: Some( + start_timestamp + .map_or(SgBigInt("0".to_string()), |v| SgBigInt(v.to_string())), + ), + timestamp_lte: Some( + end_timestamp + .map_or(SgBigInt(u64::MAX.to_string()), |v| SgBigInt(v.to_string())), + ), + }, + ) + .await?; + + Ok(data.trades) + } + + pub async fn trades_by_transaction( + &self, + tx_id: String, + raindex_in: Option>, + ) -> Result, RaindexSubgraphClientError> { + let mut all_trades = vec![]; + let mut page = 1; + + loop { + let pagination_variables = Self::parse_pagination_args(SgPaginationArgs { + page, + page_size: ALL_PAGES_QUERY_PAGE_SIZE, + }); + let data = self + .query::( + SgPaginationWithTxIdQueryVariables { + tx_id: tx_id.clone(), + first: pagination_variables.first, + skip: pagination_variables.skip, + raindex_in: raindex_in.clone(), + }, + ) + .await?; + + let page_len = data.trades.len(); + all_trades.extend(data.trades); + if page_len < ALL_PAGES_QUERY_PAGE_SIZE as usize { + break; + } + page += 1; + } + all_trades.sort_by(|a, b| { + let a_timestamp = a.timestamp.0.parse::().unwrap_or(0); + let b_timestamp = b.timestamp.0.parse::().unwrap_or(0); + b_timestamp + .cmp(&a_timestamp) + .then_with(|| a.id.0.cmp(&b.id.0)) + }); + Ok(all_trades) + } + + pub async fn trades_by_owner( + &self, + owner: String, + start_timestamp: Option, + end_timestamp: Option, + raindex_in: Option>, + pagination_args: SgPaginationArgs, + ) -> Result, RaindexSubgraphClientError> { + let pagination_variables = Self::parse_pagination_args(pagination_args); + let data = self + .query::( + SgOwnerTradesQueryVariables { + owner: SgBytes(owner), + first: pagination_variables.first, + skip: pagination_variables.skip, + timestamp_gte: Some( + start_timestamp + .map_or(SgBigInt("0".to_string()), |v| SgBigInt(v.to_string())), + ), + timestamp_lte: Some( + end_timestamp + .map_or(SgBigInt(u64::MAX.to_string()), |v| SgBigInt(v.to_string())), + ), + raindex_in, + }, + ) + .await?; + + Ok(data.trades) + } + + /// Fetch a single page of trades matching the provided filters. + /// + /// The filters are passed directly to the subgraph `trades` query and + /// pagination is converted with `parse_pagination_args`. Results are ordered + /// by timestamp descending by the GraphQL query. Subgraph query errors are + /// returned as `RaindexSubgraphClientError`. + pub async fn trades_list( + &self, + filters: SgTradesListQueryFilters, + pagination_args: SgPaginationArgs, + ) -> Result, RaindexSubgraphClientError> { + let pagination_variables = Self::parse_pagination_args(pagination_args); + let data = self + .query::(SgTradesListQueryVariables { + first: pagination_variables.first, + skip: pagination_variables.skip, + filters: Some(filters), + }) + .await?; + + Ok(data.trades) + } + + async fn fetch_all_trades_pages( + &self, + filters: SgTradesListQueryFilters, + ) -> Result, RaindexSubgraphClientError> { + let mut all_pages_merged = vec![]; + let mut page: u16 = 1; + + loop { + let page_data = self + .trades_list( + filters.clone(), + SgPaginationArgs { + page, + page_size: ALL_PAGES_QUERY_PAGE_SIZE, + }, + ) + .await?; + let batch_len = page_data.len(); + all_pages_merged.extend(page_data); + if batch_len < ALL_PAGES_QUERY_PAGE_SIZE as usize { + break; + } + page += 1; + } + + Ok(all_pages_merged) + } + + /// Fetch all trades matching the provided filters across every page. + /// + /// This repeatedly calls `trades_list` using the standard all-pages query page + /// size until a partial page is returned. Any subgraph query error encountered + /// while fetching a page is propagated. + pub async fn trades_list_all( + &self, + filters: SgTradesListQueryFilters, + ) -> Result, RaindexSubgraphClientError> { + self.fetch_all_trades_pages(filters).await + } + + /// Count all trades matching the provided filters. + /// + /// This walks every page with `fetch_all_trades_pages` and returns the number + /// of matching trades. Any subgraph query error encountered while fetching + /// pages is propagated. + pub async fn trades_count( + &self, + filters: SgTradesListQueryFilters, + ) -> Result { + Ok(self.fetch_all_trades_pages(filters).await?.len() as u32) + } + + pub async fn trades_by_owner_all( + &self, + owner: String, + start_timestamp: Option, + end_timestamp: Option, + raindex_in: Option>, + ) -> Result, RaindexSubgraphClientError> { + let mut all_trades = vec![]; + let mut page = 1; + + loop { + let page_data = self + .trades_by_owner( + owner.clone(), + start_timestamp, + end_timestamp, + raindex_in.clone(), + SgPaginationArgs { + page, + page_size: ALL_PAGES_QUERY_PAGE_SIZE, + }, + ) + .await?; + let page_len = page_data.len(); + all_trades.extend(page_data); + if page_len < ALL_PAGES_QUERY_PAGE_SIZE as usize { + break; + } + page += 1; + } + Ok(all_trades) + } + + /// Fetch all pages of order_takes_list query + pub async fn order_trades_list_all( + &self, + order_id: cynic::Id, + start_timestamp: Option, + end_timestamp: Option, + ) -> Result, RaindexSubgraphClientError> { + let mut all_pages_merged = vec![]; + let mut page = 1; + + loop { + let page_data = self + .order_trades_list( + order_id.clone(), + SgPaginationArgs { + page, + page_size: ALL_PAGES_QUERY_PAGE_SIZE, + }, + start_timestamp, + end_timestamp, + ) + .await?; + let page_len = page_data.len(); + all_pages_merged.extend(page_data); + if page_len < ALL_PAGES_QUERY_PAGE_SIZE as usize { + break; + } + page += 1 + } + Ok(all_pages_merged) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::types::common::{ + SgBigInt, SgBytes, SgErc20, SgRaindex, SgTradeEvent, SgTradeEventTypename, SgTradeRef, + SgTradeStructPartialOrder, SgTradeVaultBalanceChange, SgTransaction, + SgVaultBalanceChangeVault, + }; + use crate::utils::float::*; + use cynic::Id; + use httpmock::prelude::*; + use reqwest::Url; + use serde_json::json; + + fn setup_client(server: &MockServer) -> RaindexSubgraphClient { + let url = Url::parse(&server.url("")).unwrap(); + RaindexSubgraphClient::new(url) + } + + fn default_sg_transaction() -> SgTransaction { + SgTransaction { + id: SgBytes("0xtransaction_id_default".to_string()), + from: SgBytes("0xfrom_address_default".to_string()), + block_number: SgBigInt("100".to_string()), + timestamp: SgBigInt("1600000000".to_string()), + } + } + + fn default_sg_raindex() -> SgRaindex { + SgRaindex { + id: SgBytes("0xraindex_id_default".to_string()), + } + } + + fn default_sg_erc20() -> SgErc20 { + SgErc20 { + id: SgBytes("0xtoken_id_default".to_string()), + address: SgBytes("0xtoken_address_default".to_string()), + name: Some("Default Token".to_string()), + symbol: Some("DTK".to_string()), + decimals: Some(SgBigInt("18".to_string())), + } + } + + fn default_sg_vault_balance_change_vault() -> SgVaultBalanceChangeVault { + SgVaultBalanceChangeVault { + id: SgBytes("0xvault_id_default".to_string()), + vault_id: SgBytes("12345".to_string()), + token: default_sg_erc20(), + } + } + + fn default_sg_trade_event_typename() -> SgTradeEventTypename { + SgTradeEventTypename { + __typename: "TakeOrder".to_string(), + } + } + + fn default_sg_trade_ref() -> SgTradeRef { + SgTradeRef { + trade_event: default_sg_trade_event_typename(), + } + } + + fn default_sg_trade_vault_balance_change(type_name: &str) -> SgTradeVaultBalanceChange { + SgTradeVaultBalanceChange { + id: SgBytes(format!("0xtrade_vbc_{}_id_default", type_name)), + __typename: "TradeVaultBalanceChange".to_string(), + amount: SgBytes(F1.as_hex()), + new_vault_balance: SgBytes(F5.as_hex()), + old_vault_balance: SgBytes(F4.as_hex()), + vault: default_sg_vault_balance_change_vault(), + timestamp: SgBigInt("1600000100".to_string()), + transaction: default_sg_transaction(), + raindex: default_sg_raindex(), + trade: default_sg_trade_ref(), + } + } + + fn default_sg_trade_event() -> SgTradeEvent { + SgTradeEvent { + transaction: default_sg_transaction(), + sender: SgBytes("0xsender_address_default".to_string()), + } + } + + fn default_sg_trade_struct_partial_order() -> SgTradeStructPartialOrder { + SgTradeStructPartialOrder { + id: SgBytes("0xorder_id_for_trade_default".to_string()), + order_hash: SgBytes("0xorder_hash_for_trade_default".to_string()), + owner: SgBytes("0xowner_address_default".to_string()), + } + } + + fn default_sg_trade() -> SgTrade { + SgTrade { + id: SgBytes("0xtrade_id_default".to_string()), + trade_event: default_sg_trade_event(), + output_vault_balance_change: default_sg_trade_vault_balance_change("output"), + order: default_sg_trade_struct_partial_order(), + input_vault_balance_change: default_sg_trade_vault_balance_change("input"), + timestamp: SgBigInt("1600000200".to_string()), + raindex: default_sg_raindex(), + } + } + + fn sg_trade_with_id_timestamp(id: &str, timestamp: &str) -> SgTrade { + let mut trade = default_sg_trade(); + trade.id = SgBytes(id.to_string()); + trade.timestamp = SgBigInt(timestamp.to_string()); + trade + } + + fn assert_sg_trade_eq(actual: &SgTrade, expected: &SgTrade) { + assert_eq!(actual.id, expected.id, "Trade ID mismatch"); + assert_eq!( + actual.timestamp, expected.timestamp, + "Trade timestamp mismatch" + ); + assert_eq!( + actual.raindex.id, expected.raindex.id, + "Trade raindex ID mismatch" + ); + + // Assert TradeEvent + assert_eq!(actual.trade_event.sender, expected.trade_event.sender); + assert_eq!( + actual.trade_event.transaction.id, + expected.trade_event.transaction.id + ); + + // Assert SgTradeStructPartialOrder + assert_eq!(actual.order.id, expected.order.id); + assert_eq!(actual.order.order_hash, expected.order.order_hash); + + // Assert OutputVaultBalanceChange + let actual_ovbc = &actual.output_vault_balance_change; + let expected_ovbc = &expected.output_vault_balance_change; + assert_eq!(actual_ovbc.id, expected_ovbc.id); + assert_eq!(actual_ovbc.amount, expected_ovbc.amount); + assert_eq!(actual_ovbc.vault.id, expected_ovbc.vault.id); + assert_eq!(actual_ovbc.transaction.id, expected_ovbc.transaction.id); + + // Assert InputVaultBalanceChange + let actual_ivbc = &actual.input_vault_balance_change; + let expected_ivbc = &expected.input_vault_balance_change; + assert_eq!(actual_ivbc.id, expected_ivbc.id); + assert_eq!(actual_ivbc.amount, expected_ivbc.amount); + assert_eq!(actual_ivbc.vault.id, expected_ivbc.vault.id); + assert_eq!(actual_ivbc.transaction.id, expected_ivbc.transaction.id); + } + + #[tokio::test] + async fn test_order_trade_detail_found() { + let sg_server = MockServer::start_async().await; + let client = setup_client(&sg_server); + let trade_id_str = "0xtrade123"; + let trade_id = Id::new(trade_id_str); + let expected_trade = default_sg_trade(); + + sg_server.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"trade": expected_trade}})); + }); + + let result = client.order_trade_detail(trade_id).await; + assert!(result.is_ok(), "Result should be Ok"); + let trade = result.unwrap(); + assert_sg_trade_eq(&trade, &expected_trade); + } + + #[tokio::test] + async fn test_order_trade_detail_not_found() { + let sg_server = MockServer::start_async().await; + let client = setup_client(&sg_server); + let trade_id = Id::new("0xnotfoundtrade"); + + sg_server.mock(|when, then| { + when.method(POST).path("/"); + then.status(200).json_body(json!({"data": {"trade": null}})); + }); + + let result = client.order_trade_detail(trade_id).await; + assert!(matches!(result, Err(RaindexSubgraphClientError::Empty))); + } + + #[tokio::test] + async fn test_order_trade_detail_network_error() { + let sg_server = MockServer::start_async().await; + let client = setup_client(&sg_server); + let trade_id = Id::new("0xtrade123error"); + + sg_server.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + + let result = client.order_trade_detail(trade_id).await; + assert!(matches!( + result, + Err(RaindexSubgraphClientError::CynicClientError(_)) + )); + } + + #[tokio::test] + async fn test_order_trades_list_found_no_timestamp() { + let sg_server = MockServer::start_async().await; + let client = setup_client(&sg_server); + let order_id = Id::new("0xorder1"); + let pagination_args = SgPaginationArgs { + page: 1, + page_size: 10, + }; + let expected_trades = vec![default_sg_trade(), default_sg_trade()]; + + sg_server.mock(|when, then| { + when.method(POST).path("/").body_contains(order_id.inner()); + then.status(200) + .json_body(json!({"data": {"trades": expected_trades}})); + }); + + let result = client + .order_trades_list(order_id, pagination_args, None, None) + .await; + assert!(result.is_ok()); + let trades = result.unwrap(); + assert_eq!(trades.len(), expected_trades.len()); + for (actual, expected) in trades.iter().zip(expected_trades.iter()) { + assert_sg_trade_eq(actual, expected); + } + } + + #[tokio::test] + async fn test_order_trades_list_empty_result() { + let sg_server = MockServer::start_async().await; + let client = setup_client(&sg_server); + let order_id = Id::new("0xorder_empty"); + let pagination_args = SgPaginationArgs { + page: 1, + page_size: 10, + }; + + sg_server.mock(|when, then| { + when.method(POST).path("/").body_contains(order_id.inner()); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + + let result = client + .order_trades_list(order_id, pagination_args, None, None) + .await; + assert!(result.is_ok()); + assert!(result.unwrap().is_empty()); + } + + #[tokio::test] + async fn test_order_trades_list_pagination_second_page() { + let sg_server = MockServer::start_async().await; + let client = setup_client(&sg_server); + let order_id = Id::new("0xorder_page2"); + let page_size = 10; + let pagination_args = SgPaginationArgs { page: 2, page_size }; + let expected_skip = page_size; + let expected_trades = vec![default_sg_trade()]; + + sg_server.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(order_id.inner()) + .body_contains(format!("\"skip\":{}", expected_skip)) + .body_contains(format!("\"first\":{}", page_size)); + then.status(200) + .json_body(json!({"data": {"trades": expected_trades}})); + }); + + let result = client + .order_trades_list(order_id, pagination_args, None, None) + .await; + assert!(result.is_ok()); + let trades = result.unwrap(); + assert_eq!(trades.len(), expected_trades.len()); + } + + #[tokio::test] + async fn test_order_trades_list_network_error() { + let sg_server = MockServer::start_async().await; + let client = setup_client(&sg_server); + let order_id = Id::new("0xorder_network_error"); + let pagination_args = SgPaginationArgs { + page: 1, + page_size: 10, + }; + + sg_server.mock(|when, then| { + when.method(POST).path("/").body_contains(order_id.inner()); + then.status(500); + }); + + let result = client + .order_trades_list(order_id, pagination_args, None, None) + .await; + assert!(matches!( + result, + Err(RaindexSubgraphClientError::CynicClientError(_)) + )); + } + + #[tokio::test] + async fn test_order_trades_list_all_multiple_pages() { + let sg_server = MockServer::start_async().await; + let client = setup_client(&sg_server); + let order_id = Id::new("0xorder_multi_page"); + let trades_page1: Vec = (0..ALL_PAGES_QUERY_PAGE_SIZE) + .map(|_| default_sg_trade()) + .collect(); + let trades_page2: Vec = (0..50).map(|_| default_sg_trade()).collect(); + + sg_server.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(order_id.inner()) + .body_contains(format!("\"first\":{}", ALL_PAGES_QUERY_PAGE_SIZE)) + .body_contains("\"skip\":0"); + then.status(200) + .json_body(json!({"data": {"trades": trades_page1}})); + }); + sg_server.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(order_id.inner()) + .body_contains(format!("\"first\":{}", ALL_PAGES_QUERY_PAGE_SIZE)) + .body_contains(format!("\"skip\":{}", ALL_PAGES_QUERY_PAGE_SIZE)); + then.status(200) + .json_body(json!({"data": {"trades": trades_page2}})); + }); + sg_server.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(order_id.inner()) + .body_contains(format!("\"first\":{}", ALL_PAGES_QUERY_PAGE_SIZE)) + .body_contains(format!("\"skip\":{}", ALL_PAGES_QUERY_PAGE_SIZE * 2)); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + + let result = client.order_trades_list_all(order_id, None, None).await; + assert!(result.is_ok()); + let trades = result.unwrap(); + assert_eq!( + trades.len(), + ALL_PAGES_QUERY_PAGE_SIZE as usize + trades_page2.len() + ); + } + + #[tokio::test] + async fn test_order_trades_list_all_single_page() { + let sg_server = MockServer::start_async().await; + let client = setup_client(&sg_server); + let order_id = Id::new("0xorder_single_page"); + let trades_page1: Vec = (0..50).map(|_| default_sg_trade()).collect(); + + sg_server.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(order_id.inner()) + .body_contains(format!("\"first\":{}", ALL_PAGES_QUERY_PAGE_SIZE)) + .body_contains("\"skip\":0"); + then.status(200) + .json_body(json!({"data": {"trades": trades_page1}})); + }); + sg_server.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(order_id.inner()) + .body_contains(format!("\"first\":{}", ALL_PAGES_QUERY_PAGE_SIZE)) + .body_contains(format!("\"skip\":{}", ALL_PAGES_QUERY_PAGE_SIZE)); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + + let result = client.order_trades_list_all(order_id, None, None).await; + assert!(result.is_ok()); + let trades = result.unwrap(); + assert_eq!(trades.len(), trades_page1.len()); + } + + #[tokio::test] + async fn test_order_trades_list_all_no_trades() { + let sg_server = MockServer::start_async().await; + let client = setup_client(&sg_server); + let order_id = Id::new("0xorder_all_no_trades"); + + sg_server.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(order_id.inner()) + .body_contains(format!("\"first\":{}", ALL_PAGES_QUERY_PAGE_SIZE)) + .body_contains("\"skip\":0"); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + + let result = client.order_trades_list_all(order_id, None, None).await; + assert!(result.is_ok()); + assert!(result.unwrap().is_empty()); + } + + #[tokio::test] + async fn test_trades_by_transaction_found() { + let sg_server = MockServer::start_async().await; + let client = setup_client(&sg_server); + let tx_id = "0xtx_abc123".to_string(); + let expected_trades = vec![default_sg_trade(), default_sg_trade()]; + + sg_server.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"trades": expected_trades}})); + }); + sg_server.mock(|when, then| { + when.method(POST).path("/"); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + + let result = client.trades_by_transaction(tx_id, None).await; + assert!(result.is_ok()); + let trades = result.unwrap(); + assert_eq!(trades.len(), expected_trades.len()); + for (actual, expected) in trades.iter().zip(expected_trades.iter()) { + assert_sg_trade_eq(actual, expected); + } + } + + #[tokio::test] + async fn test_trades_by_transaction_sorts_by_timestamp_then_id() { + let sg_server = MockServer::start_async().await; + let client = setup_client(&sg_server); + let tx_id = "0xtx_sorted".to_string(); + let older = sg_trade_with_id_timestamp("0xtrade_c", "100"); + let same_timestamp_second = sg_trade_with_id_timestamp("0xtrade_b", "200"); + let same_timestamp_first = sg_trade_with_id_timestamp("0xtrade_a", "200"); + + sg_server.mock(|when, then| { + when.method(POST).path("/"); + then.status(200).json_body(json!({ + "data": { + "trades": [ + older, + same_timestamp_second, + same_timestamp_first + ] + } + })); + }); + sg_server.mock(|when, then| { + when.method(POST).path("/"); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + + let trades = client.trades_by_transaction(tx_id, None).await.unwrap(); + let ids: Vec<_> = trades.into_iter().map(|trade| trade.id.0).collect(); + assert_eq!(ids, vec!["0xtrade_a", "0xtrade_b", "0xtrade_c"]); + } + + #[tokio::test] + async fn test_trades_by_transaction_empty() { + let sg_server = MockServer::start_async().await; + let client = setup_client(&sg_server); + let tx_id = "0xtx_empty".to_string(); + + sg_server.mock(|when, then| { + when.method(POST).path("/"); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + + let result = client.trades_by_transaction(tx_id, None).await; + assert!(result.is_ok()); + assert!(result.unwrap().is_empty()); + } + + #[tokio::test] + async fn test_trades_by_transaction_with_raindex_filter() { + let sg_server = MockServer::start_async().await; + let client = setup_client(&sg_server); + let tx_id = "0xtx_raindex_filtered".to_string(); + let raindex = "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef".to_string(); + + sg_server.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(format!("\"raindexIn\":[\"{}\"]", raindex)); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + + let result = client + .trades_by_transaction(tx_id, Some(vec![raindex])) + .await; + assert!(result.is_ok()); + assert!(result.unwrap().is_empty()); + } + + #[tokio::test] + async fn test_trades_by_transaction_multiple_pages() { + let sg_server = MockServer::start_async().await; + let client = setup_client(&sg_server); + let tx_id = "0xtx_multi_page".to_string(); + let trades_page1: Vec = (0..ALL_PAGES_QUERY_PAGE_SIZE) + .map(|_| default_sg_trade()) + .collect(); + let trades_page2: Vec = (0..50).map(|_| default_sg_trade()).collect(); + + sg_server.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(format!("\"first\":{}", ALL_PAGES_QUERY_PAGE_SIZE)) + .body_contains("\"skip\":0"); + then.status(200) + .json_body(json!({"data": {"trades": trades_page1}})); + }); + sg_server.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(format!("\"first\":{}", ALL_PAGES_QUERY_PAGE_SIZE)) + .body_contains(format!("\"skip\":{}", ALL_PAGES_QUERY_PAGE_SIZE)); + then.status(200) + .json_body(json!({"data": {"trades": trades_page2}})); + }); + sg_server.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(format!("\"first\":{}", ALL_PAGES_QUERY_PAGE_SIZE)) + .body_contains(format!("\"skip\":{}", ALL_PAGES_QUERY_PAGE_SIZE * 2)); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + + let result = client.trades_by_transaction(tx_id, None).await; + assert!(result.is_ok()); + let trades = result.unwrap(); + assert_eq!( + trades.len(), + ALL_PAGES_QUERY_PAGE_SIZE as usize + trades_page2.len() + ); + } + + #[tokio::test] + async fn test_trades_by_transaction_network_error() { + let sg_server = MockServer::start_async().await; + let client = setup_client(&sg_server); + let tx_id = "0xtx_error".to_string(); + + sg_server.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + + let result = client.trades_by_transaction(tx_id, None).await; + assert!(matches!( + result, + Err(RaindexSubgraphClientError::CynicClientError(_)) + )); + } + + #[tokio::test] + async fn test_order_trades_list_all_network_error_on_page() { + let sg_server = MockServer::start_async().await; + let client = setup_client(&sg_server); + let order_id = Id::new("0xorder_all_network_error"); + let trades_page1: Vec = (0..ALL_PAGES_QUERY_PAGE_SIZE) + .map(|_| default_sg_trade()) + .collect(); + + sg_server.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(order_id.inner()) + .body_contains(format!("\"first\":{}", ALL_PAGES_QUERY_PAGE_SIZE)) + .body_contains("\"skip\":0"); + then.status(200) + .json_body(json!({"data": {"trades": trades_page1}})); + }); + sg_server.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(order_id.inner()) + .body_contains(format!("\"first\":{}", ALL_PAGES_QUERY_PAGE_SIZE)) + .body_contains(format!("\"skip\":{}", ALL_PAGES_QUERY_PAGE_SIZE)); + then.status(500); + }); + + let result = client.order_trades_list_all(order_id, None, None).await; + assert!(matches!( + result, + Err(RaindexSubgraphClientError::CynicClientError(_)) + )); + } + + #[tokio::test] + async fn test_trades_by_owner_found() { + let sg_server = MockServer::start_async().await; + let client = setup_client(&sg_server); + let owner = "0xowner_abc123".to_string(); + let expected_trades = vec![default_sg_trade(), default_sg_trade()]; + let pagination_args = SgPaginationArgs { + page: 1, + page_size: 10, + }; + + sg_server.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"trades": expected_trades}})); + }); + + let result = client + .trades_by_owner(owner, None, None, None, pagination_args) + .await; + assert!(result.is_ok()); + let trades = result.unwrap(); + assert_eq!(trades.len(), expected_trades.len()); + for (actual, expected) in trades.iter().zip(expected_trades.iter()) { + assert_sg_trade_eq(actual, expected); + } + } + + #[tokio::test] + async fn test_trades_by_owner_empty() { + let sg_server = MockServer::start_async().await; + let client = setup_client(&sg_server); + let owner = "0xowner_empty".to_string(); + let pagination_args = SgPaginationArgs { + page: 1, + page_size: 10, + }; + + sg_server.mock(|when, then| { + when.method(POST).path("/"); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + + let result = client + .trades_by_owner(owner, None, None, None, pagination_args) + .await; + assert!(result.is_ok()); + assert!(result.unwrap().is_empty()); + } + + #[tokio::test] + async fn test_trades_by_owner_with_raindex_filter() { + let sg_server = MockServer::start_async().await; + let client = setup_client(&sg_server); + let owner = "0xowner_filtered".to_string(); + let raindex = "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef".to_string(); + let pagination_args = SgPaginationArgs { + page: 1, + page_size: 10, + }; + + sg_server.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(format!("\"raindexIn\":[\"{}\"]", raindex)); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + + let result = client + .trades_by_owner(owner, None, None, Some(vec![raindex]), pagination_args) + .await; + assert!(result.is_ok()); + assert!(result.unwrap().is_empty()); + } + + #[tokio::test] + async fn test_trades_by_owner_all_multiple_pages() { + let sg_server = MockServer::start_async().await; + let client = setup_client(&sg_server); + let owner = "0xowner_multi_page".to_string(); + let trades_page1: Vec = (0..ALL_PAGES_QUERY_PAGE_SIZE) + .map(|_| default_sg_trade()) + .collect(); + let trades_page2: Vec = (0..50).map(|_| default_sg_trade()).collect(); + + sg_server.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(format!("\"first\":{}", ALL_PAGES_QUERY_PAGE_SIZE)) + .body_contains("\"skip\":0"); + then.status(200) + .json_body(json!({"data": {"trades": trades_page1}})); + }); + sg_server.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(format!("\"first\":{}", ALL_PAGES_QUERY_PAGE_SIZE)) + .body_contains(format!("\"skip\":{}", ALL_PAGES_QUERY_PAGE_SIZE)); + then.status(200) + .json_body(json!({"data": {"trades": trades_page2}})); + }); + sg_server.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(format!("\"first\":{}", ALL_PAGES_QUERY_PAGE_SIZE)) + .body_contains(format!("\"skip\":{}", ALL_PAGES_QUERY_PAGE_SIZE * 2)); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + + let result = client.trades_by_owner_all(owner, None, None, None).await; + assert!(result.is_ok()); + let trades = result.unwrap(); + assert_eq!( + trades.len(), + ALL_PAGES_QUERY_PAGE_SIZE as usize + trades_page2.len() + ); + } + + #[tokio::test] + async fn test_trades_by_owner_network_error() { + let sg_server = MockServer::start_async().await; + let client = setup_client(&sg_server); + let owner = "0xowner_error".to_string(); + let pagination_args = SgPaginationArgs { + page: 1, + page_size: 10, + }; + + sg_server.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + + let result = client + .trades_by_owner(owner, None, None, None, pagination_args) + .await; + assert!(matches!( + result, + Err(RaindexSubgraphClientError::CynicClientError(_)) + )); + } +} From 710c299a9ae64d19f55b735891a3c3335193015d Mon Sep 17 00:00:00 2001 From: gildlab Date: Wed, 20 May 2026 06:10:30 +0000 Subject: [PATCH 63/69] fix: restore multi_raindex_client.rs from main with rename applied --- crates/subgraph/src/multi_raindex_client.rs | 2269 +++++++++++++++++++ 1 file changed, 2269 insertions(+) diff --git a/crates/subgraph/src/multi_raindex_client.rs b/crates/subgraph/src/multi_raindex_client.rs index 8b13789179..dc4fa009a1 100644 --- a/crates/subgraph/src/multi_raindex_client.rs +++ b/crates/subgraph/src/multi_raindex_client.rs @@ -1 +1,2270 @@ +use crate::{ + types::common::{ + SgErc20WithSubgraphName, SgOrderWithSubgraphName, SgOrdersListFilterArgs, + SgTradeWithSubgraphName, SgTradesListQueryFilters, SgVaultWithSubgraphName, + SgVaultsListFilterArgs, + }, + RaindexSubgraphClient, RaindexSubgraphClientError, SgPaginationArgs, +}; +use futures::future::join_all; +use reqwest::Url; +use serde::{Deserialize, Serialize}; +use wasm_bindgen_utils::{impl_wasm_traits, prelude::*}; +#[derive(Debug, Clone, Serialize, Deserialize, Tsify)] +pub struct MultiSubgraphArgs { + #[cfg_attr(target_family = "wasm", tsify(type = "string"))] + pub url: Url, + pub name: String, +} +impl_wasm_traits!(MultiSubgraphArgs); + +pub struct MultiRaindexSubgraphClient { + subgraphs: Vec, +} + +fn sort_trades(trades: &mut [SgTradeWithSubgraphName]) { + trades.sort_by(|a, b| { + let a_timestamp = a.trade.timestamp.0.parse::().unwrap_or(0); + let b_timestamp = b.trade.timestamp.0.parse::().unwrap_or(0); + b_timestamp + .cmp(&a_timestamp) + .then_with(|| a.trade.id.0.cmp(&b.trade.id.0)) + }); +} + +impl MultiRaindexSubgraphClient { + pub fn new(subgraphs: Vec) -> Self { + Self { subgraphs } + } + + fn get_raindex_subgraph_client(&self, url: Url) -> RaindexSubgraphClient { + RaindexSubgraphClient::new(url) + } + + pub async fn orders_list( + &self, + filter_args: SgOrdersListFilterArgs, + pagination_args: SgPaginationArgs, + ) -> Result, RaindexSubgraphClientError> { + let futures = self.subgraphs.iter().map(|subgraph| { + let url = subgraph.url.clone(); + let filter_args = filter_args.clone(); + let pagination_args = pagination_args.clone(); + async move { + let client = self.get_raindex_subgraph_client(url); + let orders = client.orders_list(filter_args, pagination_args).await?; + let wrapped_orders: Vec = orders + .into_iter() + .map(|order| SgOrderWithSubgraphName { + order, + subgraph_name: subgraph.name.clone(), + }) + .collect(); + Ok::<_, RaindexSubgraphClientError>(wrapped_orders) + } + }); + + let results = join_all(futures).await; + + let mut all_orders = Vec::new(); + let mut last_error = None; + for result in results { + match result { + Ok(items) => all_orders.extend(items), + Err(e) => last_error = Some(e), + } + } + if all_orders.is_empty() { + if let Some(e) = last_error { + return Err(e); + } + } + + all_orders.sort_by(|a, b| { + let a_timestamp = a.order.timestamp_added.0.parse::().unwrap_or(0); + let b_timestamp = b.order.timestamp_added.0.parse::().unwrap_or(0); + b_timestamp.cmp(&a_timestamp) + }); + + Ok(all_orders) + } + + pub async fn orders_count( + &self, + filter_args: SgOrdersListFilterArgs, + ) -> Result { + let futures = self.subgraphs.iter().map(|subgraph| { + let url = subgraph.url.clone(); + let filter_args = filter_args.clone(); + async move { + let client = self.get_raindex_subgraph_client(url); + client.orders_count(filter_args).await + } + }); + + let results = join_all(futures).await; + let mut total: u32 = 0; + for result in results { + total += result?; + } + Ok(total) + } + + pub async fn vaults_list( + &self, + filter_args: SgVaultsListFilterArgs, + pagination_args: SgPaginationArgs, + ) -> Result, RaindexSubgraphClientError> { + let futures = self.subgraphs.iter().map(|subgraph| { + let url = subgraph.url.clone(); + let filter_args = filter_args.clone(); + let pagination_args = pagination_args.clone(); + async move { + let client = self.get_raindex_subgraph_client(url); + let vaults = client.vaults_list(filter_args, pagination_args).await?; + let wrapped_vaults: Vec = vaults + .into_iter() + .map(|vault| SgVaultWithSubgraphName { + vault, + subgraph_name: subgraph.name.clone(), + }) + .collect(); + Ok::<_, RaindexSubgraphClientError>(wrapped_vaults) + } + }); + + let results = join_all(futures).await; + + let mut all_vaults = Vec::new(); + let mut last_error = None; + for result in results { + match result { + Ok(items) => all_vaults.extend(items), + Err(e) => last_error = Some(e), + } + } + if all_vaults.is_empty() { + if let Some(e) = last_error { + return Err(e); + } + } + + Ok(all_vaults) + } + + pub async fn trades_by_transaction( + &self, + tx_id: String, + raindex_in: Option>, + ) -> Result, RaindexSubgraphClientError> { + let futures = self.subgraphs.iter().map(|subgraph| { + let url = subgraph.url.clone(); + let subgraph_name = subgraph.name.clone(); + let tx_id = tx_id.clone(); + let raindex_in = raindex_in.clone(); + async move { + let client = self.get_raindex_subgraph_client(url.clone()); + let result = client + .trades_by_transaction(tx_id, raindex_in) + .await + .map(|trades| { + trades + .into_iter() + .map(|trade| SgTradeWithSubgraphName { + trade, + subgraph_name: subgraph_name.clone(), + }) + .collect::>() + }); + (subgraph_name, url, result) + } + }); + + let results = join_all(futures).await; + + let mut all_trades = Vec::new(); + let mut last_error = None; + let mut any_success = false; + for (subgraph_name, url, result) in results { + match result { + Ok(items) => { + any_success = true; + all_trades.extend(items); + } + Err(e) => { + tracing::warn!( + subgraph = %subgraph_name, + url = %url, + error = %e, + "failed to fetch transaction trades from subgraph" + ); + last_error = Some(e); + } + } + } + if !any_success { + if let Some(e) = last_error { + return Err(e); + } + } + + Ok(all_trades) + } + + pub async fn trades_by_owner( + &self, + owner: String, + start_timestamp: Option, + end_timestamp: Option, + raindex_in: Option>, + ) -> Vec { + let futures = self.subgraphs.iter().map(|subgraph| { + let url = subgraph.url.clone(); + let owner = owner.clone(); + let raindex_in = raindex_in.clone(); + async move { + let client = self.get_raindex_subgraph_client(url); + let trades = client + .trades_by_owner_all(owner, start_timestamp, end_timestamp, raindex_in) + .await?; + let wrapped_trades: Vec = trades + .into_iter() + .map(|trade| SgTradeWithSubgraphName { + trade, + subgraph_name: subgraph.name.clone(), + }) + .collect(); + Ok::<_, RaindexSubgraphClientError>(wrapped_trades) + } + }); + + let results = join_all(futures).await; + + results + .into_iter() + .filter_map(Result::ok) + .flatten() + .collect() + } + + /// Fetches the general filtered trades list across every configured subgraph. + /// + /// This backs the SDK-level `RaindexClient.getTrades` API. Order-specific trade + /// history still uses `RaindexSubgraphClient::order_trades_list`. + pub async fn trades_list( + &self, + filters: SgTradesListQueryFilters, + pagination_args: SgPaginationArgs, + ) -> Result, RaindexSubgraphClientError> { + let futures = self.subgraphs.iter().map(|subgraph| { + let url = subgraph.url.clone(); + let subgraph_name = subgraph.name.clone(); + let filters = filters.clone(); + let pagination_args = pagination_args.clone(); + async move { + let client = self.get_raindex_subgraph_client(url.clone()); + let result = client + .trades_list(filters, pagination_args) + .await + .map(|trades| { + trades + .into_iter() + .map(|trade| SgTradeWithSubgraphName { + trade, + subgraph_name: subgraph_name.clone(), + }) + .collect::>() + }); + (subgraph_name, url, result) + } + }); + + let results = join_all(futures).await; + let mut all_trades = Vec::new(); + let mut last_error = None; + let mut any_success = false; + for (subgraph_name, url, result) in results { + match result { + Ok(items) => { + any_success = true; + all_trades.extend(items); + } + Err(e) => { + tracing::warn!( + subgraph = %subgraph_name, + url = %url, + error = %e, + "failed to fetch trades from subgraph" + ); + last_error = Some(e); + } + } + } + if !any_success { + if let Some(e) = last_error { + return Err(e); + } + } + + sort_trades(&mut all_trades); + Ok(all_trades) + } + + /// Fetches all filtered trades across every configured subgraph. + /// + /// This is used when callers need to merge and paginate across multiple data + /// sources after fetching. Order-specific trade history still uses + /// `RaindexSubgraphClient::order_trades_list`. + pub async fn trades_list_all( + &self, + filters: SgTradesListQueryFilters, + ) -> Result, RaindexSubgraphClientError> { + let futures = self.subgraphs.iter().map(|subgraph| { + let url = subgraph.url.clone(); + let subgraph_name = subgraph.name.clone(); + let filters = filters.clone(); + async move { + let client = self.get_raindex_subgraph_client(url.clone()); + let result = client.trades_list_all(filters).await.map(|trades| { + trades + .into_iter() + .map(|trade| SgTradeWithSubgraphName { + trade, + subgraph_name: subgraph_name.clone(), + }) + .collect::>() + }); + (subgraph_name, url, result) + } + }); + + let results = join_all(futures).await; + let mut all_trades = Vec::new(); + let mut last_error = None; + let mut any_success = false; + for (subgraph_name, url, result) in results { + match result { + Ok(items) => { + any_success = true; + all_trades.extend(items); + } + Err(e) => { + tracing::warn!( + subgraph = %subgraph_name, + url = %url, + error = %e, + "failed to fetch all trades from subgraph" + ); + last_error = Some(e); + } + } + } + if !any_success { + if let Some(e) = last_error { + return Err(e); + } + } + + sort_trades(&mut all_trades); + Ok(all_trades) + } + + pub async fn trades_count( + &self, + filters: SgTradesListQueryFilters, + ) -> Result { + let futures = self.subgraphs.iter().map(|subgraph| { + let url = subgraph.url.clone(); + let subgraph_name = subgraph.name.clone(); + let filters = filters.clone(); + async move { + let client = self.get_raindex_subgraph_client(url.clone()); + (subgraph_name, url, client.trades_count(filters).await) + } + }); + + let results = join_all(futures).await; + let mut total: u32 = 0; + let mut last_error = None; + let mut any_success = false; + for (subgraph_name, url, result) in results { + match result { + Ok(count) => { + any_success = true; + total += count; + } + Err(e) => { + tracing::warn!( + subgraph = %subgraph_name, + url = %url, + error = %e, + "failed to count trades from subgraph" + ); + last_error = Some(e); + } + } + } + if !any_success { + if let Some(e) = last_error { + return Err(e); + } + } + Ok(total) + } + + pub async fn tokens_list( + &self, + ) -> Result, RaindexSubgraphClientError> { + let futures = self.subgraphs.iter().map(|subgraph| { + let url = subgraph.url.clone(); + async move { + let client = self.get_raindex_subgraph_client(url); + let tokens = client.tokens_list_all().await?; + let wrapped_tokens: Vec = tokens + .into_iter() + .map(|token| SgErc20WithSubgraphName { + token, + subgraph_name: subgraph.name.clone(), + }) + .collect(); + Ok::<_, RaindexSubgraphClientError>(wrapped_tokens) + } + }); + + let results = join_all(futures).await; + + let mut all_tokens = Vec::new(); + let mut last_error = None; + for result in results { + match result { + Ok(items) => all_tokens.extend(items), + Err(e) => last_error = Some(e), + } + } + if all_tokens.is_empty() { + if let Some(e) = last_error { + return Err(e); + } + } + + Ok(all_tokens) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::cynic_client::CynicClientError; + use crate::raindex_client::ALL_PAGES_QUERY_PAGE_SIZE; + use crate::types::common::{ + SgBigInt, SgBytes, SgErc20, SgOrder, SgOrdersListFilterArgs, SgRaindex, SgTrade, + SgTradeEvent, SgTradeEventTypename, SgTradeRef, SgTradeStructPartialOrder, + SgTradeVaultBalanceChange, SgTradesListQueryFilters, SgTransaction, SgVault, + SgVaultBalanceChangeVault, + }; + use crate::utils::float::*; + use httpmock::prelude::*; + use reqwest::Url; + use serde_json::json; + + fn sample_sg_order(id_suffix: &str, timestamp: &str) -> SgOrder { + SgOrder { + id: SgBytes(format!("0xorder_id_{}", id_suffix)), + order_bytes: SgBytes("0x00".to_string()), + order_hash: SgBytes(format!("0xhash_{}", id_suffix)), + owner: SgBytes("0xdefault_owner".to_string()), + outputs: vec![], + inputs: vec![], + raindex: SgRaindex { + id: SgBytes("0xdefault_raindex_id".to_string()), + }, + active: true, + timestamp_added: SgBigInt(timestamp.to_string()), + meta: None, + add_events: vec![], + trades: vec![], + remove_events: vec![], + } + } + + fn default_filter_args() -> SgOrdersListFilterArgs { + SgOrdersListFilterArgs { + owners: vec![], + active: None, + order_hash: None, + tokens: None, + raindexes: vec![], + has_positive_output_vault_balance: None, + } + } + + fn default_pagination_args() -> SgPaginationArgs { + SgPaginationArgs { + page: 1, + page_size: 10, + } + } + + #[tokio::test] + async fn test_orders_list_no_subgraphs() { + let client = MultiRaindexSubgraphClient::new(vec![]); + let result = client + .orders_list(default_filter_args(), default_pagination_args()) + .await + .unwrap(); + assert!(result.is_empty()); + } + + #[tokio::test] + async fn test_orders_list_one_subgraph_returns_orders() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let sg1_name = "subgraph_alpha"; + + let order1_s1 = sample_sg_order("s1_1", "100"); + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"orders": [order1_s1]}})); + }); + + let client = MultiRaindexSubgraphClient::new(vec![MultiSubgraphArgs { + url: sg1_url, + name: sg1_name.to_string(), + }]); + + let orders = client + .orders_list(default_filter_args(), default_pagination_args()) + .await + .unwrap(); + assert_eq!(orders.len(), 1); + assert_eq!(orders[0].order.id, order1_s1.id); + assert_eq!(orders[0].subgraph_name, sg1_name); + } + + #[tokio::test] + async fn test_orders_list_multiple_subgraphs_merge_and_sort() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let sg1_name = "sg_one"; + + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + let sg2_name = "sg_two"; + + let order_a_s1 = sample_sg_order("s1_A", "100"); + let order_b_s2 = sample_sg_order("s2_B", "200"); + let order_c_s2 = sample_sg_order("s2_C", "50"); + + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"orders": [order_a_s1]}})); + }); + server2.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"orders": [order_b_s2, order_c_s2]}})); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: sg1_name.to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: sg2_name.to_string(), + }, + ]); + + let orders = client + .orders_list(default_filter_args(), default_pagination_args()) + .await + .unwrap(); + + assert_eq!(orders.len(), 3); + assert_eq!(orders[0].order.id, order_b_s2.id); + assert_eq!(orders[0].subgraph_name, sg2_name); + assert_eq!(orders[1].order.id, order_a_s1.id); + assert_eq!(orders[1].subgraph_name, sg1_name); + assert_eq!(orders[2].order.id, order_c_s2.id); + assert_eq!(orders[2].subgraph_name, sg2_name); + } + + #[tokio::test] + async fn test_orders_list_multiple_subgraphs_some_empty() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let sg1_name = "sg_one"; + + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + let sg2_name = "sg_two_empty"; + + let order_a_s1 = sample_sg_order("s1_A", "100"); + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"orders": [order_a_s1]}})); + }); + server2.mock(|when, then| { + when.method(POST).path("/"); + then.status(200).json_body(json!({"data": {"orders": []}})); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: sg1_name.to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: sg2_name.to_string(), + }, + ]); + let orders = client + .orders_list(default_filter_args(), default_pagination_args()) + .await + .unwrap(); + assert_eq!(orders.len(), 1); + assert_eq!(orders[0].order.id, order_a_s1.id); + assert_eq!(orders[0].subgraph_name, sg1_name); + } + + #[tokio::test] + async fn test_orders_list_one_subgraph_errors_others_succeed() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let sg1_name = "sg_one_ok"; + + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + let sg2_name = "sg_two_error"; + + let order_a_s1 = sample_sg_order("s1_A", "100"); + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"orders": [order_a_s1]}})); + }); + server2.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: sg1_name.to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: sg2_name.to_string(), + }, + ]); + let orders = client + .orders_list(default_filter_args(), default_pagination_args()) + .await + .unwrap(); + assert_eq!(orders.len(), 1); + assert_eq!(orders[0].order.id, order_a_s1.id); + assert_eq!(orders[0].subgraph_name, sg1_name); + } + + #[tokio::test] + async fn test_orders_list_all_subgraphs_error() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let sg1_name = "sg_one_err"; + + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + let sg2_name = "sg_two_err"; + + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + server2.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: sg1_name.to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: sg2_name.to_string(), + }, + ]); + let result = client + .orders_list(default_filter_args(), default_pagination_args()) + .await; + assert!(result.is_err()); + } + + #[tokio::test] + async fn test_orders_list_rate_limited_returns_http_429_error() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let sg1_name = "sg_rate_limited"; + + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(429).body("rate limit exceeded"); + }); + + let client = MultiRaindexSubgraphClient::new(vec![MultiSubgraphArgs { + url: sg1_url, + name: sg1_name.to_string(), + }]); + let result = client + .orders_list(default_filter_args(), default_pagination_args()) + .await; + assert!(result.is_err()); + let err = result.unwrap_err(); + match err { + RaindexSubgraphClientError::CynicClientError(CynicClientError::HttpError { + status, + body, + }) => { + assert_eq!(status, 429); + assert_eq!(body, "rate limit exceeded"); + } + other => panic!("Expected HttpError with status 429, got: {:?}", other), + } + } + + #[tokio::test] + async fn test_orders_list_rate_limited_with_one_successful_subgraph() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let sg1_name = "sg_ok"; + + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + let sg2_name = "sg_rate_limited"; + + let order_a = sample_sg_order("s1_A", "100"); + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"orders": [order_a]}})); + }); + server2.mock(|when, then| { + when.method(POST).path("/"); + then.status(429).body("rate limit exceeded"); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: sg1_name.to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: sg2_name.to_string(), + }, + ]); + let orders = client + .orders_list(default_filter_args(), default_pagination_args()) + .await + .unwrap(); + assert_eq!(orders.len(), 1); + assert_eq!(orders[0].order.id, order_a.id); + assert_eq!(orders[0].subgraph_name, sg1_name); + } + + #[tokio::test] + async fn test_orders_list_invalid_timestamp_string_sorts_as_zero() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let sg1_name = "sg_one"; + + let order_a = sample_sg_order("A", "100"); + let order_b = sample_sg_order("B", "invalid_timestamp"); + let order_c = sample_sg_order("C", "50"); + + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"orders": [order_a, order_b, order_c]}})); + }); + + let client = MultiRaindexSubgraphClient::new(vec![MultiSubgraphArgs { + url: sg1_url, + name: sg1_name.to_string(), + }]); + let orders = client + .orders_list(default_filter_args(), default_pagination_args()) + .await + .unwrap(); + assert_eq!(orders.len(), 3); + assert_eq!(orders[0].order.id, order_a.id); + assert_eq!(orders[1].order.id, order_c.id); + assert_eq!(orders[2].order.id, order_b.id); + } + + #[tokio::test] + async fn test_orders_list_sorts_various_timestamps_correctly() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let sg1_name = "sg_one"; + + let order_a = sample_sg_order("A", "0"); + let order_b = sample_sg_order("B", "9999999999999"); + let order_c = sample_sg_order("C", "1"); + let order_d = sample_sg_order("D", "-10"); + let order_e = sample_sg_order("E", "another_invalid"); + + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(200).json_body( + json!({"data": {"orders": [order_a, order_b, order_c, order_d, order_e]}}), + ); + }); + + let client = MultiRaindexSubgraphClient::new(vec![MultiSubgraphArgs { + url: sg1_url, + name: sg1_name.to_string(), + }]); + let orders = client + .orders_list(default_filter_args(), default_pagination_args()) + .await + .unwrap(); + assert_eq!(orders.len(), 5); + + assert_eq!(orders[0].order.id, order_b.id); + assert_eq!(orders[1].order.id, order_c.id); + + let ids_for_ts_zero: Vec<&SgBytes> = orders + .iter() + .filter(|o| o.order.timestamp_added.0.parse::().unwrap_or(0) == 0) + .map(|o| &o.order.id) + .collect(); + assert!(ids_for_ts_zero.contains(&&order_a.id)); + assert!(ids_for_ts_zero.contains(&&order_e.id)); + assert_eq!(orders[4].order.id, order_d.id); + + let order_ids_sorted: Vec = orders.into_iter().map(|o| o.order.id).collect(); + assert_eq!(order_ids_sorted[0], order_b.id); + assert_eq!(order_ids_sorted[1], order_c.id); + + assert!( + (order_ids_sorted[2] == order_a.id && order_ids_sorted[3] == order_e.id) + || (order_ids_sorted[2] == order_e.id && order_ids_sorted[3] == order_a.id) + ); + assert_eq!(order_ids_sorted[4], order_d.id); + } + + #[tokio::test] + async fn test_orders_count_no_subgraphs() { + let client = MultiRaindexSubgraphClient::new(vec![]); + let count = client.orders_count(default_filter_args()).await.unwrap(); + assert_eq!(count, 0); + } + + #[tokio::test] + async fn test_orders_count_one_subgraph() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + + let orders: Vec<_> = (0..3) + .map(|i| sample_sg_order(&format!("c_{}", i), "100")) + .collect(); + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"orders": orders}})); + }); + + let client = MultiRaindexSubgraphClient::new(vec![MultiSubgraphArgs { + url: sg1_url, + name: "sg_one".to_string(), + }]); + + let count = client.orders_count(default_filter_args()).await.unwrap(); + assert_eq!(count, 3); + } + + #[tokio::test] + async fn test_orders_count_multiple_subgraphs_sums() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + + let orders_s1: Vec<_> = (0..2) + .map(|i| sample_sg_order(&format!("s1_{}", i), "100")) + .collect(); + let orders_s2: Vec<_> = (0..5) + .map(|i| sample_sg_order(&format!("s2_{}", i), "200")) + .collect(); + + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"orders": orders_s1}})); + }); + server2.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"orders": orders_s2}})); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: "sg_one".to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: "sg_two".to_string(), + }, + ]); + + let count = client.orders_count(default_filter_args()).await.unwrap(); + assert_eq!(count, 7); + } + + #[tokio::test] + async fn test_orders_count_one_subgraph_errors_propagates() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + + let orders_s1: Vec<_> = (0..4) + .map(|i| sample_sg_order(&format!("s1_{}", i), "100")) + .collect(); + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"orders": orders_s1}})); + }); + server2.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: "sg_one".to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: "sg_two_err".to_string(), + }, + ]); + + let result = client.orders_count(default_filter_args()).await; + assert!(result.is_err()); + } + + #[tokio::test] + async fn test_orders_count_all_subgraphs_error() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + server2.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: "sg_one_err".to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: "sg_two_err".to_string(), + }, + ]); + + let result = client.orders_count(default_filter_args()).await; + assert!(result.is_err()); + } + + #[tokio::test] + async fn test_orders_count_pagination_boundary() { + use crate::raindex_client::ALL_PAGES_QUERY_PAGE_SIZE; + + let server = MockServer::start_async().await; + let sg_url = Url::parse(&server.url("")).unwrap(); + + let page1_orders: Vec<_> = (0..ALL_PAGES_QUERY_PAGE_SIZE) + .map(|i| sample_sg_order(&format!("p1_{}", i), "100")) + .collect(); + let page2_orders: Vec<_> = (0..10) + .map(|i| sample_sg_order(&format!("p2_{}", i), "100")) + .collect(); + + server.mock(|when, then| { + when.method(POST).path("/").body_contains("\"skip\":0"); + then.status(200) + .json_body(json!({"data": {"orders": page1_orders}})); + }); + server.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(format!("\"skip\":{}", ALL_PAGES_QUERY_PAGE_SIZE)); + then.status(200) + .json_body(json!({"data": {"orders": page2_orders}})); + }); + + let client = MultiRaindexSubgraphClient::new(vec![MultiSubgraphArgs { + url: sg_url, + name: "sg_one".to_string(), + }]); + + let count = client.orders_count(default_filter_args()).await.unwrap(); + assert_eq!(count, ALL_PAGES_QUERY_PAGE_SIZE as u32 + 10); + } + + fn default_sg_transaction() -> SgTransaction { + SgTransaction { + id: SgBytes("0xtransaction_id_default".to_string()), + from: SgBytes("0xfrom_address_default".to_string()), + block_number: SgBigInt("100".to_string()), + timestamp: SgBigInt("1600000000".to_string()), + } + } + + fn default_sg_trade_erc20() -> SgErc20 { + SgErc20 { + id: SgBytes("0xtoken_id_default".to_string()), + address: SgBytes("0xtoken_address_default".to_string()), + name: Some("Default Token".to_string()), + symbol: Some("DTK".to_string()), + decimals: Some(SgBigInt("18".to_string())), + } + } + + fn default_sg_vault_balance_change_vault() -> SgVaultBalanceChangeVault { + SgVaultBalanceChangeVault { + id: SgBytes("0xvault_id_default".to_string()), + vault_id: SgBytes("12345".to_string()), + token: default_sg_trade_erc20(), + } + } + + fn default_sg_trade_event_typename() -> SgTradeEventTypename { + SgTradeEventTypename { + __typename: "TakeOrder".to_string(), + } + } + + fn default_sg_trade_ref() -> SgTradeRef { + SgTradeRef { + trade_event: default_sg_trade_event_typename(), + } + } + + fn default_sg_trade_vault_balance_change(type_name: &str) -> SgTradeVaultBalanceChange { + SgTradeVaultBalanceChange { + id: SgBytes(format!("0xtrade_vbc_{}_id_default", type_name)), + __typename: "TradeVaultBalanceChange".to_string(), + amount: SgBytes(F1.as_hex()), + new_vault_balance: SgBytes(F5.as_hex()), + old_vault_balance: SgBytes(F4.as_hex()), + vault: default_sg_vault_balance_change_vault(), + timestamp: SgBigInt("1600000100".to_string()), + transaction: default_sg_transaction(), + raindex: SgRaindex { + id: SgBytes("0xraindex_id_default".to_string()), + }, + trade: default_sg_trade_ref(), + } + } + + fn default_sg_trade_event() -> SgTradeEvent { + SgTradeEvent { + transaction: default_sg_transaction(), + sender: SgBytes("0xsender_address_default".to_string()), + } + } + + fn default_sg_trade_struct_partial_order() -> SgTradeStructPartialOrder { + SgTradeStructPartialOrder { + id: SgBytes("0xorder_id_for_trade_default".to_string()), + order_hash: SgBytes("0xorder_hash_for_trade_default".to_string()), + owner: SgBytes("0xowner_address_default".to_string()), + } + } + + fn default_sg_trade() -> SgTrade { + SgTrade { + id: SgBytes("0xtrade_id_default".to_string()), + trade_event: default_sg_trade_event(), + output_vault_balance_change: default_sg_trade_vault_balance_change("output"), + order: default_sg_trade_struct_partial_order(), + input_vault_balance_change: default_sg_trade_vault_balance_change("input"), + timestamp: SgBigInt("1600000200".to_string()), + raindex: SgRaindex { + id: SgBytes("0xraindex_id_default".to_string()), + }, + } + } + + fn sample_sg_trade(id: &str, timestamp: &str) -> SgTrade { + SgTrade { + id: SgBytes(id.to_string()), + timestamp: SgBigInt(timestamp.to_string()), + ..default_sg_trade() + } + } + + fn default_trade_filters() -> SgTradesListQueryFilters { + SgTradesListQueryFilters::default() + } + + #[tokio::test] + async fn test_trades_list_no_subgraphs() { + let client = MultiRaindexSubgraphClient::new(vec![]); + let trades = client + .trades_list( + default_trade_filters(), + SgPaginationArgs { + page: 1, + page_size: 10, + }, + ) + .await + .unwrap(); + assert!(trades.is_empty()); + } + + #[tokio::test] + async fn test_trades_list_multiple_subgraphs_merge() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + + let trade_s1 = sample_sg_trade("0xtrade_old", "100"); + let trade_s2 = sample_sg_trade("0xtrade_new", "200"); + server1.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains("\"first\":10") + .body_contains("\"skip\":0"); + then.status(200) + .json_body(json!({"data": {"trades": [trade_s1]}})); + }); + server2.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains("\"first\":10") + .body_contains("\"skip\":0"); + then.status(200) + .json_body(json!({"data": {"trades": [trade_s2]}})); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: "sg_one".to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: "sg_two".to_string(), + }, + ]); + + let trades = client + .trades_list( + default_trade_filters(), + SgPaginationArgs { + page: 1, + page_size: 10, + }, + ) + .await + .unwrap(); + assert_eq!(trades.len(), 2); + let names: std::collections::HashSet<_> = trades + .iter() + .map(|trade| trade.subgraph_name.as_str()) + .collect(); + assert!(names.contains("sg_one")); + assert!(names.contains("sg_two")); + assert_eq!(trades[0].trade.id.0, "0xtrade_new"); + assert_eq!(trades[1].trade.id.0, "0xtrade_old"); + } + + #[tokio::test] + async fn test_trades_list_one_subgraph_errors_others_succeed() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + + let trade_s1 = default_sg_trade(); + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"trades": [trade_s1]}})); + }); + server2.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: "sg_one".to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: "sg_two_err".to_string(), + }, + ]); + + let trades = client + .trades_list( + default_trade_filters(), + SgPaginationArgs { + page: 1, + page_size: 10, + }, + ) + .await + .unwrap(); + assert_eq!(trades.len(), 1); + assert_eq!(trades[0].subgraph_name, "sg_one"); + } + + #[tokio::test] + async fn test_trades_list_every_subgraph_errors() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + server2.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: "sg_one_err".to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: "sg_two_err".to_string(), + }, + ]); + + let result = client + .trades_list( + default_trade_filters(), + SgPaginationArgs { + page: 1, + page_size: 10, + }, + ) + .await; + assert!(result.is_err()); + } + + #[tokio::test] + async fn test_trades_list_all_multiple_subgraphs_merge() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + + let trade_s1 = sample_sg_trade("0xtrade_old", "100"); + let trade_s2 = sample_sg_trade("0xtrade_new", "200"); + server1.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(format!("\"first\":{}", ALL_PAGES_QUERY_PAGE_SIZE)) + .body_contains("\"skip\":0"); + then.status(200) + .json_body(json!({"data": {"trades": [trade_s1]}})); + }); + server2.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(format!("\"first\":{}", ALL_PAGES_QUERY_PAGE_SIZE)) + .body_contains("\"skip\":0"); + then.status(200) + .json_body(json!({"data": {"trades": [trade_s2]}})); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: "sg_one".to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: "sg_two".to_string(), + }, + ]); + + let trades = client + .trades_list_all(default_trade_filters()) + .await + .unwrap(); + assert_eq!(trades.len(), 2); + let names: std::collections::HashSet<_> = trades + .iter() + .map(|trade| trade.subgraph_name.as_str()) + .collect(); + assert!(names.contains("sg_one")); + assert!(names.contains("sg_two")); + assert_eq!(trades[0].trade.id.0, "0xtrade_new"); + assert_eq!(trades[1].trade.id.0, "0xtrade_old"); + } + + #[tokio::test] + async fn test_trades_list_all_one_subgraph_errors_others_succeed() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + + let trade_s1 = default_sg_trade(); + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"trades": [trade_s1]}})); + }); + server2.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: "sg_one".to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: "sg_two_err".to_string(), + }, + ]); + + let trades = client + .trades_list_all(default_trade_filters()) + .await + .unwrap(); + assert_eq!(trades.len(), 1); + assert_eq!(trades[0].subgraph_name, "sg_one"); + } + + #[tokio::test] + async fn test_trades_list_all_every_subgraph_errors() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + server2.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: "sg_one_err".to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: "sg_two_err".to_string(), + }, + ]); + + let result = client.trades_list_all(default_trade_filters()).await; + assert!(result.is_err()); + } + + #[tokio::test] + async fn test_trades_count_no_subgraphs() { + let client = MultiRaindexSubgraphClient::new(vec![]); + let count = client.trades_count(default_trade_filters()).await.unwrap(); + assert_eq!(count, 0); + } + + #[tokio::test] + async fn test_trades_count_multiple_subgraphs_sum() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + + let trades_s1 = vec![default_sg_trade(), default_sg_trade()]; + let trades_s2 = vec![default_sg_trade(), default_sg_trade(), default_sg_trade()]; + server1.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(format!("\"first\":{}", ALL_PAGES_QUERY_PAGE_SIZE)) + .body_contains("\"skip\":0"); + then.status(200) + .json_body(json!({"data": {"trades": trades_s1}})); + }); + server2.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(format!("\"first\":{}", ALL_PAGES_QUERY_PAGE_SIZE)) + .body_contains("\"skip\":0"); + then.status(200) + .json_body(json!({"data": {"trades": trades_s2}})); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: "sg_one".to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: "sg_two".to_string(), + }, + ]); + + let count = client.trades_count(default_trade_filters()).await.unwrap(); + assert_eq!(count, 5); + } + + #[tokio::test] + async fn test_trades_count_one_subgraph_errors_others_succeed() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + + let trades_s1 = vec![default_sg_trade(), default_sg_trade()]; + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"trades": trades_s1}})); + }); + server2.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: "sg_one".to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: "sg_two_err".to_string(), + }, + ]); + + let count = client.trades_count(default_trade_filters()).await.unwrap(); + assert_eq!(count, 2); + } + + #[tokio::test] + async fn test_trades_count_all_subgraphs_error() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + server2.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: "sg_one_err".to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: "sg_two_err".to_string(), + }, + ]); + + let result = client.trades_count(default_trade_filters()).await; + assert!(result.is_err()); + } + + #[tokio::test] + async fn test_trades_by_transaction_no_subgraphs() { + let client = MultiRaindexSubgraphClient::new(vec![]); + let result = client + .trades_by_transaction("0xtx123".to_string(), None) + .await + .unwrap(); + assert!(result.is_empty()); + } + + #[tokio::test] + async fn test_trades_by_transaction_one_subgraph_returns_trades() { + use crate::raindex_client::ALL_PAGES_QUERY_PAGE_SIZE; + + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let sg1_name = "subgraph_alpha"; + let tx_id = "0xtx_abc"; + + let trade1 = default_sg_trade(); + server1.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(tx_id) + .body_contains("\"skip\":0"); + then.status(200) + .json_body(json!({"data": {"trades": [trade1]}})); + }); + server1.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(tx_id) + .body_contains(format!("\"skip\":{}", ALL_PAGES_QUERY_PAGE_SIZE)); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + + let client = MultiRaindexSubgraphClient::new(vec![MultiSubgraphArgs { + url: sg1_url, + name: sg1_name.to_string(), + }]); + + let trades = client + .trades_by_transaction(tx_id.to_string(), None) + .await + .unwrap(); + assert_eq!(trades.len(), 1); + assert_eq!(trades[0].trade.id, trade1.id); + assert_eq!(trades[0].subgraph_name, sg1_name); + } + + #[tokio::test] + async fn test_trades_by_transaction_with_raindex_filter() { + use crate::raindex_client::ALL_PAGES_QUERY_PAGE_SIZE; + + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let sg1_name = "subgraph_ob_filter"; + let tx_id = "0xtx_ob_filter"; + let raindex_addr = "0x1234567890abcdef1234567890abcdef12345678"; + + let trade1 = default_sg_trade(); + server1.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(tx_id) + .body_contains(raindex_addr) + .body_contains("\"skip\":0"); + then.status(200) + .json_body(json!({"data": {"trades": [trade1]}})); + }); + server1.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(tx_id) + .body_contains(raindex_addr) + .body_contains(format!("\"skip\":{}", ALL_PAGES_QUERY_PAGE_SIZE)); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + + let client = MultiRaindexSubgraphClient::new(vec![MultiSubgraphArgs { + url: sg1_url, + name: sg1_name.to_string(), + }]); + + let trades = client + .trades_by_transaction(tx_id.to_string(), Some(vec![raindex_addr.to_string()])) + .await + .unwrap(); + assert_eq!(trades.len(), 1); + assert_eq!(trades[0].trade.id, trade1.id); + assert_eq!(trades[0].subgraph_name, sg1_name); + } + + #[tokio::test] + async fn test_trades_by_transaction_multiple_subgraphs_merge() { + use crate::raindex_client::ALL_PAGES_QUERY_PAGE_SIZE; + + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let sg1_name = "sg_one"; + + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + let sg2_name = "sg_two"; + let tx_id = "0xtx_multi"; + + let trade_s1 = default_sg_trade(); + let trade_s2 = default_sg_trade(); + + server1.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(tx_id) + .body_contains("\"skip\":0"); + then.status(200) + .json_body(json!({"data": {"trades": [trade_s1]}})); + }); + server1.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(tx_id) + .body_contains(format!("\"skip\":{}", ALL_PAGES_QUERY_PAGE_SIZE)); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + server2.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(tx_id) + .body_contains("\"skip\":0"); + then.status(200) + .json_body(json!({"data": {"trades": [trade_s2]}})); + }); + server2.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(tx_id) + .body_contains(format!("\"skip\":{}", ALL_PAGES_QUERY_PAGE_SIZE)); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: sg1_name.to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: sg2_name.to_string(), + }, + ]); + + let trades = client + .trades_by_transaction(tx_id.to_string(), None) + .await + .unwrap(); + assert_eq!(trades.len(), 2); + + let names: std::collections::HashSet<_> = + trades.iter().map(|t| t.subgraph_name.clone()).collect(); + assert!(names.contains(sg1_name)); + assert!(names.contains(sg2_name)); + } + + #[tokio::test] + async fn test_trades_by_transaction_one_subgraph_errors_others_succeed() { + use crate::raindex_client::ALL_PAGES_QUERY_PAGE_SIZE; + + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let sg1_name = "sg_one_ok"; + + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + let sg2_name = "sg_two_error"; + let tx_id = "0xtx_partial"; + + let trade_s1 = default_sg_trade(); + server1.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(tx_id) + .body_contains("\"skip\":0"); + then.status(200) + .json_body(json!({"data": {"trades": [trade_s1]}})); + }); + server1.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(tx_id) + .body_contains(format!("\"skip\":{}", ALL_PAGES_QUERY_PAGE_SIZE)); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + server2.mock(|when, then| { + when.method(POST).path("/").body_contains(tx_id); + then.status(500); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: sg1_name.to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: sg2_name.to_string(), + }, + ]); + let trades = client + .trades_by_transaction(tx_id.to_string(), None) + .await + .unwrap(); + assert_eq!(trades.len(), 1); + assert_eq!(trades[0].trade.id, trade_s1.id); + assert_eq!(trades[0].subgraph_name, sg1_name); + } + + #[tokio::test] + async fn test_trades_by_transaction_all_subgraphs_error() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let sg1_name = "sg_one_err"; + + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + let sg2_name = "sg_two_err"; + let tx_id = "0xtx_all_err"; + + server1.mock(|when, then| { + when.method(POST).path("/").body_contains(tx_id); + then.status(500); + }); + server2.mock(|when, then| { + when.method(POST).path("/").body_contains(tx_id); + then.status(500); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: sg1_name.to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: sg2_name.to_string(), + }, + ]); + let result = client.trades_by_transaction(tx_id.to_string(), None).await; + assert!(result.is_err()); + } + + fn sample_sg_erc20(id_suffix: &str) -> SgErc20 { + SgErc20 { + id: SgBytes(format!("0xtoken_id_{}", id_suffix)), + address: SgBytes(format!("0xtoken_address_{}", id_suffix)), + name: Some(format!("Token {}", id_suffix)), + symbol: Some(format!("TKN{}", id_suffix)), + decimals: Some(SgBigInt("18".to_string())), + } + } + + fn sample_sg_raindex(id_suffix: &str) -> SgRaindex { + SgRaindex { + id: SgBytes(format!("0xraindex_id_{}", id_suffix)), + } + } + + fn sample_sg_vault(id_suffix: &str) -> SgVault { + SgVault { + id: SgBytes(format!("0xvault_id_{}", id_suffix)), + owner: SgBytes(format!("0xowner_vault_{}", id_suffix)), + vault_id: SgBytes(format!( + "{}", + id_suffix + .chars() + .filter_map(|c| c.to_digit(10)) + .fold(0, |acc, digit| acc * 10 + digit) + + 1000 + )), + balance: SgBytes(F1.as_hex()), + token: sample_sg_erc20(id_suffix), + raindex: sample_sg_raindex(id_suffix), + orders_as_output: vec![], + orders_as_input: vec![], + balance_changes: vec![], + } + } + + fn default_vault_filter_args() -> SgVaultsListFilterArgs { + SgVaultsListFilterArgs { + owners: vec![], + hide_zero_balance: false, + tokens: vec![], + raindexes: vec![], + only_active_orders: false, + } + } + + #[tokio::test] + async fn test_vaults_list_no_subgraphs() { + let client = MultiRaindexSubgraphClient::new(vec![]); + let result = client + .vaults_list(default_vault_filter_args(), default_pagination_args()) + .await + .unwrap(); + assert!(result.is_empty()); + } + + #[tokio::test] + async fn test_vaults_list_one_subgraph_returns_vaults() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let sg1_name = "subgraph_gamma"; + + let vault1_s1 = sample_sg_vault("s1_v1"); + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"vaults": [vault1_s1]}})); + }); + + let client = MultiRaindexSubgraphClient::new(vec![MultiSubgraphArgs { + url: sg1_url, + name: sg1_name.to_string(), + }]); + + let vaults = client + .vaults_list(default_vault_filter_args(), default_pagination_args()) + .await + .unwrap(); + assert_eq!(vaults.len(), 1); + assert_eq!(vaults[0].vault.id, vault1_s1.id); + assert_eq!(vaults[0].subgraph_name, sg1_name); + } + + #[tokio::test] + async fn test_vaults_list_multiple_subgraphs_merge() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let sg1_name = "sg_v_one"; + + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + let sg2_name = "sg_v_two"; + + let vault_a_s1 = sample_sg_vault("s1_VA"); + let vault_b_s2 = sample_sg_vault("s2_VB"); + let vault_c_s2 = sample_sg_vault("s2_VC"); + + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"vaults": [vault_a_s1]}})); + }); + server2.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"vaults": [vault_b_s2, vault_c_s2]}})); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: sg1_name.to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: sg2_name.to_string(), + }, + ]); + + let vaults_with_names = client + .vaults_list(default_vault_filter_args(), default_pagination_args()) + .await + .unwrap(); + + assert_eq!(vaults_with_names.len(), 3); + + let mut expected_vault_ids_with_names = std::collections::HashSet::new(); + expected_vault_ids_with_names.insert((vault_a_s1.id.clone(), sg1_name.to_string())); + expected_vault_ids_with_names.insert((vault_b_s2.id.clone(), sg2_name.to_string())); + expected_vault_ids_with_names.insert((vault_c_s2.id.clone(), sg2_name.to_string())); + + let actual_vault_ids_with_names: std::collections::HashSet<_> = vaults_with_names + .into_iter() + .map(|v| (v.vault.id, v.subgraph_name)) + .collect(); + + assert_eq!(actual_vault_ids_with_names, expected_vault_ids_with_names); + } + + #[tokio::test] + async fn test_vaults_list_multiple_subgraphs_some_empty() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let sg1_name = "sg_v_one"; + + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + let sg2_name = "sg_v_two_empty"; + + let vault_a_s1 = sample_sg_vault("s1_VA"); + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"vaults": [vault_a_s1]}})); + }); + server2.mock(|when, then| { + when.method(POST).path("/"); + then.status(200).json_body(json!({"data": {"vaults": []}})); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: sg1_name.to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: sg2_name.to_string(), + }, + ]); + let vaults = client + .vaults_list(default_vault_filter_args(), default_pagination_args()) + .await + .unwrap(); + assert_eq!(vaults.len(), 1); + assert_eq!(vaults[0].vault.id, vault_a_s1.id); + assert_eq!(vaults[0].subgraph_name, sg1_name); + } + + #[tokio::test] + async fn test_vaults_list_one_subgraph_errors_others_succeed() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let sg1_name = "sg_v_one_ok"; + + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + let sg2_name = "sg_v_two_error"; + + let vault_a_s1 = sample_sg_vault("s1_VA"); + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"vaults": [vault_a_s1]}})); + }); + server2.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: sg1_name.to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: sg2_name.to_string(), + }, + ]); + let vaults = client + .vaults_list(default_vault_filter_args(), default_pagination_args()) + .await + .unwrap(); + assert_eq!(vaults.len(), 1); + assert_eq!(vaults[0].vault.id, vault_a_s1.id); + assert_eq!(vaults[0].subgraph_name, sg1_name); + } + + #[tokio::test] + async fn test_vaults_list_all_subgraphs_error() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let sg1_name = "sg_v_one_err"; + + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + let sg2_name = "sg_v_two_err"; + + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + server2.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: sg1_name.to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: sg2_name.to_string(), + }, + ]); + let result = client + .vaults_list(default_vault_filter_args(), default_pagination_args()) + .await; + assert!(result.is_err()); + } + + #[tokio::test] + async fn test_trades_by_owner_no_subgraphs() { + let client = MultiRaindexSubgraphClient::new(vec![]); + let result = client + .trades_by_owner("0xowner".to_string(), None, None, None) + .await; + assert!(result.is_empty()); + } + + #[tokio::test] + async fn test_trades_by_owner_one_subgraph_returns_trades() { + let server = MockServer::start_async().await; + let sg_url = Url::parse(&server.url("")).unwrap(); + let sg_name = "sg_owner"; + let owner = "0xowner_abc"; + + let trade1 = default_sg_trade(); + server.mock(|when, then| { + when.method(POST).path("/").body_contains(owner); + then.status(200) + .json_body(json!({"data": {"trades": [trade1]}})); + }); + server.mock(|when, then| { + when.method(POST).path("/").body_contains(owner); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + + let client = MultiRaindexSubgraphClient::new(vec![MultiSubgraphArgs { + url: sg_url, + name: sg_name.to_string(), + }]); + + let trades = client + .trades_by_owner(owner.to_string(), None, None, None) + .await; + assert_eq!(trades.len(), 1); + assert_eq!(trades[0].trade.id, trade1.id); + assert_eq!(trades[0].subgraph_name, sg_name); + } + + #[tokio::test] + async fn test_trades_by_owner_multiple_subgraphs_merge() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let sg1_name = "sg_one"; + + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + let sg2_name = "sg_two"; + + let owner = "0xowner_multi"; + let trade_s1 = default_sg_trade(); + let trade_s2 = default_sg_trade(); + + server1.mock(|when, then| { + when.method(POST).path("/").body_contains(owner); + then.status(200) + .json_body(json!({"data": {"trades": [trade_s1]}})); + }); + server1.mock(|when, then| { + when.method(POST).path("/").body_contains(owner); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + server2.mock(|when, then| { + when.method(POST).path("/").body_contains(owner); + then.status(200) + .json_body(json!({"data": {"trades": [trade_s2]}})); + }); + server2.mock(|when, then| { + when.method(POST).path("/").body_contains(owner); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: sg1_name.to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: sg2_name.to_string(), + }, + ]); + + let trades = client + .trades_by_owner(owner.to_string(), None, None, None) + .await; + assert_eq!(trades.len(), 2); + + let names: std::collections::HashSet<_> = + trades.iter().map(|t| t.subgraph_name.clone()).collect(); + assert!(names.contains(sg1_name)); + assert!(names.contains(sg2_name)); + } + + #[tokio::test] + async fn test_trades_by_owner_with_time_filters() { + let server = MockServer::start_async().await; + let sg_url = Url::parse(&server.url("")).unwrap(); + let sg_name = "sg_time"; + let owner = "0xowner_time"; + + let trade1 = default_sg_trade(); + server.mock(|when, then| { + when.method(POST).path("/").body_contains(owner); + then.status(200) + .json_body(json!({"data": {"trades": [trade1]}})); + }); + server.mock(|when, then| { + when.method(POST).path("/").body_contains(owner); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + + let client = MultiRaindexSubgraphClient::new(vec![MultiSubgraphArgs { + url: sg_url, + name: sg_name.to_string(), + }]); + + let trades = client + .trades_by_owner(owner.to_string(), Some(1000), Some(2000), None) + .await; + assert_eq!(trades.len(), 1); + assert_eq!(trades[0].trade.id, trade1.id); + } + + #[tokio::test] + async fn test_trades_by_owner_with_raindex_filter() { + let server = MockServer::start_async().await; + let sg_url = Url::parse(&server.url("")).unwrap(); + let sg_name = "sg_ob_filter"; + let owner = "0xowner_ob"; + let raindex_addr = "0x1234567890abcdef1234567890abcdef12345678"; + + let trade1 = default_sg_trade(); + server.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(owner) + .body_contains(raindex_addr); + then.status(200) + .json_body(json!({"data": {"trades": [trade1]}})); + }); + server.mock(|when, then| { + when.method(POST) + .path("/") + .body_contains(owner) + .body_contains(raindex_addr); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + + let client = MultiRaindexSubgraphClient::new(vec![MultiSubgraphArgs { + url: sg_url, + name: sg_name.to_string(), + }]); + + let trades = client + .trades_by_owner( + owner.to_string(), + None, + None, + Some(vec![raindex_addr.to_string()]), + ) + .await; + assert_eq!(trades.len(), 1); + assert_eq!(trades[0].trade.id, trade1.id); + } + + #[tokio::test] + async fn test_trades_by_owner_one_subgraph_errors_others_succeed() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + let sg1_name = "sg_one_ok"; + + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + let sg2_name = "sg_two_error"; + + let owner = "0xowner_partial"; + let trade_s1 = default_sg_trade(); + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(200) + .json_body(json!({"data": {"trades": [trade_s1]}})); + }); + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(200).json_body(json!({"data": {"trades": []}})); + }); + server2.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: sg1_name.to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: sg2_name.to_string(), + }, + ]); + let trades = client + .trades_by_owner(owner.to_string(), None, None, None) + .await; + assert_eq!(trades.len(), 1); + assert_eq!(trades[0].trade.id, trade_s1.id); + assert_eq!(trades[0].subgraph_name, sg1_name); + } + + #[tokio::test] + async fn test_trades_by_owner_all_subgraphs_error() { + let server1 = MockServer::start_async().await; + let sg1_url = Url::parse(&server1.url("")).unwrap(); + + let server2 = MockServer::start_async().await; + let sg2_url = Url::parse(&server2.url("")).unwrap(); + + server1.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + server2.mock(|when, then| { + when.method(POST).path("/"); + then.status(500); + }); + + let client = MultiRaindexSubgraphClient::new(vec![ + MultiSubgraphArgs { + url: sg1_url, + name: "sg_one_err".to_string(), + }, + MultiSubgraphArgs { + url: sg2_url, + name: "sg_two_err".to_string(), + }, + ]); + let trades = client + .trades_by_owner("0xowner_all_err".to_string(), None, None, None) + .await; + assert!(trades.is_empty()); + } +} From 90b63648e7caf9fc59b6b7c378b73a9ecaf56dc2 Mon Sep 17 00:00:00 2001 From: David Meister Date: Wed, 20 May 2026 09:29:16 +0000 Subject: [PATCH 64/69] fix: update SERIALIZED_STATE constant + version=6 in state_management tests Three rust unit tests in crates/common/src/raindex_order_builder/state_management.rs were stale relative to YAML rename + spec version bump: - SERIALIZED_STATE constant (line 402): the base64 blob encodes the YAML fixtures in raindex_order_builder/mod.rs which got rename-edited (orderbooks: -> raindexes:, etc.). Updated to the new value produced by serialize_state() with the current fixtures. - test_new_from_state_invalid_dotrain: inline dotrain had version: 5, which now fails at the spec-version check ("expected 6, found 5") before the test could reach the dotrain-mismatch assertion. Bumped to version: 6 so parsing proceeds; the dotrain is still distinct from get_yaml() so DotrainMismatch still fires as expected. --- crates/common/src/raindex_order_builder/state_management.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/common/src/raindex_order_builder/state_management.rs b/crates/common/src/raindex_order_builder/state_management.rs index b290f634b8..642398d10b 100644 --- a/crates/common/src/raindex_order_builder/state_management.rs +++ b/crates/common/src/raindex_order_builder/state_management.rs @@ -399,7 +399,7 @@ mod tests { use raindex_app_settings::{network::NetworkCfg, order::VaultType, yaml::YamlParsableHash}; use std::str::FromStr; - const SERIALIZED_STATE: &str = "H4sIAAAAAAAA_2NigABOKJ2UmZeSmZeuawjlMzAwQ2lDAwN0RUaMUAEDBjgLxmCD0iX52al5xthMw64SlccD5RXn56bq5qWWlOcXZcP0yULpjJKSAit9_Zz85MScjPziEisLAwtT_aKCZN3SopxqkApGEMkIs9o1xEMEyhQyCauYgEYwCjGyQ6VDQG5QMGZkgfG9_YwZGJjgnkFzuyHcCkNLS5ArUWSN4LJGlpY6UGZKYKlbVV5aVVJeUl5mYUlyQaJZcGVgVmmuhZNBVmSxQYRFortnaLmPsWGyrTgsLFJzUpNLdMGG6qakFuTkV-am5pUAADgqxtfKAQAA"; + const SERIALIZED_STATE: &str = "H4sIAAAAAAAA_2NigABOKJ2UmZeSmZeuawjlMzAwQ2lDAwN0RUaMUAEDBjgLxmCD0iX52al5xthMw64SlccD5RXn56bq5qWWlOcXZcP0yULpjJKSAit9_Zz85MScjPziEisLAwtT_aKCZN3SopxqkApGEMkIs9o1xEMEyhQyCauYgEYwCjGyQ6VDQG5QMGZkgfG9_YwZGJjgnkFzuyHcCkNLS5ArUWSN4LJGlpY6UGaEYXZEUUFeuWegaXGuUamrh3N4SmmmY2m2c36gX0iEZ0RQbnaZYZVBqm65rTgsLFJzUpNLdMGG6qakFuTkV-am5pUAAINPx5HKAQAA"; fn encode_state(state: &SerializedBuilderState) -> String { let bytes = bincode::serialize(state).unwrap(); @@ -549,7 +549,7 @@ mod tests { #[tokio::test] async fn test_new_from_state_invalid_dotrain() { let dotrain = r#" - version: 5 + version: 6 networks: test: rpcs: From 31a21261974c2438f5b1ea816b5bf06f82612fe6 Mon Sep 17 00:00:00 2001 From: David Meister Date: Wed, 20 May 2026 09:43:46 +0000 Subject: [PATCH 65/69] fix: update test-js-bindings serializedState constant for rename Same root cause as the rust state_management fix: the SERIALIZED_STATE encodes YAML fixtures that got rename-edited (orderbooks: -> raindexes:), so the produced base64 blob no longer matches the constant. Updated to the actual value produced by builder.serializeState() with current fixtures. --- packages/raindex/test/js_api/builder.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/raindex/test/js_api/builder.test.ts b/packages/raindex/test/js_api/builder.test.ts index a81f66b0de..07a12736c6 100644 --- a/packages/raindex/test/js_api/builder.test.ts +++ b/packages/raindex/test/js_api/builder.test.ts @@ -1145,7 +1145,7 @@ describe("Rain Raindex JS API Package Bindgen Tests - Builder", async function ( describe("state management tests", async () => { let serializedState = - "H4sIAAAAAAAA_21QvU7DMBCOAwIJMSDEioTESoibKD9UZWAAyo-KgEhtWVBJTRPVtYPtgAoPwcjKC1Q8ASsbz4PYIOIciOgN_s73fee7z8j4iUVARaSyrlLWT9kAQQ0bC3_Z2x7NiQmVOc3wIWE1Q8csoIc3_YrEKSUzgDWM0bTHnOpNLyj5iFiMqDsuhrpvFTBRKqvbNuVxjyZcqnqIQ88WWWzlgj4UClScSI_ejZorkD42Pibr743J65P38tkxna235xgto3mgo2KHNQdp29G3D9P4jeo3lAN830f_fJWs67obkO5c3ByceYftIBgfHwXxvsB5ilsn7cu9827zujOQXfc-DFhLeqfbS9DDVUKE1ScZ5eMRYeoLJmrdMssBAAA="; + "H4sIAAAAAAAA_21QsU7DMBCNAwIJMSDEioTEionrKEmpylBQVYZKIJFKdAyp20R17GC7BMRHMLLyAxVfwMrG9yA2iLBDo_YGv_O9d757BtZfbGtURCp4m7JRyiZA15C1tcjeR3RGbF3ZMAyfEtawTKxr9NCxX5PgSrKmsYEQWPUYrt_MgpJnBDKiCi6mpm9fY6JU3nIcyuOIJlyqVhM1PUfkMZwJ-lQqQHkCM7obXuzp9Ln9NT_8bM_fX7y37xsbn3y8xmAXbGo6LHc4wMDYDn992NZ_1L-hGuD7PljyVbGu6x7p9KzI6aB7FWZQBQMpewGO-kHnYdznBU2HdxMu8HnvujO-FMPTHd3DVUIEHJGc8seMMPUDQuHlHcsBAAA="; let dotrain3: string; let builder: RaindexOrderBuilder; beforeAll(async () => { From 6ae327441f13c4ac740eeb6a34344035e359ca80 Mon Sep 17 00:00:00 2001 From: David Meister Date: Wed, 20 May 2026 11:18:57 +0000 Subject: [PATCH 66/69] fix: re-run prettier on packages/ui-components/src --- .../src/__fixtures__/RegistryManager.ts | 24 +- .../src/__tests__/BadgeActive.test.ts | 44 +- .../src/__tests__/ButtonDarkMode.test.ts | 82 +- .../src/__tests__/ButtonLoading.test.ts | 46 +- .../src/__tests__/ButtonVaultLink.test.ts | 81 +- .../src/__tests__/CardProperty.test.ts | 16 +- .../src/__tests__/ChartTimeFilters.test.ts | 76 +- .../src/__tests__/Checkbox.test.ts | 122 +- .../CheckboxInactiveOrdersVault.test.ts | 120 +- .../CheckboxZeroBalanceVault.test.ts | 60 +- .../src/__tests__/CodeMirrorDotrain.test.ts | 167 +- .../src/__tests__/CodeMirrorRainlang.test.ts | 129 +- .../__tests__/ComposedRainlangModal.test.ts | 51 +- .../__tests__/DeploymentSectionHeader.test.ts | 92 +- .../src/__tests__/DeploymentSteps.test.ts | 979 +++--- .../src/__tests__/DeploymentTile.test.ts | 36 +- .../src/__tests__/DeploymentsSection.test.ts | 73 +- .../src/__tests__/DepositInput.test.ts | 146 +- .../src/__tests__/DisclaimerModal.test.ts | 76 +- .../__tests__/DotrainRegistryProvider.test.ts | 98 +- .../__tests__/DropdownActiveNetworks.test.ts | 134 +- .../src/__tests__/DropdownCheckbox.test.ts | 398 +-- .../src/__tests__/DropdownProperty.test.ts | 38 +- .../src/__tests__/DropdownRadio.test.ts | 230 +- .../__tests__/DropdownRaindexesFilter.test.ts | 1042 +++--- .../__tests__/DropdownTokensFilter.test.ts | 1067 ++++--- .../src/__tests__/EditableSpan.test.ts | 30 +- .../__tests__/FieldDefinitionInput.test.ts | 308 +- .../__tests__/FixedBottomTransaction.test.ts | 788 ++--- .../ui-components/src/__tests__/Hash.test.ts | 110 +- .../src/__tests__/InputHex.test.ts | 36 +- .../src/__tests__/InputOrderHash.test.ts | 52 +- .../src/__tests__/InputRegistryUrl.test.ts | 144 +- .../src/__tests__/InputToken.test.ts | 90 +- .../src/__tests__/InputTokenAmount.test.ts | 65 +- .../__tests__/InvalidOrdersSection.test.ts | 46 +- .../src/__tests__/License.test.ts | 151 +- .../src/__tests__/LightweightChart.test.ts | 550 ++-- .../__tests__/ListViewRaindexFilters.test.ts | 404 +-- .../src/__tests__/LocalDbStatusBadge.test.ts | 36 +- .../src/__tests__/LocalDbStatusCard.test.ts | 317 +- .../src/__tests__/LocalDbStatusModal.test.ts | 825 ++--- .../src/__tests__/OrderAPY.test.ts | 40 +- .../src/__tests__/OrderDetail.test.ts | 1284 ++++---- .../src/__tests__/OrderOrVaultHash.test.ts | 218 +- .../src/__tests__/OrderPage.test.ts | 226 +- .../src/__tests__/OrderVaultsVolTable.test.ts | 152 +- .../src/__tests__/OrdersListTable.test.ts | 1242 ++++---- .../src/__tests__/PageHeader.test.ts | 128 +- .../src/__tests__/RegistryManager.test.ts | 349 +- .../src/__tests__/SelectToken.test.ts | 900 +++--- .../src/__tests__/ShareChoicesButton.test.ts | 108 +- .../src/__tests__/TableTimeFilters.test.ts | 74 +- .../src/__tests__/TanstackAppTable.test.ts | 386 +-- .../TanstackLightweightChartLine.test.ts | 124 +- .../src/__tests__/TanstackOrderQuote.test.ts | 718 +++-- .../TanstackPageContentDetail.test.ts | 108 +- .../src/__tests__/ToastDetail.test.ts | 232 +- .../src/__tests__/ToastProvider.test.ts | 242 +- .../src/__tests__/TokenBalance.test.ts | 224 +- .../src/__tests__/TokenIOInput.test.ts | 446 +-- .../src/__tests__/TokenSelectionModal.test.ts | 707 +++-- .../src/__tests__/Transaction.test.ts | 760 ++--- .../src/__tests__/TransactionDetail.test.ts | 270 +- .../src/__tests__/TransactionList.test.ts | 418 +-- .../src/__tests__/TransactionManager.test.ts | 2826 +++++++++-------- .../src/__tests__/TransactionProvider.test.ts | 148 +- .../src/__tests__/ValidOrdersSection.test.ts | 58 +- .../VaultBalanceChangeTypeFilter.test.ts | 150 +- .../VaultBalanceChangesTable.test.ts | 427 +-- .../src/__tests__/VaultBalanceChart.test.ts | 30 +- .../src/__tests__/VaultCard.test.ts | 208 +- .../src/__tests__/VaultDetail.test.ts | 493 +-- .../src/__tests__/VaultIdInformation.test.ts | 121 +- .../src/__tests__/VaultsListTable.test.ts | 994 +++--- .../src/__tests__/WalletConnect.test.ts | 110 +- .../src/__tests__/WalletProvider.test.ts | 66 +- .../awaitTransactionIndexing.test.ts | 298 +- .../src/__tests__/breadcrumbs.test.ts | 52 +- .../src/__tests__/getExplorerLink.test.ts | 36 +- .../src/__tests__/handleShareChoices.test.ts | 98 +- .../ui-components/src/__tests__/hex.test.ts | 78 +- .../src/__tests__/loadRegistryUrl.test.ts | 131 +- .../src/__tests__/pairTradesChartData.test.ts | 858 ++--- .../src/__tests__/queryClient.test.ts | 313 +- .../src/__tests__/registry.test.ts | 490 +-- .../src/__tests__/useToasts.test.ts | 336 +- .../src/additional-svelte-typings.d.ts | 10 +- packages/ui-components/src/app.d.ts | 14 +- packages/ui-components/src/app.html | 18 +- .../src/lib/__mocks__/MockComponent.ts | 2 +- .../src/lib/__mocks__/mockWeb3Config.ts | 29 +- .../src/lib/__mocks__/queries.ts | 143 +- .../ui-components/src/lib/__mocks__/stores.ts | 208 +- packages/ui-components/src/lib/app.css | 6 +- .../components/charts/transformAndSortData.ts | 238 +- .../components/transactions/getStatusEmoji.ts | 36 +- packages/ui-components/src/lib/consts.ts | 2 +- .../src/lib/errors/DeploymentStepsError.ts | 100 +- .../ui-components/src/lib/errors/index.ts | 2 +- .../ui-components/src/lib/hooks/useLocalDb.ts | 24 +- .../src/lib/hooks/useRaindexClient.test.ts | 72 +- .../src/lib/hooks/useRaindexClient.ts | 24 +- .../lib/hooks/useRaindexOrderBuilder.test.ts | 71 +- packages/ui-components/src/lib/index.ts | 295 +- .../src/lib/models/Transaction.ts | 216 +- .../lib/providers/dotrainRegistry/context.ts | 87 +- .../dotrainRegistry/useDotrainRegistry.ts | 71 +- .../lib/providers/registry/RegistryManager.ts | 273 +- .../src/lib/providers/registry/context.ts | 76 +- .../src/lib/providers/registry/useRegistry.ts | 42 +- .../src/lib/providers/toasts/context.ts | 24 +- .../src/lib/providers/toasts/useToasts.ts | 106 +- .../transactions/TransactionManager.ts | 1207 +++---- .../src/lib/providers/transactions/context.ts | 25 +- .../providers/transactions/useTransactions.ts | 14 +- .../src/lib/providers/wallet/context.ts | 78 +- .../src/lib/providers/wallet/useAccount.ts | 348 +- .../ui-components/src/lib/queries/keys.ts | 20 +- .../src/lib/queries/queryClient.ts | 37 +- .../lib/services/awaitTransactionIndexing.ts | 272 +- .../src/lib/services/getExplorerLink.ts | 18 +- .../src/lib/services/handleShareChoices.ts | 33 +- .../src/lib/services/historicalOrderCharts.ts | 889 +++--- .../ui-components/src/lib/services/index.ts | 10 +- .../src/lib/services/loadRegistryUrl.ts | 43 +- .../src/lib/services/pairTradesChartData.ts | 413 +-- .../src/lib/services/registry.ts | 170 +- .../ui-components/src/lib/services/time.ts | 184 +- .../lib/storesGeneric/cachedWritableStore.ts | 152 +- .../ui-components/src/lib/test/matchers.ts | 17 +- .../ui-components/src/lib/types/account.ts | 4 +- .../ui-components/src/lib/types/appStores.ts | 20 +- packages/ui-components/src/lib/types/modal.ts | 64 +- packages/ui-components/src/lib/types/order.ts | 12 +- packages/ui-components/src/lib/types/toast.ts | 14 +- .../src/lib/types/tokenBalance.ts | 8 +- .../src/lib/types/transaction.ts | 100 +- .../src/lib/utils/breadcrumbs.ts | 18 +- .../src/lib/utils/codeMirrorThemes.ts | 166 +- .../src/lib/utils/configHelpers.ts | 38 +- .../src/lib/utils/constructHashLink.ts | 221 +- .../src/lib/utils/getNetworkName.ts | 18 +- packages/ui-components/src/lib/utils/hex.ts | 2 +- .../src/lib/utils/lightweightChartsThemes.ts | 64 +- .../ui-components/src/lib/utils/number.ts | 29 +- .../ui-components/src/lib/utils/tokens.ts | 4 +- .../src/lib/utils/vaultBalanceChangeLabels.ts | 44 +- 148 files changed, 17546 insertions(+), 16455 deletions(-) diff --git a/packages/ui-components/src/__fixtures__/RegistryManager.ts b/packages/ui-components/src/__fixtures__/RegistryManager.ts index c9e220f26b..6d9d96725d 100644 --- a/packages/ui-components/src/__fixtures__/RegistryManager.ts +++ b/packages/ui-components/src/__fixtures__/RegistryManager.ts @@ -1,17 +1,17 @@ -import { vi } from 'vitest'; -import type { RegistryManager } from '$lib/providers/registry/RegistryManager'; +import { vi } from "vitest"; +import type { RegistryManager } from "$lib/providers/registry/RegistryManager"; -const mockDefaultRegistry = 'https://example.com/default-registry.json'; +const mockDefaultRegistry = "https://example.com/default-registry.json"; let mockCurrentRegistry: string | null = mockDefaultRegistry; export const initialRegistry: Partial = { - getCurrentRegistry: vi.fn(() => mockCurrentRegistry ?? mockDefaultRegistry), - setRegistry: vi.fn((newRegistry: string) => { - mockCurrentRegistry = newRegistry; - }), - resetToDefault: vi.fn(() => { - mockCurrentRegistry = mockDefaultRegistry; - }), - updateUrlWithRegistry: vi.fn(), - isCustomRegistry: vi.fn(() => mockCurrentRegistry !== mockDefaultRegistry) + getCurrentRegistry: vi.fn(() => mockCurrentRegistry ?? mockDefaultRegistry), + setRegistry: vi.fn((newRegistry: string) => { + mockCurrentRegistry = newRegistry; + }), + resetToDefault: vi.fn(() => { + mockCurrentRegistry = mockDefaultRegistry; + }), + updateUrlWithRegistry: vi.fn(), + isCustomRegistry: vi.fn(() => mockCurrentRegistry !== mockDefaultRegistry), }; diff --git a/packages/ui-components/src/__tests__/BadgeActive.test.ts b/packages/ui-components/src/__tests__/BadgeActive.test.ts index 2ced71d9bb..4c53ec6dc1 100644 --- a/packages/ui-components/src/__tests__/BadgeActive.test.ts +++ b/packages/ui-components/src/__tests__/BadgeActive.test.ts @@ -1,27 +1,27 @@ -import { render, screen } from '@testing-library/svelte'; -import BadgeActive from '../lib/components/BadgeActive.svelte'; -import { describe, it, expect } from 'vitest'; +import { render, screen } from "@testing-library/svelte"; +import BadgeActive from "../lib/components/BadgeActive.svelte"; +import { describe, it, expect } from "vitest"; -describe('BadgeActive', () => { - it('shows "Active" text when active is true', () => { - render(BadgeActive, { props: { active: true } }); - expect(screen.getByText('Active')).toBeInTheDocument(); - }); +describe("BadgeActive", () => { + it('shows "Active" text when active is true', () => { + render(BadgeActive, { props: { active: true } }); + expect(screen.getByText("Active")).toBeInTheDocument(); + }); - it('shows "Inactive" text when active is false', () => { - render(BadgeActive, { props: { active: false } }); - expect(screen.getByText('Inactive')).toBeInTheDocument(); - }); + it('shows "Inactive" text when active is false', () => { + render(BadgeActive, { props: { active: false } }); + expect(screen.getByText("Inactive")).toBeInTheDocument(); + }); - it('uses green color for active state', () => { - render(BadgeActive, { props: { active: true } }); - const badge = screen.getByText('Active'); - expect(badge.className).toContain('bg-green'); - }); + it("uses green color for active state", () => { + render(BadgeActive, { props: { active: true } }); + const badge = screen.getByText("Active"); + expect(badge.className).toContain("bg-green"); + }); - it('uses yellow color for inactive state', () => { - render(BadgeActive, { props: { active: false } }); - const badge = screen.getByText('Inactive'); - expect(badge.className).toContain('bg-yellow'); - }); + it("uses yellow color for inactive state", () => { + render(BadgeActive, { props: { active: false } }); + const badge = screen.getByText("Inactive"); + expect(badge.className).toContain("bg-yellow"); + }); }); diff --git a/packages/ui-components/src/__tests__/ButtonDarkMode.test.ts b/packages/ui-components/src/__tests__/ButtonDarkMode.test.ts index e8cefadde4..f2911af2d8 100644 --- a/packages/ui-components/src/__tests__/ButtonDarkMode.test.ts +++ b/packages/ui-components/src/__tests__/ButtonDarkMode.test.ts @@ -1,56 +1,56 @@ -import { render, screen, fireEvent } from '@testing-library/svelte'; -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import { writable, get, type Writable } from 'svelte/store'; -import ButtonDarkMode from '../lib/components/ButtonDarkMode.svelte'; - -vi.mock('flowbite-svelte', async (importOriginal) => { - const original = await importOriginal(); - return { - ...original, - DarkMode: (await import('../lib/__mocks__/MockComponent.svelte')).default - }; +import { render, screen, fireEvent } from "@testing-library/svelte"; +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { writable, get, type Writable } from "svelte/store"; +import ButtonDarkMode from "../lib/components/ButtonDarkMode.svelte"; + +vi.mock("flowbite-svelte", async (importOriginal) => { + const original = await importOriginal(); + return { + ...original, + DarkMode: (await import("../lib/__mocks__/MockComponent.svelte")).default, + }; }); -describe('ButtonDarkMode.svelte', () => { - let mockColorThemeStore: Writable; +describe("ButtonDarkMode.svelte", () => { + let mockColorThemeStore: Writable; - beforeEach(() => { - mockColorThemeStore = writable(undefined); - document.documentElement.classList.remove('dark'); - }); + beforeEach(() => { + mockColorThemeStore = writable(undefined); + document.documentElement.classList.remove("dark"); + }); - it('renders the button and the DarkMode component', () => { - render(ButtonDarkMode, { props: { colorTheme: mockColorThemeStore } }); + it("renders the button and the DarkMode component", () => { + render(ButtonDarkMode, { props: { colorTheme: mockColorThemeStore } }); - expect(screen.getByRole('button')).toBeInTheDocument(); - expect(screen.getByTestId('mock-component')).toBeInTheDocument(); - }); + expect(screen.getByRole("button")).toBeInTheDocument(); + expect(screen.getByTestId("mock-component")).toBeInTheDocument(); + }); - it('sets colorTheme to "light" when toggled in light mode', async () => { - render(ButtonDarkMode, { props: { colorTheme: mockColorThemeStore } }); - const button = screen.getByRole('button'); + it('sets colorTheme to "light" when toggled in light mode', async () => { + render(ButtonDarkMode, { props: { colorTheme: mockColorThemeStore } }); + const button = screen.getByRole("button"); - expect(document.documentElement.classList.contains('dark')).toBe(false); - expect(get(mockColorThemeStore)).toBeUndefined(); + expect(document.documentElement.classList.contains("dark")).toBe(false); + expect(get(mockColorThemeStore)).toBeUndefined(); - await fireEvent.click(button); + await fireEvent.click(button); - expect(get(mockColorThemeStore)).toBe('light'); - expect(document.documentElement.classList.contains('dark')).toBe(false); - }); + expect(get(mockColorThemeStore)).toBe("light"); + expect(document.documentElement.classList.contains("dark")).toBe(false); + }); - it('sets colorTheme to "dark" when clicked in dark mode', async () => { - document.documentElement.classList.add('dark'); + it('sets colorTheme to "dark" when clicked in dark mode', async () => { + document.documentElement.classList.add("dark"); - render(ButtonDarkMode, { props: { colorTheme: mockColorThemeStore } }); - const button = screen.getByRole('button'); + render(ButtonDarkMode, { props: { colorTheme: mockColorThemeStore } }); + const button = screen.getByRole("button"); - expect(document.documentElement.classList.contains('dark')).toBe(true); - expect(get(mockColorThemeStore)).toBeUndefined(); + expect(document.documentElement.classList.contains("dark")).toBe(true); + expect(get(mockColorThemeStore)).toBeUndefined(); - await fireEvent.click(button); + await fireEvent.click(button); - expect(get(mockColorThemeStore)).toBe('dark'); - expect(document.documentElement.classList.contains('dark')).toBe(true); - }); + expect(get(mockColorThemeStore)).toBe("dark"); + expect(document.documentElement.classList.contains("dark")).toBe(true); + }); }); diff --git a/packages/ui-components/src/__tests__/ButtonLoading.test.ts b/packages/ui-components/src/__tests__/ButtonLoading.test.ts index f4187386ac..98185a6231 100644 --- a/packages/ui-components/src/__tests__/ButtonLoading.test.ts +++ b/packages/ui-components/src/__tests__/ButtonLoading.test.ts @@ -1,27 +1,27 @@ -import { render, screen } from '@testing-library/svelte'; -import { describe, it, expect } from 'vitest'; -import ButtonLoading from '../lib/components/ButtonLoading.svelte'; +import { render, screen } from "@testing-library/svelte"; +import { describe, it, expect } from "vitest"; +import ButtonLoading from "../lib/components/ButtonLoading.svelte"; -describe('ButtonLoading', () => { - it('should render a button with a spinner when loading is true', () => { - render(ButtonLoading, { - loading: true - }); - expect(screen.getByTestId('spinner')).toBeInTheDocument(); - }); +describe("ButtonLoading", () => { + it("should render a button with a spinner when loading is true", () => { + render(ButtonLoading, { + loading: true, + }); + expect(screen.getByTestId("spinner")).toBeInTheDocument(); + }); - it('should disable the button when loading is true', () => { - render(ButtonLoading, { - loading: true - }); - const button = screen.getByRole('button'); - expect(button).toBeDisabled(); - }); + it("should disable the button when loading is true", () => { + render(ButtonLoading, { + loading: true, + }); + const button = screen.getByRole("button"); + expect(button).toBeDisabled(); + }); - it('should not render a spinner when loading is false', () => { - render(ButtonLoading, { - loading: false - }); - expect(screen.queryByTestId('spinner')).not.toBeInTheDocument(); - }); + it("should not render a spinner when loading is false", () => { + render(ButtonLoading, { + loading: false, + }); + expect(screen.queryByTestId("spinner")).not.toBeInTheDocument(); + }); }); diff --git a/packages/ui-components/src/__tests__/ButtonVaultLink.test.ts b/packages/ui-components/src/__tests__/ButtonVaultLink.test.ts index 9dff7fa6c0..3e2a95dfc4 100644 --- a/packages/ui-components/src/__tests__/ButtonVaultLink.test.ts +++ b/packages/ui-components/src/__tests__/ButtonVaultLink.test.ts @@ -1,45 +1,48 @@ -import { describe, it, expect } from 'vitest'; -import { render, screen } from '@testing-library/svelte'; -import ButtonVaultLink from '../lib/components/ButtonVaultLink.svelte'; -import type { RaindexVault } from '@rainlanguage/raindex'; +import { describe, it, expect } from "vitest"; +import { render, screen } from "@testing-library/svelte"; +import ButtonVaultLink from "../lib/components/ButtonVaultLink.svelte"; +import type { RaindexVault } from "@rainlanguage/raindex"; -describe('ButtonVaultLink', () => { - const mockVault = { - id: '123', - vaultId: BigInt(1000), - balance: BigInt('1000000000000000000'), - token: { - name: 'Test Token', - symbol: 'TEST', - decimals: '18' - } - } as unknown as RaindexVault; +describe("ButtonVaultLink", () => { + const mockVault = { + id: "123", + vaultId: BigInt(1000), + balance: BigInt("1000000000000000000"), + token: { + name: "Test Token", + symbol: "TEST", + decimals: "18", + }, + } as unknown as RaindexVault; - it('should render vault information correctly', () => { - render(ButtonVaultLink, { - props: { - tokenVault: mockVault, - chainId: 1, - raindexAddress: '0x00' - } - }); + it("should render vault information correctly", () => { + render(ButtonVaultLink, { + props: { + tokenVault: mockVault, + chainId: 1, + raindexAddress: "0x00", + }, + }); - const vaultLink = screen.getByTestId('vault-link'); - expect(vaultLink).toBeTruthy(); - expect(vaultLink).toHaveTextContent('Test Token'); - expect(vaultLink).toHaveTextContent('TEST'); - }); + const vaultLink = screen.getByTestId("vault-link"); + expect(vaultLink).toBeTruthy(); + expect(vaultLink).toHaveTextContent("Test Token"); + expect(vaultLink).toHaveTextContent("TEST"); + }); - it('should set the link id attribute correctly', () => { - render(ButtonVaultLink, { - props: { - tokenVault: mockVault, - chainId: 1, - raindexAddress: '0x00' - } - }); + it("should set the link id attribute correctly", () => { + render(ButtonVaultLink, { + props: { + tokenVault: mockVault, + chainId: 1, + raindexAddress: "0x00", + }, + }); - const linkElement = screen.getByRole('link'); - expect(linkElement).toHaveAttribute('id', `token-info-${mockVault.vaultId}`); - }); + const linkElement = screen.getByRole("link"); + expect(linkElement).toHaveAttribute( + "id", + `token-info-${mockVault.vaultId}`, + ); + }); }); diff --git a/packages/ui-components/src/__tests__/CardProperty.test.ts b/packages/ui-components/src/__tests__/CardProperty.test.ts index 1990193e88..f7760927a6 100644 --- a/packages/ui-components/src/__tests__/CardProperty.test.ts +++ b/packages/ui-components/src/__tests__/CardProperty.test.ts @@ -1,10 +1,10 @@ -import { render, screen } from '@testing-library/svelte'; -import { describe, it, expect } from 'vitest'; -import CardProperty from '../lib/components/CardProperty.svelte'; +import { render, screen } from "@testing-library/svelte"; +import { describe, it, expect } from "vitest"; +import CardProperty from "../lib/components/CardProperty.svelte"; -describe('Page Component', () => { - it('should render the card component', async () => { - render(CardProperty); - expect(screen.getByTestId('card-property-key')).toBeInTheDocument(); - }); +describe("Page Component", () => { + it("should render the card component", async () => { + render(CardProperty); + expect(screen.getByTestId("card-property-key")).toBeInTheDocument(); + }); }); diff --git a/packages/ui-components/src/__tests__/ChartTimeFilters.test.ts b/packages/ui-components/src/__tests__/ChartTimeFilters.test.ts index b3babec7c7..0e08505aed 100644 --- a/packages/ui-components/src/__tests__/ChartTimeFilters.test.ts +++ b/packages/ui-components/src/__tests__/ChartTimeFilters.test.ts @@ -1,67 +1,67 @@ -import { render, fireEvent, screen } from '@testing-library/svelte'; -import { get, writable } from 'svelte/store'; -import { test, expect } from 'vitest'; -import ChartTimeFiltersTest from './ChartTimeFilters.test.svelte'; +import { render, fireEvent, screen } from "@testing-library/svelte"; +import { get, writable } from "svelte/store"; +import { test, expect } from "vitest"; +import ChartTimeFiltersTest from "./ChartTimeFilters.test.svelte"; const TIME_DELTA_24_HOURS = 60 * 60 * 24; const TIME_DELTA_7_DAYS = TIME_DELTA_24_HOURS * 7; const TIME_DELTA_30_DAYS = TIME_DELTA_24_HOURS * 30; const TIME_DELTA_1_YEAR = TIME_DELTA_24_HOURS * 365; -test('initial timeDelta is set to 1 year', async () => { - const timeDeltaStore = writable(TIME_DELTA_1_YEAR); +test("initial timeDelta is set to 1 year", async () => { + const timeDeltaStore = writable(TIME_DELTA_1_YEAR); - render(ChartTimeFiltersTest, { timeDeltaStore }); + render(ChartTimeFiltersTest, { timeDeltaStore }); - const yearButton = screen.getByText('1 Year'); - expect(yearButton).toBeDisabled(); - expect(get(timeDeltaStore)).toBe(TIME_DELTA_1_YEAR); + const yearButton = screen.getByText("1 Year"); + expect(yearButton).toBeDisabled(); + expect(get(timeDeltaStore)).toBe(TIME_DELTA_1_YEAR); }); -test('clicking 30 Days button updates timeDelta', async () => { - const timeDeltaStore = writable(TIME_DELTA_1_YEAR); +test("clicking 30 Days button updates timeDelta", async () => { + const timeDeltaStore = writable(TIME_DELTA_1_YEAR); - render(ChartTimeFiltersTest, { timeDeltaStore }); + render(ChartTimeFiltersTest, { timeDeltaStore }); - const thirtyDaysButton = screen.getByText('30 Days'); - await fireEvent.click(thirtyDaysButton); + const thirtyDaysButton = screen.getByText("30 Days"); + await fireEvent.click(thirtyDaysButton); - expect(thirtyDaysButton).toBeDisabled(); - expect(get(timeDeltaStore)).toBe(TIME_DELTA_30_DAYS); + expect(thirtyDaysButton).toBeDisabled(); + expect(get(timeDeltaStore)).toBe(TIME_DELTA_30_DAYS); }); -test('clicking 7 Days button updates timeDelta', async () => { - const timeDeltaStore = writable(TIME_DELTA_1_YEAR); +test("clicking 7 Days button updates timeDelta", async () => { + const timeDeltaStore = writable(TIME_DELTA_1_YEAR); - render(ChartTimeFiltersTest, { timeDeltaStore }); + render(ChartTimeFiltersTest, { timeDeltaStore }); - const sevenDaysButton = screen.getByText('7 Days'); - await fireEvent.click(sevenDaysButton); + const sevenDaysButton = screen.getByText("7 Days"); + await fireEvent.click(sevenDaysButton); - expect(sevenDaysButton).toBeDisabled(); - expect(get(timeDeltaStore)).toBe(TIME_DELTA_7_DAYS); + expect(sevenDaysButton).toBeDisabled(); + expect(get(timeDeltaStore)).toBe(TIME_DELTA_7_DAYS); }); -test('clicking 24 Hours button updates timeDelta', async () => { - const timeDeltaStore = writable(TIME_DELTA_1_YEAR); +test("clicking 24 Hours button updates timeDelta", async () => { + const timeDeltaStore = writable(TIME_DELTA_1_YEAR); - render(ChartTimeFiltersTest, { timeDeltaStore }); + render(ChartTimeFiltersTest, { timeDeltaStore }); - const twentyFourHoursButton = screen.getByText('24 Hours'); - await fireEvent.click(twentyFourHoursButton); + const twentyFourHoursButton = screen.getByText("24 Hours"); + await fireEvent.click(twentyFourHoursButton); - expect(twentyFourHoursButton).toBeDisabled(); - expect(get(timeDeltaStore)).toBe(TIME_DELTA_24_HOURS); + expect(twentyFourHoursButton).toBeDisabled(); + expect(get(timeDeltaStore)).toBe(TIME_DELTA_24_HOURS); }); -test('clicking 1 Year button updates timeDelta', async () => { - const timeDeltaStore = writable(TIME_DELTA_30_DAYS); +test("clicking 1 Year button updates timeDelta", async () => { + const timeDeltaStore = writable(TIME_DELTA_30_DAYS); - render(ChartTimeFiltersTest, { timeDeltaStore }); + render(ChartTimeFiltersTest, { timeDeltaStore }); - const yearButton = screen.getByText('1 Year'); - await fireEvent.click(yearButton); + const yearButton = screen.getByText("1 Year"); + await fireEvent.click(yearButton); - expect(yearButton).toBeDisabled(); - expect(get(timeDeltaStore)).toBe(TIME_DELTA_1_YEAR); + expect(yearButton).toBeDisabled(); + expect(get(timeDeltaStore)).toBe(TIME_DELTA_1_YEAR); }); diff --git a/packages/ui-components/src/__tests__/Checkbox.test.ts b/packages/ui-components/src/__tests__/Checkbox.test.ts index 8c27d229be..0b7985fa25 100644 --- a/packages/ui-components/src/__tests__/Checkbox.test.ts +++ b/packages/ui-components/src/__tests__/Checkbox.test.ts @@ -1,62 +1,62 @@ -import { render, fireEvent } from '@testing-library/svelte'; -import { describe, it, expect, vi } from 'vitest'; -import Checkbox from '../lib/components/checkbox/Checkbox.svelte'; -import { tick } from 'svelte'; - -describe('Checkbox Component', () => { - it('renders with default props', () => { - const { getByTestId } = render(Checkbox); - expect(getByTestId('checkbox')).toBeTruthy(); - }); - - it('renders with label', () => { - const label = 'Test Label'; - const { getByText } = render(Checkbox, { props: { label } }); - expect(getByText(label)).toBeTruthy(); - }); - - it('initializes with checked state', () => { - const { getByTestId } = render(Checkbox, { props: { checked: true } }); - const checkbox = getByTestId('checkbox') as HTMLInputElement; - expect(checkbox.checked).toBe(true); - }); - - it('handles change event', async () => { - const mockChange = vi.fn(); - const { getByTestId, component } = render(Checkbox); - - component.$on('change', mockChange); - const checkbox = getByTestId('checkbox'); - - await fireEvent.click(checkbox); - expect(mockChange).toHaveBeenCalledTimes(1); - expect(mockChange.mock.calls[0][0].detail).toBe(true); - - await fireEvent.click(checkbox); - expect(mockChange).toHaveBeenCalledTimes(2); - expect(mockChange.mock.calls[1][0].detail).toBe(false); - }); - - it('updates checked state when clicked', async () => { - const { getByTestId } = render(Checkbox); - const checkbox = getByTestId('checkbox') as HTMLInputElement; - - expect(checkbox.checked).toBe(false); - await fireEvent.click(checkbox); - expect(checkbox.checked).toBe(true); - }); - - it('binds to checked prop', async () => { - const checked = false; - const { getByTestId, component } = render(Checkbox, { props: { checked } }); - const checkbox = getByTestId('checkbox') as HTMLInputElement; - - expect(checkbox.checked).toBe(false); - - // Use tick to wait for the next update cycle - component.$set({ checked: true }); - await tick(); - - expect(checkbox.checked).toBe(true); - }); +import { render, fireEvent } from "@testing-library/svelte"; +import { describe, it, expect, vi } from "vitest"; +import Checkbox from "../lib/components/checkbox/Checkbox.svelte"; +import { tick } from "svelte"; + +describe("Checkbox Component", () => { + it("renders with default props", () => { + const { getByTestId } = render(Checkbox); + expect(getByTestId("checkbox")).toBeTruthy(); + }); + + it("renders with label", () => { + const label = "Test Label"; + const { getByText } = render(Checkbox, { props: { label } }); + expect(getByText(label)).toBeTruthy(); + }); + + it("initializes with checked state", () => { + const { getByTestId } = render(Checkbox, { props: { checked: true } }); + const checkbox = getByTestId("checkbox") as HTMLInputElement; + expect(checkbox.checked).toBe(true); + }); + + it("handles change event", async () => { + const mockChange = vi.fn(); + const { getByTestId, component } = render(Checkbox); + + component.$on("change", mockChange); + const checkbox = getByTestId("checkbox"); + + await fireEvent.click(checkbox); + expect(mockChange).toHaveBeenCalledTimes(1); + expect(mockChange.mock.calls[0][0].detail).toBe(true); + + await fireEvent.click(checkbox); + expect(mockChange).toHaveBeenCalledTimes(2); + expect(mockChange.mock.calls[1][0].detail).toBe(false); + }); + + it("updates checked state when clicked", async () => { + const { getByTestId } = render(Checkbox); + const checkbox = getByTestId("checkbox") as HTMLInputElement; + + expect(checkbox.checked).toBe(false); + await fireEvent.click(checkbox); + expect(checkbox.checked).toBe(true); + }); + + it("binds to checked prop", async () => { + const checked = false; + const { getByTestId, component } = render(Checkbox, { props: { checked } }); + const checkbox = getByTestId("checkbox") as HTMLInputElement; + + expect(checkbox.checked).toBe(false); + + // Use tick to wait for the next update cycle + component.$set({ checked: true }); + await tick(); + + expect(checkbox.checked).toBe(true); + }); }); diff --git a/packages/ui-components/src/__tests__/CheckboxInactiveOrdersVault.test.ts b/packages/ui-components/src/__tests__/CheckboxInactiveOrdersVault.test.ts index adf8e162d4..1c2f70de0c 100644 --- a/packages/ui-components/src/__tests__/CheckboxInactiveOrdersVault.test.ts +++ b/packages/ui-components/src/__tests__/CheckboxInactiveOrdersVault.test.ts @@ -1,59 +1,63 @@ -import { render, fireEvent, screen } from '@testing-library/svelte'; -import { get, writable, type Writable } from 'svelte/store'; -import { beforeEach, expect, test, describe } from 'vitest'; -import CheckboxInactiveOrdersVault from '../lib/components/CheckboxInactiveOrdersVault.svelte'; - -describe('CheckboxInactiveOrdersVault', () => { - let hideInactiveOrdersVaults: Writable; - - beforeEach(() => { - hideInactiveOrdersVaults = writable(false); - }); - - test('renders correctly', () => { - render(CheckboxInactiveOrdersVault, { - props: { - hideInactiveOrdersVaults - } - }); - expect(screen.getByText('Hide vaults without active orders')).toBeInTheDocument(); - }); - - test('checkbox defaults to unchecked', () => { - render(CheckboxInactiveOrdersVault, { - props: { - hideInactiveOrdersVaults - } - }); - - const checkbox = screen.getByRole('checkbox'); - expect(checkbox).not.toBeChecked(); - }); - - test('toggles store value when clicked', async () => { - render(CheckboxInactiveOrdersVault, { - props: { - hideInactiveOrdersVaults - } - }); - - const checkbox = screen.getByRole('checkbox'); - expect(get(hideInactiveOrdersVaults)).toBe(false); - - await fireEvent.click(checkbox); - expect(get(hideInactiveOrdersVaults)).toBe(true); - - await fireEvent.click(checkbox); - expect(get(hideInactiveOrdersVaults)).toBe(false); - }); - - test('renders with correct test id', () => { - render(CheckboxInactiveOrdersVault, { - props: { - hideInactiveOrdersVaults - } - }); - - expect(screen.getByTestId('inactive-orders-vault-checkbox')).toBeInTheDocument(); - }); +import { render, fireEvent, screen } from "@testing-library/svelte"; +import { get, writable, type Writable } from "svelte/store"; +import { beforeEach, expect, test, describe } from "vitest"; +import CheckboxInactiveOrdersVault from "../lib/components/CheckboxInactiveOrdersVault.svelte"; + +describe("CheckboxInactiveOrdersVault", () => { + let hideInactiveOrdersVaults: Writable; + + beforeEach(() => { + hideInactiveOrdersVaults = writable(false); + }); + + test("renders correctly", () => { + render(CheckboxInactiveOrdersVault, { + props: { + hideInactiveOrdersVaults, + }, + }); + expect( + screen.getByText("Hide vaults without active orders"), + ).toBeInTheDocument(); + }); + + test("checkbox defaults to unchecked", () => { + render(CheckboxInactiveOrdersVault, { + props: { + hideInactiveOrdersVaults, + }, + }); + + const checkbox = screen.getByRole("checkbox"); + expect(checkbox).not.toBeChecked(); + }); + + test("toggles store value when clicked", async () => { + render(CheckboxInactiveOrdersVault, { + props: { + hideInactiveOrdersVaults, + }, + }); + + const checkbox = screen.getByRole("checkbox"); + expect(get(hideInactiveOrdersVaults)).toBe(false); + + await fireEvent.click(checkbox); + expect(get(hideInactiveOrdersVaults)).toBe(true); + + await fireEvent.click(checkbox); + expect(get(hideInactiveOrdersVaults)).toBe(false); + }); + + test("renders with correct test id", () => { + render(CheckboxInactiveOrdersVault, { + props: { + hideInactiveOrdersVaults, + }, + }); + + expect( + screen.getByTestId("inactive-orders-vault-checkbox"), + ).toBeInTheDocument(); + }); }); diff --git a/packages/ui-components/src/__tests__/CheckboxZeroBalanceVault.test.ts b/packages/ui-components/src/__tests__/CheckboxZeroBalanceVault.test.ts index a273983ac3..a60c9695c3 100644 --- a/packages/ui-components/src/__tests__/CheckboxZeroBalanceVault.test.ts +++ b/packages/ui-components/src/__tests__/CheckboxZeroBalanceVault.test.ts @@ -1,38 +1,38 @@ -import { render, fireEvent, screen } from '@testing-library/svelte'; -import { get, writable, type Writable } from 'svelte/store'; -import { beforeEach, expect, test, describe } from 'vitest'; -import CheckboxZeroBalanceVault from '../lib/components/CheckboxZeroBalanceVault.svelte'; +import { render, fireEvent, screen } from "@testing-library/svelte"; +import { get, writable, type Writable } from "svelte/store"; +import { beforeEach, expect, test, describe } from "vitest"; +import CheckboxZeroBalanceVault from "../lib/components/CheckboxZeroBalanceVault.svelte"; -describe('CheckboxZeroBalanceVault', () => { - let hideZeroBalanceVaults: Writable; +describe("CheckboxZeroBalanceVault", () => { + let hideZeroBalanceVaults: Writable; - beforeEach(() => { - hideZeroBalanceVaults = writable(false); - }); + beforeEach(() => { + hideZeroBalanceVaults = writable(false); + }); - test('renders correctly', () => { - render(CheckboxZeroBalanceVault, { - props: { - hideZeroBalanceVaults - } - }); - expect(screen.getByText('Hide empty vaults')).toBeInTheDocument(); - }); + test("renders correctly", () => { + render(CheckboxZeroBalanceVault, { + props: { + hideZeroBalanceVaults, + }, + }); + expect(screen.getByText("Hide empty vaults")).toBeInTheDocument(); + }); - test('toggles store value when clicked', async () => { - render(CheckboxZeroBalanceVault, { - props: { - hideZeroBalanceVaults - } - }); + test("toggles store value when clicked", async () => { + render(CheckboxZeroBalanceVault, { + props: { + hideZeroBalanceVaults, + }, + }); - const checkbox = screen.getByRole('checkbox'); - expect(get(hideZeroBalanceVaults)).toBe(false); + const checkbox = screen.getByRole("checkbox"); + expect(get(hideZeroBalanceVaults)).toBe(false); - await fireEvent.click(checkbox); - expect(get(hideZeroBalanceVaults)).toBe(true); + await fireEvent.click(checkbox); + expect(get(hideZeroBalanceVaults)).toBe(true); - await fireEvent.click(checkbox); - expect(get(hideZeroBalanceVaults)).toBe(false); - }); + await fireEvent.click(checkbox); + expect(get(hideZeroBalanceVaults)).toBe(false); + }); }); diff --git a/packages/ui-components/src/__tests__/CodeMirrorDotrain.test.ts b/packages/ui-components/src/__tests__/CodeMirrorDotrain.test.ts index 8810d24606..c250099cad 100644 --- a/packages/ui-components/src/__tests__/CodeMirrorDotrain.test.ts +++ b/packages/ui-components/src/__tests__/CodeMirrorDotrain.test.ts @@ -1,99 +1,100 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import { render, waitFor } from '@testing-library/svelte'; -import { CodeMirrorDotrain } from '@rainlanguage/ui-components'; -import { RawRainlangExtension } from 'codemirror-rainlang'; // Direct import -import { writable } from 'svelte/store'; +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { render, waitFor } from "@testing-library/svelte"; +import { CodeMirrorDotrain } from "@rainlanguage/ui-components"; +import { RawRainlangExtension } from "codemirror-rainlang"; // Direct import +import { writable } from "svelte/store"; -vi.mock('codemirror-rainlang', () => ({ - RawRainlangExtension: vi.fn(() => ({ - plugin: vi.fn(), - hover: vi.fn(), - completion: vi.fn(), - language: vi.fn(), - diagnostics: vi.fn() - })) +vi.mock("codemirror-rainlang", () => ({ + RawRainlangExtension: vi.fn(() => ({ + plugin: vi.fn(), + hover: vi.fn(), + completion: vi.fn(), + language: vi.fn(), + diagnostics: vi.fn(), + })), })); -vi.mock('@codemirror/lint', () => ({ - openLintPanel: vi.fn() +vi.mock("@codemirror/lint", () => ({ + openLintPanel: vi.fn(), })); -vi.mock('svelte-codemirror-editor', async () => { - const mockCodeMirror = (await import('../lib/__mocks__/MockComponent.svelte')).default; - return { default: mockCodeMirror }; +vi.mock("svelte-codemirror-editor", async () => { + const mockCodeMirror = (await import("../lib/__mocks__/MockComponent.svelte")) + .default; + return { default: mockCodeMirror }; }); -describe('CodeMirrorDotrain', () => { - beforeEach(() => { - vi.clearAllMocks(); - }); +describe("CodeMirrorDotrain", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); - it('should render codemirror-dotrain', async () => { - const testValue = 'initial dotrain value'; - const rainlangExtensionMock = new RawRainlangExtension({ - hover: async () => null, - completion: async () => null, - diagnostics: async () => [] - }); + it("should render codemirror-dotrain", async () => { + const testValue = "initial dotrain value"; + const rainlangExtensionMock = new RawRainlangExtension({ + hover: async () => null, + completion: async () => null, + diagnostics: async () => [], + }); - const screen = render(CodeMirrorDotrain, { - props: { - rainlangText: testValue, - disabled: false, - styles: {}, - rainlangExtension: rainlangExtensionMock, - codeMirrorTheme: writable({}), - onTextChange: vi.fn() - } - }); - await waitFor(() => { - expect(screen.getByTestId('codemirror-dotrain')).toBeInTheDocument(); - }); - }); + const screen = render(CodeMirrorDotrain, { + props: { + rainlangText: testValue, + disabled: false, + styles: {}, + rainlangExtension: rainlangExtensionMock, + codeMirrorTheme: writable({}), + onTextChange: vi.fn(), + }, + }); + await waitFor(() => { + expect(screen.getByTestId("codemirror-dotrain")).toBeInTheDocument(); + }); + }); - it('should render codemirror-dotrain component with correct initial value', async () => { - const testValue = 'initial dotrain value'; - const rainlangExtensionMock = new RawRainlangExtension({ - hover: async () => null, - completion: async () => null, - diagnostics: async () => [] - }); + it("should render codemirror-dotrain component with correct initial value", async () => { + const testValue = "initial dotrain value"; + const rainlangExtensionMock = new RawRainlangExtension({ + hover: async () => null, + completion: async () => null, + diagnostics: async () => [], + }); - const screen = render(CodeMirrorDotrain, { - props: { - rainlangText: testValue, - disabled: false, - styles: {}, - rainlangExtension: rainlangExtensionMock, - codeMirrorTheme: writable({}), - onTextChange: vi.fn() - } - }); - expect(screen.component.$$.ctx[0]).toBe(testValue); - }); + const screen = render(CodeMirrorDotrain, { + props: { + rainlangText: testValue, + disabled: false, + styles: {}, + rainlangExtension: rainlangExtensionMock, + codeMirrorTheme: writable({}), + onTextChange: vi.fn(), + }, + }); + expect(screen.component.$$.ctx[0]).toBe(testValue); + }); - it('should call onTextChange when the text changes', async () => { - const testValue = 'initial dotrain value'; - const rainlangExtensionMock = new RawRainlangExtension({ - hover: async () => null, - completion: async () => null, - diagnostics: async () => [] - }); - const onTextChangeMock = vi.fn(); + it("should call onTextChange when the text changes", async () => { + const testValue = "initial dotrain value"; + const rainlangExtensionMock = new RawRainlangExtension({ + hover: async () => null, + completion: async () => null, + diagnostics: async () => [], + }); + const onTextChangeMock = vi.fn(); - const { component } = render(CodeMirrorDotrain, { - props: { - rainlangText: testValue, - disabled: false, - styles: {}, - rainlangExtension: rainlangExtensionMock, - codeMirrorTheme: writable({}), - onTextChange: onTextChangeMock - } - }); + const { component } = render(CodeMirrorDotrain, { + props: { + rainlangText: testValue, + disabled: false, + styles: {}, + rainlangExtension: rainlangExtensionMock, + codeMirrorTheme: writable({}), + onTextChange: onTextChangeMock, + }, + }); - component.$$.ctx[component.$$.props.onTextChange]('value'); + component.$$.ctx[component.$$.props.onTextChange]("value"); - expect(onTextChangeMock).toHaveBeenCalledWith('value'); - }); + expect(onTextChangeMock).toHaveBeenCalledWith("value"); + }); }); diff --git a/packages/ui-components/src/__tests__/CodeMirrorRainlang.test.ts b/packages/ui-components/src/__tests__/CodeMirrorRainlang.test.ts index 4b87b107d5..6fafa76dc0 100644 --- a/packages/ui-components/src/__tests__/CodeMirrorRainlang.test.ts +++ b/packages/ui-components/src/__tests__/CodeMirrorRainlang.test.ts @@ -1,79 +1,80 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import { render, waitFor } from '@testing-library/svelte'; -import CodeMirrorRainlang from '../lib/components/CodeMirrorRainlang.svelte'; -import type { RaindexOrder } from '@rainlanguage/raindex'; -import { writable } from 'svelte/store'; +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { render, waitFor } from "@testing-library/svelte"; +import CodeMirrorRainlang from "../lib/components/CodeMirrorRainlang.svelte"; +import type { RaindexOrder } from "@rainlanguage/raindex"; +import { writable } from "svelte/store"; -vi.mock('codemirror-rainlang', () => ({ - RainlangLR: vi.fn() +vi.mock("codemirror-rainlang", () => ({ + RainlangLR: vi.fn(), })); -vi.mock('svelte-codemirror-editor', async () => { - const mockCodeMirror = (await import('../lib/__mocks__/MockComponent.svelte')).default; - return { default: mockCodeMirror }; +vi.mock("svelte-codemirror-editor", async () => { + const mockCodeMirror = (await import("../lib/__mocks__/MockComponent.svelte")) + .default; + return { default: mockCodeMirror }; }); -describe('CodeMirrorRainlang', () => { - beforeEach(() => { - vi.clearAllMocks(); - }); +describe("CodeMirrorRainlang", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); - it('should use order.rainlang when order prop is provided', async () => { - const mockOrder: RaindexOrder = { - rainlang: 'mocked rainlang text' - } as RaindexOrder; + it("should use order.rainlang when order prop is provided", async () => { + const mockOrder: RaindexOrder = { + rainlang: "mocked rainlang text", + } as RaindexOrder; - const screen = render(CodeMirrorRainlang, { - props: { - order: mockOrder, - codeMirrorTheme: writable({}), - codeMirrorDisabled: false, - codeMirrorStyles: {} - } - }); + const screen = render(CodeMirrorRainlang, { + props: { + order: mockOrder, + codeMirrorTheme: writable({}), + codeMirrorDisabled: false, + codeMirrorStyles: {}, + }, + }); - await waitFor(() => { - const mockComponent = screen.getByTestId('mock-component'); - expect(mockComponent).toHaveAttribute('value', 'mocked rainlang text'); - }); - }); + await waitFor(() => { + const mockComponent = screen.getByTestId("mock-component"); + expect(mockComponent).toHaveAttribute("value", "mocked rainlang text"); + }); + }); - it('should use rainlangText when no order is provided', async () => { - const testText = 'test rainlang text'; + it("should use rainlangText when no order is provided", async () => { + const testText = "test rainlang text"; - const screen = render(CodeMirrorRainlang, { - props: { - order: undefined, - rainlangText: testText, - codeMirrorTheme: writable({}), - codeMirrorDisabled: false, - codeMirrorStyles: {} - } - }); + const screen = render(CodeMirrorRainlang, { + props: { + order: undefined, + rainlangText: testText, + codeMirrorTheme: writable({}), + codeMirrorDisabled: false, + codeMirrorStyles: {}, + }, + }); - await waitFor(() => { - const mockComponent = screen.getByTestId('mock-component'); - expect(mockComponent).toHaveAttribute('value', 'test rainlang text'); - }); - }); + await waitFor(() => { + const mockComponent = screen.getByTestId("mock-component"); + expect(mockComponent).toHaveAttribute("value", "test rainlang text"); + }); + }); - it('should pass through disabled prop', async () => { - const mockOrder: RaindexOrder = { - rainlang: 'mocked rainlang text' - } as RaindexOrder; + it("should pass through disabled prop", async () => { + const mockOrder: RaindexOrder = { + rainlang: "mocked rainlang text", + } as RaindexOrder; - const screen = render(CodeMirrorRainlang, { - props: { - order: mockOrder, - codeMirrorTheme: writable({}), - codeMirrorDisabled: false, - codeMirrorStyles: {} - } - }); + const screen = render(CodeMirrorRainlang, { + props: { + order: mockOrder, + codeMirrorTheme: writable({}), + codeMirrorDisabled: false, + codeMirrorStyles: {}, + }, + }); - await waitFor(() => { - const mockComponent = screen.getByTestId('mock-component'); - expect(mockComponent).toHaveAttribute('readonly', 'false'); - }); - }); + await waitFor(() => { + const mockComponent = screen.getByTestId("mock-component"); + expect(mockComponent).toHaveAttribute("readonly", "false"); + }); + }); }); diff --git a/packages/ui-components/src/__tests__/ComposedRainlangModal.test.ts b/packages/ui-components/src/__tests__/ComposedRainlangModal.test.ts index dcfba67761..4dde04e6ef 100644 --- a/packages/ui-components/src/__tests__/ComposedRainlangModal.test.ts +++ b/packages/ui-components/src/__tests__/ComposedRainlangModal.test.ts @@ -1,37 +1,38 @@ -import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; -import { render, fireEvent, waitFor } from '@testing-library/svelte'; -import ComposedRainlangModal from '../lib/components/deployment/ComposedRainlangModal.svelte'; -import type { RaindexOrderBuilder } from '@rainlanguage/raindex'; -import { useRaindexOrderBuilder } from '$lib/hooks/useRaindexOrderBuilder'; +import { describe, it, expect, vi, beforeEach, type Mock } from "vitest"; +import { render, fireEvent, waitFor } from "@testing-library/svelte"; +import ComposedRainlangModal from "../lib/components/deployment/ComposedRainlangModal.svelte"; +import type { RaindexOrderBuilder } from "@rainlanguage/raindex"; +import { useRaindexOrderBuilder } from "$lib/hooks/useRaindexOrderBuilder"; -vi.mock('svelte-codemirror-editor', async () => { - const mockCodeMirror = (await import('../lib/__mocks__/MockComponent.svelte')).default; - return { default: mockCodeMirror }; +vi.mock("svelte-codemirror-editor", async () => { + const mockCodeMirror = (await import("../lib/__mocks__/MockComponent.svelte")) + .default; + return { default: mockCodeMirror }; }); -vi.mock('$lib/hooks/useRaindexOrderBuilder', () => ({ - useRaindexOrderBuilder: vi.fn() +vi.mock("$lib/hooks/useRaindexOrderBuilder", () => ({ + useRaindexOrderBuilder: vi.fn(), })); const mockBuilder = { - getComposedRainlang: vi.fn(() => Promise.resolve('mocked rainlang text')) + getComposedRainlang: vi.fn(() => Promise.resolve("mocked rainlang text")), } as unknown as RaindexOrderBuilder; -describe('ComposedRainlangModal', () => { - beforeEach(() => { - vi.clearAllMocks(); - (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilder); - }); +describe("ComposedRainlangModal", () => { + beforeEach(() => { + vi.clearAllMocks(); + (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilder); + }); - it('should open modal and display rainlang text when button is clicked', async () => { - const { getByText, getByTestId } = render(ComposedRainlangModal); + it("should open modal and display rainlang text when button is clicked", async () => { + const { getByText, getByTestId } = render(ComposedRainlangModal); - const button = getByText('Show Rainlang'); - await fireEvent.click(button); + const button = getByText("Show Rainlang"); + await fireEvent.click(button); - await waitFor(() => { - expect(mockBuilder.getComposedRainlang).toHaveBeenCalled(); - expect(getByTestId('modal')).toBeInTheDocument(); - }); - }); + await waitFor(() => { + expect(mockBuilder.getComposedRainlang).toHaveBeenCalled(); + expect(getByTestId("modal")).toBeInTheDocument(); + }); + }); }); diff --git a/packages/ui-components/src/__tests__/DeploymentSectionHeader.test.ts b/packages/ui-components/src/__tests__/DeploymentSectionHeader.test.ts index a07a758ee7..985b089e7d 100644 --- a/packages/ui-components/src/__tests__/DeploymentSectionHeader.test.ts +++ b/packages/ui-components/src/__tests__/DeploymentSectionHeader.test.ts @@ -1,46 +1,48 @@ -import { render, screen } from '@testing-library/svelte'; -import { describe, it, expect } from 'vitest'; -import DeploymentSectionHeader from '../lib/components/deployment/DeploymentSectionHeader.svelte'; -import type { ComponentProps } from 'svelte'; - -export type DeploymentSectionHeaderComponentProps = ComponentProps; - -describe('DeploymentSectionHeader', () => { - const defaultProps: DeploymentSectionHeaderComponentProps = { - title: 'Test Title', - description: 'Test Description' - }; - - it('renders title and description', () => { - render(DeploymentSectionHeader, defaultProps); - - expect(screen.getByText('Test Title')).toBeInTheDocument(); - expect(screen.getByText('Test Description')).toBeInTheDocument(); - }); - - it('renders title only', () => { - render(DeploymentSectionHeader, { title: 'Test Title' }); - - expect(screen.getByText('Test Title')).toBeInTheDocument(); - expect(screen.queryByText('Test Description')).not.toBeInTheDocument(); - }); - - it('renders description with markdown', () => { - render(DeploymentSectionHeader, { - title: 'Test Title', - description: '**Bold** and *italic* text\n\n[Link](https://www.example.com)' - }); - - const boldElement = screen.getByText('Bold'); - expect(boldElement).toBeInTheDocument(); - expect(boldElement.tagName).toBe('STRONG'); - - const italicElement = screen.getByText('italic'); - expect(italicElement).toBeInTheDocument(); - expect(italicElement.tagName).toBe('EM'); - - const linkElement = screen.getByRole('link', { name: /Link/i }); - expect(linkElement).toBeInTheDocument(); - expect(linkElement).toHaveAttribute('href', 'https://www.example.com'); - }); +import { render, screen } from "@testing-library/svelte"; +import { describe, it, expect } from "vitest"; +import DeploymentSectionHeader from "../lib/components/deployment/DeploymentSectionHeader.svelte"; +import type { ComponentProps } from "svelte"; + +export type DeploymentSectionHeaderComponentProps = + ComponentProps; + +describe("DeploymentSectionHeader", () => { + const defaultProps: DeploymentSectionHeaderComponentProps = { + title: "Test Title", + description: "Test Description", + }; + + it("renders title and description", () => { + render(DeploymentSectionHeader, defaultProps); + + expect(screen.getByText("Test Title")).toBeInTheDocument(); + expect(screen.getByText("Test Description")).toBeInTheDocument(); + }); + + it("renders title only", () => { + render(DeploymentSectionHeader, { title: "Test Title" }); + + expect(screen.getByText("Test Title")).toBeInTheDocument(); + expect(screen.queryByText("Test Description")).not.toBeInTheDocument(); + }); + + it("renders description with markdown", () => { + render(DeploymentSectionHeader, { + title: "Test Title", + description: + "**Bold** and *italic* text\n\n[Link](https://www.example.com)", + }); + + const boldElement = screen.getByText("Bold"); + expect(boldElement).toBeInTheDocument(); + expect(boldElement.tagName).toBe("STRONG"); + + const italicElement = screen.getByText("italic"); + expect(italicElement).toBeInTheDocument(); + expect(italicElement.tagName).toBe("EM"); + + const linkElement = screen.getByRole("link", { name: /Link/i }); + expect(linkElement).toBeInTheDocument(); + expect(linkElement).toHaveAttribute("href", "https://www.example.com"); + }); }); diff --git a/packages/ui-components/src/__tests__/DeploymentSteps.test.ts b/packages/ui-components/src/__tests__/DeploymentSteps.test.ts index 71407967c0..711878cdb4 100644 --- a/packages/ui-components/src/__tests__/DeploymentSteps.test.ts +++ b/packages/ui-components/src/__tests__/DeploymentSteps.test.ts @@ -1,504 +1,519 @@ -import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; -import { render, screen, waitFor } from '@testing-library/svelte'; -import DeploymentSteps from '../lib/components/deployment/DeploymentSteps.svelte'; -import { RaindexOrderBuilder, type ScenarioCfg } from '@rainlanguage/raindex'; -import type { ComponentProps } from 'svelte'; -import { readable, writable } from 'svelte/store'; -import type { AppKit } from '@reown/appkit'; -import type { OrderBuilderDeploymentCfg, RaindexClient } from '@rainlanguage/raindex'; -import userEvent from '@testing-library/user-event'; -import { useRaindexOrderBuilder } from '$lib/hooks/useRaindexOrderBuilder'; -import { useAccount } from '$lib/providers/wallet/useAccount'; -import type { Account } from '$lib/types/account'; -import { useRaindexClient } from '$lib/hooks/useRaindexClient'; - -vi.mock('@rainlanguage/raindex', () => ({ - RaindexOrderBuilder: vi.fn() +import { describe, it, expect, vi, beforeEach, type Mock } from "vitest"; +import { render, screen, waitFor } from "@testing-library/svelte"; +import DeploymentSteps from "../lib/components/deployment/DeploymentSteps.svelte"; +import { RaindexOrderBuilder, type ScenarioCfg } from "@rainlanguage/raindex"; +import type { ComponentProps } from "svelte"; +import { readable, writable } from "svelte/store"; +import type { AppKit } from "@reown/appkit"; +import type { + OrderBuilderDeploymentCfg, + RaindexClient, +} from "@rainlanguage/raindex"; +import userEvent from "@testing-library/user-event"; +import { useRaindexOrderBuilder } from "$lib/hooks/useRaindexOrderBuilder"; +import { useAccount } from "$lib/providers/wallet/useAccount"; +import type { Account } from "$lib/types/account"; +import { useRaindexClient } from "$lib/hooks/useRaindexClient"; + +vi.mock("@rainlanguage/raindex", () => ({ + RaindexOrderBuilder: vi.fn(), })); -const { mockConnectedStore } = await vi.hoisted(() => import('../lib/__mocks__/stores')); +const { mockConnectedStore } = await vi.hoisted( + () => import("../lib/__mocks__/stores"), +); -vi.mock('$lib/hooks/useRaindexOrderBuilder', () => ({ - useRaindexOrderBuilder: vi.fn() +vi.mock("$lib/hooks/useRaindexOrderBuilder", () => ({ + useRaindexOrderBuilder: vi.fn(), })); -vi.mock('$lib/hooks/useRaindexClient', () => ({ - useRaindexClient: vi.fn() +vi.mock("$lib/hooks/useRaindexClient", () => ({ + useRaindexClient: vi.fn(), })); -vi.mock('$lib/providers/wallet/useAccount', () => ({ - useAccount: vi.fn() +vi.mock("$lib/providers/wallet/useAccount", () => ({ + useAccount: vi.fn(), })); type DeploymentStepsProps = ComponentProps; const mockDeployment = { - key: 'flare-sflr-wflr', - name: 'SFLR<>WFLR on Flare', - description: 'Rotate sFLR (Sceptre staked FLR) and WFLR on Flare.', - deposits: [], - fields: [], - select_tokens: [], - deployment: { - key: 'flare-sflr-wflr', - scenario: { - key: 'flare', - bindings: {} - } as ScenarioCfg, - order: { - key: 'flare-sflr-wflr', - network: { - key: 'flare', - 'chain-id': 14, - 'network-id': 14, - rpc: 'https://rpc.ankr.com/flare', - label: 'Flare', - currency: 'FLR' - }, - rainlang: { - key: 'flare', - bindings: {} - } as ScenarioCfg, - order: { - key: 'flare-sflr-wflr', - network: { - key: 'flare', - 'chain-id': 14, - 'network-id': 14, - rpc: 'https://rpc.ankr.com/flare', - label: 'Flare', - currency: 'FLR' - }, - address: '0x0' - }, - raindex: { - id: 'flare', - address: '0x0' - }, - inputs: [], - outputs: [] - } - } + key: "flare-sflr-wflr", + name: "SFLR<>WFLR on Flare", + description: "Rotate sFLR (Sceptre staked FLR) and WFLR on Flare.", + deposits: [], + fields: [], + select_tokens: [], + deployment: { + key: "flare-sflr-wflr", + scenario: { + key: "flare", + bindings: {}, + } as ScenarioCfg, + order: { + key: "flare-sflr-wflr", + network: { + key: "flare", + "chain-id": 14, + "network-id": 14, + rpc: "https://rpc.ankr.com/flare", + label: "Flare", + currency: "FLR", + }, + rainlang: { + key: "flare", + bindings: {}, + } as ScenarioCfg, + order: { + key: "flare-sflr-wflr", + network: { + key: "flare", + "chain-id": 14, + "network-id": 14, + rpc: "https://rpc.ankr.com/flare", + label: "Flare", + currency: "FLR", + }, + address: "0x0", + }, + raindex: { + id: "flare", + address: "0x0", + }, + inputs: [], + outputs: [], + }, + }, } as unknown as OrderBuilderDeploymentCfg; const mockOnDeploy = vi.fn(); const defaultProps: DeploymentStepsProps = { - orderDetail: { - name: 'SFLR<>WFLR on Flare', - description: 'Rotate sFLR (Sceptre staked FLR) and WFLR on Flare.', - short_description: 'Rotate sFLR (Sceptre staked FLR) and WFLR on Flare.' - }, - deployment: mockDeployment, - wagmiConnected: mockConnectedStore, - appKitModal: writable({} as AppKit), - onDeploy: mockOnDeploy, - account: readable('0x123') + orderDetail: { + name: "SFLR<>WFLR on Flare", + description: "Rotate sFLR (Sceptre staked FLR) and WFLR on Flare.", + short_description: "Rotate sFLR (Sceptre staked FLR) and WFLR on Flare.", + }, + deployment: mockDeployment, + wagmiConnected: mockConnectedStore, + appKitModal: writable({} as AppKit), + onDeploy: mockOnDeploy, + account: readable("0x123"), } as DeploymentStepsProps; -describe('DeploymentSteps', () => { - let builderInstance: RaindexOrderBuilder; - let mockBuilder: RaindexOrderBuilder; - - beforeEach(() => { - vi.clearAllMocks(); - - // Create a mock instance with all the methods - builderInstance = { - areAllTokensSelected: vi.fn().mockReturnValue({ value: false }), - getSelectTokens: vi.fn().mockReturnValue({ value: [] }), - getCurrentDeployment: vi.fn().mockReturnValue(mockDeployment), - getAllFieldDefinitions: vi.fn().mockReturnValue({ value: [] }), - hasAnyDeposit: vi.fn().mockReturnValue({ value: false }), - hasAnyVaultId: vi.fn().mockReturnValue(false), - getAllTokenInfos: vi.fn().mockResolvedValue({ value: [] }), - getAllTokens: vi.fn().mockResolvedValue({ - value: [ - { - key: 'token1', - address: '0x1234567890123456789012345678901234567890', - name: 'Test Token 1', - symbol: 'TEST1', - decimals: 18 - }, - { - key: 'token2', - address: '0x0987654321098765432109876543210987654321', - name: 'Another Token', - symbol: 'ANOTHER', - decimals: 6 - } - ] - }), - getCurrentDeploymentDetails: vi.fn().mockReturnValue({ - value: { - name: 'Test Deployment', - description: 'This is a test deployment description' - } - }), - getTokenInfo: vi.fn().mockResolvedValue({ - value: { - name: 'Test Token', - symbol: 'TEST', - address: '0x123', - decimals: 18 - } - }), - isSelectTokenSet: vi.fn().mockReturnValue({ value: false }), - setSelectToken: vi.fn(), - unsetSelectToken: vi.fn(), - getDeploymentTransactionArgs: vi.fn(), - getAccountBalance: vi.fn().mockResolvedValue({ - value: '1000000000000000000' - }) - } as unknown as RaindexOrderBuilder; - - mockBuilder = builderInstance; - vi.mocked(useRaindexOrderBuilder).mockReturnValue(mockBuilder); - - // Set default mock return value for useAccount - vi.mocked(useAccount).mockReturnValue({ - account: writable(null), - matchesAccount: vi.fn() - }); - }); - - it('shows deployment details when provided', async () => { - render(DeploymentSteps, { props: defaultProps }); - - await waitFor(() => { - expect(screen.getByText('SFLR<>WFLR on Flare')).toBeInTheDocument(); - }); - }); - - it('shows select tokens section when tokens need to be selected', async () => { - (mockBuilder.getSelectTokens as Mock).mockReturnValue({ - value: ['token1', 'token2'] - }); - - render(DeploymentSteps, { - props: defaultProps - }); - - await waitFor(() => { - expect(screen.getByText('Select Tokens')).toBeInTheDocument(); - expect( - screen.getByText('Select the tokens that you want to use in your order.') - ).toBeInTheDocument(); - }); - }); - - it('shows wallet connect button when all required fields are filled, but no account exists', async () => { - const mockSelectTokens = [ - { key: 'token1', name: 'Token 1', description: undefined }, - { key: 'token2', name: 'Token 2', description: undefined } - ]; - - // Set up specific mocks for this test - (mockBuilder.getSelectTokens as Mock).mockReturnValue({ - value: mockSelectTokens - }); - (mockBuilder.getTokenInfo as Mock).mockImplementation(() => {}); - (mockBuilder.areAllTokensSelected as Mock).mockReturnValue({ value: true }); - (mockBuilder.isSelectTokenSet as Mock).mockReturnValue({ value: false }); - (mockBuilder.setSelectToken as Mock).mockImplementation(() => {}); - (mockBuilder.getCurrentDeployment as Mock).mockReturnValue({ - value: { - deployment: { - order: { - inputs: [], - outputs: [] - } - }, - deposits: [] - } - }); - - (mockBuilder.getAllTokenInfos as Mock).mockResolvedValue({ - value: [ - { - address: '0x1', - decimals: 18, - name: 'Token 1', - symbol: 'TKN1' - }, - { - address: '0x2', - decimals: 18, - name: 'Token 2', - symbol: 'TKN2' - } - ] - }); - - render(DeploymentSteps, { props: { ...defaultProps, account: readable(null) } }); - - await waitFor(() => { - expect(screen.getByText('Connect')).toBeInTheDocument(); - }); - }); - - it('shows deploy button when all required fields are filled, and account is connected', async () => { - const mockSelectTokens = [ - { key: 'token1', name: 'Token 1', description: undefined }, - { key: 'token2', name: 'Token 2', description: undefined } - ]; - - // Set up specific mocks for this test - (mockBuilder.getSelectTokens as Mock).mockReturnValue({ - value: mockSelectTokens - }); - (mockBuilder.getTokenInfo as Mock).mockImplementation(() => {}); - (mockBuilder.areAllTokensSelected as Mock).mockReturnValue({ value: true }); - (mockBuilder.isSelectTokenSet as Mock).mockReturnValue({ value: false }); - (mockBuilder.setSelectToken as Mock).mockImplementation(() => {}); - (mockBuilder.getCurrentDeployment as Mock).mockReturnValue({ - value: { - deployment: { - order: { - inputs: [], - outputs: [] - } - }, - deposits: [] - } - }); - - (mockBuilder.getAllTokenInfos as Mock).mockResolvedValue({ - value: [ - { - address: '0x1', - decimals: 18, - name: 'Token 1', - symbol: 'TKN1' - }, - { - address: '0x2', - decimals: 18, - name: 'Token 2', - symbol: 'TKN2' - } - ] - }); - - render(DeploymentSteps, { props: defaultProps }); - - await waitFor(() => { - expect(screen.getByText('Deploy Order')).toBeInTheDocument(); - }); - }); - it('refreshes field descriptions when tokens change', async () => { - const mockSelectTokens = [ - { key: 'token1', name: 'Token 1', description: undefined }, - { key: 'token2', name: 'Token 2', description: undefined } - ]; - - // Set up specific mocks for this test - (mockBuilder.getSelectTokens as Mock).mockReturnValue({ - value: mockSelectTokens - }); - (mockBuilder.getTokenInfo as Mock).mockImplementation(() => {}); - (mockBuilder.areAllTokensSelected as Mock).mockReturnValue({ value: true }); - (mockBuilder.isSelectTokenSet as Mock).mockReturnValue({ value: false }); - (mockBuilder.setSelectToken as Mock).mockImplementation(() => {}); - (mockBuilder.getCurrentDeployment as Mock).mockReturnValue({ - value: { - deployment: { - order: { - inputs: [], - outputs: [] - } - }, - deposits: [] - } - }); - - (mockBuilder.getAllTokenInfos as Mock).mockResolvedValue({ - value: [ - { - address: '0x1', - decimals: 18, - name: 'Token 1', - symbol: 'TKN1' - }, - { - address: '0x2', - decimals: 18, - name: 'Token 2', - symbol: 'TKN2' - } - ] - }); - - const user = userEvent.setup(); - - render(DeploymentSteps, { - props: defaultProps - }); - - await waitFor(() => { - expect(mockBuilder.areAllTokensSelected).toHaveBeenCalled(); - }); - - await waitFor(() => { - expect(screen.getByText('Select Tokens')).toBeInTheDocument(); - expect(screen.getByText('Token 1')).toBeInTheDocument(); - expect(screen.getByText('Token 2')).toBeInTheDocument(); - }); - - const selectTokenInput = screen.getByText('Token 1'); - (mockBuilder.getTokenInfo as Mock).mockResolvedValue({ - value: { - address: '0x1', - decimals: 18, - name: 'Token 1', - symbol: 'TKN1' - } - }); - await user.type(selectTokenInput, '0x1'); - - const selectTokenOutput = screen.getByText('Token 2'); - (mockBuilder.getTokenInfo as Mock).mockResolvedValue({ - value: { - address: '0x2', - decimals: 18, - name: 'Token 2', - symbol: 'TKN2' - } - }); - await user.type(selectTokenOutput, '0x2'); - - await waitFor(() => { - expect(mockBuilder.getAllTokenInfos).toHaveBeenCalled(); - }); - - const customAddressButtons = screen.getAllByTestId('custom-mode-button'); - await user.click(customAddressButtons[customAddressButtons.length - 1]); - const customInputs = screen.getAllByPlaceholderText('Enter token address (0x...)'); - const lastCustomInput = customInputs[customInputs.length - 1]; - (mockBuilder.getTokenInfo as Mock).mockResolvedValue({ - value: { - address: '0x3', - decimals: 18, - name: 'Token 3', - symbol: 'TKN3' - } - }); - await user.type(lastCustomInput, '0x3'); - - (mockBuilder.getAllTokenInfos as Mock).mockResolvedValue({ - value: [ - { - address: '0x3', - decimals: 18, - name: 'Token 3', - symbol: 'TKN3' - }, - { - address: '0x2', - decimals: 18, - name: 'Token 2', - symbol: 'TKN2' - } - ] - }); - - await waitFor(() => { - expect(mockBuilder.getAllTokenInfos).toHaveBeenCalled(); - }); - }); - - it('passes correct arguments to onDeploy prop', async () => { - // Override the mock for this test - builderInstance.areAllTokensSelected = vi.fn().mockReturnValue({ value: true }); - vi.mocked(useRaindexOrderBuilder).mockReturnValue(builderInstance); - - const mockRaindexClient = {} as unknown as RaindexClient; - vi.mocked(useRaindexClient).mockReturnValue(mockRaindexClient); - - const propsWithMockHandlers = { - ...defaultProps, - account: readable('0xTestAccount') as Account - }; - - const user = userEvent.setup(); - render(DeploymentSteps, { props: propsWithMockHandlers }); - - const deployButton = screen.getByText('Deploy Order'); - await user.click(deployButton); - - await waitFor(() => { - expect(mockOnDeploy).toHaveBeenCalledTimes(1); - - const [raindexClient, builderArg] = mockOnDeploy.mock.calls[0]; - - expect(builderArg).toBe(mockBuilder); - expect(raindexClient).toBe(mockRaindexClient); - }); - }); - - it('calls getTokenInfoAndFetchBalance for each selected token on account change', async () => { - const mockSelectTokens = [ - { key: 'token1', name: 'Token 1', description: undefined }, - { key: 'token2', name: 'Token 2', description: undefined } - ]; - - (mockBuilder.getSelectTokens as Mock).mockReturnValue({ - value: mockSelectTokens - }); - - const accountStore = writable<`0x${string}` | null>('0x123'); - - const propsWithAccountStore = { - ...defaultProps, - account: accountStore - }; - - render(DeploymentSteps, { props: propsWithAccountStore }); - - await waitFor(() => { - expect(mockBuilder.getSelectTokens).toHaveBeenCalled(); - }); - vi.clearAllMocks(); - - accountStore.set('0x456'); - - await waitFor(() => { - expect(mockBuilder.getTokenInfo).toHaveBeenCalledTimes(2); - expect(mockBuilder.getTokenInfo).toHaveBeenCalledWith('token1'); - expect(mockBuilder.getTokenInfo).toHaveBeenCalledWith('token2'); - }); - await waitFor(() => { - expect(mockBuilder.getAccountBalance).toHaveBeenCalledTimes(2); - }); - }); - - it('clears token balances when account becomes null', async () => { - const mockSelectTokens = [{ key: 'token1', name: 'Token 1', description: undefined }]; - - (mockBuilder.getSelectTokens as Mock).mockReturnValue({ - value: mockSelectTokens - }); - - const accountStore = writable<`0x${string}` | null>('0x123'); - - const propsWithAccountStore = { - ...defaultProps, - account: accountStore - }; - - render(DeploymentSteps, { props: propsWithAccountStore }); - - await waitFor(() => { - expect(mockBuilder.getSelectTokens).toHaveBeenCalled(); - }); - - vi.clearAllMocks(); +describe("DeploymentSteps", () => { + let builderInstance: RaindexOrderBuilder; + let mockBuilder: RaindexOrderBuilder; + + beforeEach(() => { + vi.clearAllMocks(); + + // Create a mock instance with all the methods + builderInstance = { + areAllTokensSelected: vi.fn().mockReturnValue({ value: false }), + getSelectTokens: vi.fn().mockReturnValue({ value: [] }), + getCurrentDeployment: vi.fn().mockReturnValue(mockDeployment), + getAllFieldDefinitions: vi.fn().mockReturnValue({ value: [] }), + hasAnyDeposit: vi.fn().mockReturnValue({ value: false }), + hasAnyVaultId: vi.fn().mockReturnValue(false), + getAllTokenInfos: vi.fn().mockResolvedValue({ value: [] }), + getAllTokens: vi.fn().mockResolvedValue({ + value: [ + { + key: "token1", + address: "0x1234567890123456789012345678901234567890", + name: "Test Token 1", + symbol: "TEST1", + decimals: 18, + }, + { + key: "token2", + address: "0x0987654321098765432109876543210987654321", + name: "Another Token", + symbol: "ANOTHER", + decimals: 6, + }, + ], + }), + getCurrentDeploymentDetails: vi.fn().mockReturnValue({ + value: { + name: "Test Deployment", + description: "This is a test deployment description", + }, + }), + getTokenInfo: vi.fn().mockResolvedValue({ + value: { + name: "Test Token", + symbol: "TEST", + address: "0x123", + decimals: 18, + }, + }), + isSelectTokenSet: vi.fn().mockReturnValue({ value: false }), + setSelectToken: vi.fn(), + unsetSelectToken: vi.fn(), + getDeploymentTransactionArgs: vi.fn(), + getAccountBalance: vi.fn().mockResolvedValue({ + value: "1000000000000000000", + }), + } as unknown as RaindexOrderBuilder; + + mockBuilder = builderInstance; + vi.mocked(useRaindexOrderBuilder).mockReturnValue(mockBuilder); + + // Set default mock return value for useAccount + vi.mocked(useAccount).mockReturnValue({ + account: writable(null), + matchesAccount: vi.fn(), + }); + }); + + it("shows deployment details when provided", async () => { + render(DeploymentSteps, { props: defaultProps }); + + await waitFor(() => { + expect(screen.getByText("SFLR<>WFLR on Flare")).toBeInTheDocument(); + }); + }); + + it("shows select tokens section when tokens need to be selected", async () => { + (mockBuilder.getSelectTokens as Mock).mockReturnValue({ + value: ["token1", "token2"], + }); + + render(DeploymentSteps, { + props: defaultProps, + }); + + await waitFor(() => { + expect(screen.getByText("Select Tokens")).toBeInTheDocument(); + expect( + screen.getByText( + "Select the tokens that you want to use in your order.", + ), + ).toBeInTheDocument(); + }); + }); + + it("shows wallet connect button when all required fields are filled, but no account exists", async () => { + const mockSelectTokens = [ + { key: "token1", name: "Token 1", description: undefined }, + { key: "token2", name: "Token 2", description: undefined }, + ]; + + // Set up specific mocks for this test + (mockBuilder.getSelectTokens as Mock).mockReturnValue({ + value: mockSelectTokens, + }); + (mockBuilder.getTokenInfo as Mock).mockImplementation(() => {}); + (mockBuilder.areAllTokensSelected as Mock).mockReturnValue({ value: true }); + (mockBuilder.isSelectTokenSet as Mock).mockReturnValue({ value: false }); + (mockBuilder.setSelectToken as Mock).mockImplementation(() => {}); + (mockBuilder.getCurrentDeployment as Mock).mockReturnValue({ + value: { + deployment: { + order: { + inputs: [], + outputs: [], + }, + }, + deposits: [], + }, + }); + + (mockBuilder.getAllTokenInfos as Mock).mockResolvedValue({ + value: [ + { + address: "0x1", + decimals: 18, + name: "Token 1", + symbol: "TKN1", + }, + { + address: "0x2", + decimals: 18, + name: "Token 2", + symbol: "TKN2", + }, + ], + }); + + render(DeploymentSteps, { + props: { ...defaultProps, account: readable(null) }, + }); + + await waitFor(() => { + expect(screen.getByText("Connect")).toBeInTheDocument(); + }); + }); + + it("shows deploy button when all required fields are filled, and account is connected", async () => { + const mockSelectTokens = [ + { key: "token1", name: "Token 1", description: undefined }, + { key: "token2", name: "Token 2", description: undefined }, + ]; + + // Set up specific mocks for this test + (mockBuilder.getSelectTokens as Mock).mockReturnValue({ + value: mockSelectTokens, + }); + (mockBuilder.getTokenInfo as Mock).mockImplementation(() => {}); + (mockBuilder.areAllTokensSelected as Mock).mockReturnValue({ value: true }); + (mockBuilder.isSelectTokenSet as Mock).mockReturnValue({ value: false }); + (mockBuilder.setSelectToken as Mock).mockImplementation(() => {}); + (mockBuilder.getCurrentDeployment as Mock).mockReturnValue({ + value: { + deployment: { + order: { + inputs: [], + outputs: [], + }, + }, + deposits: [], + }, + }); + + (mockBuilder.getAllTokenInfos as Mock).mockResolvedValue({ + value: [ + { + address: "0x1", + decimals: 18, + name: "Token 1", + symbol: "TKN1", + }, + { + address: "0x2", + decimals: 18, + name: "Token 2", + symbol: "TKN2", + }, + ], + }); + + render(DeploymentSteps, { props: defaultProps }); + + await waitFor(() => { + expect(screen.getByText("Deploy Order")).toBeInTheDocument(); + }); + }); + it("refreshes field descriptions when tokens change", async () => { + const mockSelectTokens = [ + { key: "token1", name: "Token 1", description: undefined }, + { key: "token2", name: "Token 2", description: undefined }, + ]; + + // Set up specific mocks for this test + (mockBuilder.getSelectTokens as Mock).mockReturnValue({ + value: mockSelectTokens, + }); + (mockBuilder.getTokenInfo as Mock).mockImplementation(() => {}); + (mockBuilder.areAllTokensSelected as Mock).mockReturnValue({ value: true }); + (mockBuilder.isSelectTokenSet as Mock).mockReturnValue({ value: false }); + (mockBuilder.setSelectToken as Mock).mockImplementation(() => {}); + (mockBuilder.getCurrentDeployment as Mock).mockReturnValue({ + value: { + deployment: { + order: { + inputs: [], + outputs: [], + }, + }, + deposits: [], + }, + }); + + (mockBuilder.getAllTokenInfos as Mock).mockResolvedValue({ + value: [ + { + address: "0x1", + decimals: 18, + name: "Token 1", + symbol: "TKN1", + }, + { + address: "0x2", + decimals: 18, + name: "Token 2", + symbol: "TKN2", + }, + ], + }); + + const user = userEvent.setup(); + + render(DeploymentSteps, { + props: defaultProps, + }); + + await waitFor(() => { + expect(mockBuilder.areAllTokensSelected).toHaveBeenCalled(); + }); + + await waitFor(() => { + expect(screen.getByText("Select Tokens")).toBeInTheDocument(); + expect(screen.getByText("Token 1")).toBeInTheDocument(); + expect(screen.getByText("Token 2")).toBeInTheDocument(); + }); + + const selectTokenInput = screen.getByText("Token 1"); + (mockBuilder.getTokenInfo as Mock).mockResolvedValue({ + value: { + address: "0x1", + decimals: 18, + name: "Token 1", + symbol: "TKN1", + }, + }); + await user.type(selectTokenInput, "0x1"); + + const selectTokenOutput = screen.getByText("Token 2"); + (mockBuilder.getTokenInfo as Mock).mockResolvedValue({ + value: { + address: "0x2", + decimals: 18, + name: "Token 2", + symbol: "TKN2", + }, + }); + await user.type(selectTokenOutput, "0x2"); + + await waitFor(() => { + expect(mockBuilder.getAllTokenInfos).toHaveBeenCalled(); + }); + + const customAddressButtons = screen.getAllByTestId("custom-mode-button"); + await user.click(customAddressButtons[customAddressButtons.length - 1]); + const customInputs = screen.getAllByPlaceholderText( + "Enter token address (0x...)", + ); + const lastCustomInput = customInputs[customInputs.length - 1]; + (mockBuilder.getTokenInfo as Mock).mockResolvedValue({ + value: { + address: "0x3", + decimals: 18, + name: "Token 3", + symbol: "TKN3", + }, + }); + await user.type(lastCustomInput, "0x3"); + + (mockBuilder.getAllTokenInfos as Mock).mockResolvedValue({ + value: [ + { + address: "0x3", + decimals: 18, + name: "Token 3", + symbol: "TKN3", + }, + { + address: "0x2", + decimals: 18, + name: "Token 2", + symbol: "TKN2", + }, + ], + }); + + await waitFor(() => { + expect(mockBuilder.getAllTokenInfos).toHaveBeenCalled(); + }); + }); + + it("passes correct arguments to onDeploy prop", async () => { + // Override the mock for this test + builderInstance.areAllTokensSelected = vi + .fn() + .mockReturnValue({ value: true }); + vi.mocked(useRaindexOrderBuilder).mockReturnValue(builderInstance); + + const mockRaindexClient = {} as unknown as RaindexClient; + vi.mocked(useRaindexClient).mockReturnValue(mockRaindexClient); + + const propsWithMockHandlers = { + ...defaultProps, + account: readable("0xTestAccount") as Account, + }; + + const user = userEvent.setup(); + render(DeploymentSteps, { props: propsWithMockHandlers }); + + const deployButton = screen.getByText("Deploy Order"); + await user.click(deployButton); + + await waitFor(() => { + expect(mockOnDeploy).toHaveBeenCalledTimes(1); + + const [raindexClient, builderArg] = mockOnDeploy.mock.calls[0]; + + expect(builderArg).toBe(mockBuilder); + expect(raindexClient).toBe(mockRaindexClient); + }); + }); + + it("calls getTokenInfoAndFetchBalance for each selected token on account change", async () => { + const mockSelectTokens = [ + { key: "token1", name: "Token 1", description: undefined }, + { key: "token2", name: "Token 2", description: undefined }, + ]; + + (mockBuilder.getSelectTokens as Mock).mockReturnValue({ + value: mockSelectTokens, + }); + + const accountStore = writable<`0x${string}` | null>("0x123"); + + const propsWithAccountStore = { + ...defaultProps, + account: accountStore, + }; + + render(DeploymentSteps, { props: propsWithAccountStore }); + + await waitFor(() => { + expect(mockBuilder.getSelectTokens).toHaveBeenCalled(); + }); + vi.clearAllMocks(); + + accountStore.set("0x456"); + + await waitFor(() => { + expect(mockBuilder.getTokenInfo).toHaveBeenCalledTimes(2); + expect(mockBuilder.getTokenInfo).toHaveBeenCalledWith("token1"); + expect(mockBuilder.getTokenInfo).toHaveBeenCalledWith("token2"); + }); + await waitFor(() => { + expect(mockBuilder.getAccountBalance).toHaveBeenCalledTimes(2); + }); + }); + + it("clears token balances when account becomes null", async () => { + const mockSelectTokens = [ + { key: "token1", name: "Token 1", description: undefined }, + ]; + + (mockBuilder.getSelectTokens as Mock).mockReturnValue({ + value: mockSelectTokens, + }); + + const accountStore = writable<`0x${string}` | null>("0x123"); + + const propsWithAccountStore = { + ...defaultProps, + account: accountStore, + }; + + render(DeploymentSteps, { props: propsWithAccountStore }); + + await waitFor(() => { + expect(mockBuilder.getSelectTokens).toHaveBeenCalled(); + }); + + vi.clearAllMocks(); - accountStore.set(null); + accountStore.set(null); - // await new Promise((resolve) => setTimeout(resolve, 100)); - expect(mockBuilder.getTokenInfo).not.toHaveBeenCalled(); - expect(mockBuilder.getAccountBalance).not.toHaveBeenCalled(); - }); + // await new Promise((resolve) => setTimeout(resolve, 100)); + expect(mockBuilder.getTokenInfo).not.toHaveBeenCalled(); + expect(mockBuilder.getAccountBalance).not.toHaveBeenCalled(); + }); }); diff --git a/packages/ui-components/src/__tests__/DeploymentTile.test.ts b/packages/ui-components/src/__tests__/DeploymentTile.test.ts index f20b788ebf..60db0c6c48 100644 --- a/packages/ui-components/src/__tests__/DeploymentTile.test.ts +++ b/packages/ui-components/src/__tests__/DeploymentTile.test.ts @@ -1,24 +1,26 @@ -import { render, screen } from '@testing-library/svelte'; -import { describe, it, expect, vi } from 'vitest'; -import DeploymentTile from '../lib/components/deployment/DeploymentTile.svelte'; +import { render, screen } from "@testing-library/svelte"; +import { describe, it, expect, vi } from "vitest"; +import DeploymentTile from "../lib/components/deployment/DeploymentTile.svelte"; // Mock the goto function -vi.mock('$app/navigation', () => ({ - goto: vi.fn() +vi.mock("$app/navigation", () => ({ + goto: vi.fn(), })); -describe('DeploymentTile', () => { - const mockProps = { - orderName: 'test-order', - key: 'test-key', - name: 'Test Deployment', - description: 'This is a test deployment description' - }; +describe("DeploymentTile", () => { + const mockProps = { + orderName: "test-order", + key: "test-key", + name: "Test Deployment", + description: "This is a test deployment description", + }; - it('renders the deployment name and description', () => { - render(DeploymentTile, mockProps); + it("renders the deployment name and description", () => { + render(DeploymentTile, mockProps); - expect(screen.getByText('Test Deployment')).toBeInTheDocument(); - expect(screen.getByText('This is a test deployment description')).toBeInTheDocument(); - }); + expect(screen.getByText("Test Deployment")).toBeInTheDocument(); + expect( + screen.getByText("This is a test deployment description"), + ).toBeInTheDocument(); + }); }); diff --git a/packages/ui-components/src/__tests__/DeploymentsSection.test.ts b/packages/ui-components/src/__tests__/DeploymentsSection.test.ts index e08bff232c..0aa09a69af 100644 --- a/packages/ui-components/src/__tests__/DeploymentsSection.test.ts +++ b/packages/ui-components/src/__tests__/DeploymentsSection.test.ts @@ -1,36 +1,49 @@ -import { render, screen } from '@testing-library/svelte'; -import { describe, it, expect } from 'vitest'; -import DeploymentsSection from '../lib/components/deployment/DeploymentsSection.svelte'; +import { render, screen } from "@testing-library/svelte"; +import { describe, it, expect } from "vitest"; +import DeploymentsSection from "../lib/components/deployment/DeploymentsSection.svelte"; -describe('DeploymentsSection', () => { - it('renders provided deployments', () => { - const mockDeployments = new Map([ - [ - 'key1', - { name: 'Deployment 1', description: 'Description 1', short_description: 'Short 1' } - ], - ['key2', { name: 'Deployment 2', description: 'Description 2', short_description: 'Short 2' }] - ]); +describe("DeploymentsSection", () => { + it("renders provided deployments", () => { + const mockDeployments = new Map([ + [ + "key1", + { + name: "Deployment 1", + description: "Description 1", + short_description: "Short 1", + }, + ], + [ + "key2", + { + name: "Deployment 2", + description: "Description 2", + short_description: "Short 2", + }, + ], + ]); - render(DeploymentsSection, { - props: { - deployments: mockDeployments, - orderName: 'Test Strategy' - } - }); + render(DeploymentsSection, { + props: { + deployments: mockDeployments, + orderName: "Test Strategy", + }, + }); - expect(screen.getByText('Deployment 1')).toBeInTheDocument(); - expect(screen.getByText('Deployment 2')).toBeInTheDocument(); - }); + expect(screen.getByText("Deployment 1")).toBeInTheDocument(); + expect(screen.getByText("Deployment 2")).toBeInTheDocument(); + }); - it('shows empty state when there are no deployments', () => { - render(DeploymentsSection, { - props: { - deployments: [], - orderName: 'Test Strategy' - } - }); + it("shows empty state when there are no deployments", () => { + render(DeploymentsSection, { + props: { + deployments: [], + orderName: "Test Strategy", + }, + }); - expect(screen.getByText('No deployments found for this order.')).toBeInTheDocument(); - }); + expect( + screen.getByText("No deployments found for this order."), + ).toBeInTheDocument(); + }); }); diff --git a/packages/ui-components/src/__tests__/DepositInput.test.ts b/packages/ui-components/src/__tests__/DepositInput.test.ts index fc5627d955..5273a4711b 100644 --- a/packages/ui-components/src/__tests__/DepositInput.test.ts +++ b/packages/ui-components/src/__tests__/DepositInput.test.ts @@ -1,90 +1,92 @@ -import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; -import { render, fireEvent, waitFor } from '@testing-library/svelte'; -import DepositInput from '../lib/components/deployment/DepositInput.svelte'; -import type { OrderBuilderDepositCfg } from '@rainlanguage/raindex'; -import type { ComponentProps } from 'svelte'; -import { RaindexOrderBuilder } from '@rainlanguage/raindex'; -import { useRaindexOrderBuilder } from '$lib/hooks/useRaindexOrderBuilder'; +import { describe, it, expect, vi, beforeEach, type Mock } from "vitest"; +import { render, fireEvent, waitFor } from "@testing-library/svelte"; +import DepositInput from "../lib/components/deployment/DepositInput.svelte"; +import type { OrderBuilderDepositCfg } from "@rainlanguage/raindex"; +import type { ComponentProps } from "svelte"; +import { RaindexOrderBuilder } from "@rainlanguage/raindex"; +import { useRaindexOrderBuilder } from "$lib/hooks/useRaindexOrderBuilder"; type DepositInputProps = ComponentProps; -vi.mock('@rainlanguage/raindex', () => ({ - RaindexOrderBuilder: vi.fn() +vi.mock("@rainlanguage/raindex", () => ({ + RaindexOrderBuilder: vi.fn(), })); -vi.mock('$lib/hooks/useRaindexOrderBuilder', () => ({ - useRaindexOrderBuilder: vi.fn() +vi.mock("$lib/hooks/useRaindexOrderBuilder", () => ({ + useRaindexOrderBuilder: vi.fn(), })); -describe('DepositInput', () => { - let mockStateUpdateCallback: Mock; - let builderInstance: RaindexOrderBuilder; +describe("DepositInput", () => { + let mockStateUpdateCallback: Mock; + let builderInstance: RaindexOrderBuilder; - const mockDeposit: OrderBuilderDepositCfg = { - token: { address: '0x123', key: 'TEST', symbol: 'TEST' }, - presets: ['100', '200', '300'] - } as unknown as OrderBuilderDepositCfg; + const mockDeposit: OrderBuilderDepositCfg = { + token: { address: "0x123", key: "TEST", symbol: "TEST" }, + presets: ["100", "200", "300"], + } as unknown as OrderBuilderDepositCfg; - beforeEach(() => { - vi.clearAllMocks(); + beforeEach(() => { + vi.clearAllMocks(); - builderInstance = { - getDeposits: vi.fn().mockReturnValue({ - value: [{ token: 'output', amount: '10', address: '0x1234' }] - }), - setDeposit: vi.fn().mockImplementation(() => { - mockStateUpdateCallback(); - }), - getTokenInfo: vi.fn() - } as unknown as RaindexOrderBuilder; + builderInstance = { + getDeposits: vi.fn().mockReturnValue({ + value: [{ token: "output", amount: "10", address: "0x1234" }], + }), + setDeposit: vi.fn().mockImplementation(() => { + mockStateUpdateCallback(); + }), + getTokenInfo: vi.fn(), + } as unknown as RaindexOrderBuilder; - mockStateUpdateCallback = vi.fn(); - (useRaindexOrderBuilder as Mock).mockReturnValue(builderInstance); - }); + mockStateUpdateCallback = vi.fn(); + (useRaindexOrderBuilder as Mock).mockReturnValue(builderInstance); + }); - it('renders token name and presets', async () => { - (builderInstance.getTokenInfo as Mock).mockResolvedValueOnce({ - value: { - name: 'Test Token', - symbol: 'TEST' - } - }); + it("renders token name and presets", async () => { + (builderInstance.getTokenInfo as Mock).mockResolvedValueOnce({ + value: { + name: "Test Token", + symbol: "TEST", + }, + }); - const { getByText } = render(DepositInput, { - props: { - deposit: mockDeposit - } as unknown as DepositInputProps - }); - await waitFor(() => { - expect(getByText(`Deposit amount (${mockDeposit.token?.symbol})`)).toBeTruthy(); - expect(getByText('100')).toBeTruthy(); - expect(getByText('200')).toBeTruthy(); - expect(getByText('300')).toBeTruthy(); - }); - }); + const { getByText } = render(DepositInput, { + props: { + deposit: mockDeposit, + } as unknown as DepositInputProps, + }); + await waitFor(() => { + expect( + getByText(`Deposit amount (${mockDeposit.token?.symbol})`), + ).toBeTruthy(); + expect(getByText("100")).toBeTruthy(); + expect(getByText("200")).toBeTruthy(); + expect(getByText("300")).toBeTruthy(); + }); + }); - it('handles preset button clicks', async () => { - const { getByText } = render(DepositInput, { - props: { - deposit: mockDeposit - } as unknown as DepositInputProps - }); + it("handles preset button clicks", async () => { + const { getByText } = render(DepositInput, { + props: { + deposit: mockDeposit, + } as unknown as DepositInputProps, + }); - await fireEvent.click(getByText('100')); - expect(builderInstance.setDeposit).toHaveBeenCalledWith('TEST', '100'); - }); + await fireEvent.click(getByText("100")); + expect(builderInstance.setDeposit).toHaveBeenCalledWith("TEST", "100"); + }); - it('handles custom input changes and triggers state update', async () => { - const { getByPlaceholderText } = render(DepositInput, { - props: { - deposit: mockDeposit, - onStateUpdate: mockStateUpdateCallback - } as unknown as DepositInputProps - }); + it("handles custom input changes and triggers state update", async () => { + const { getByPlaceholderText } = render(DepositInput, { + props: { + deposit: mockDeposit, + onStateUpdate: mockStateUpdateCallback, + } as unknown as DepositInputProps, + }); - const input = getByPlaceholderText('Enter deposit amount'); - await fireEvent.input(input, { target: { value: '150' } }); + const input = getByPlaceholderText("Enter deposit amount"); + await fireEvent.input(input, { target: { value: "150" } }); - expect(builderInstance.setDeposit).toHaveBeenCalledWith('TEST', '150'); - expect(mockStateUpdateCallback).toHaveBeenCalled(); - }); + expect(builderInstance.setDeposit).toHaveBeenCalledWith("TEST", "150"); + expect(mockStateUpdateCallback).toHaveBeenCalled(); + }); }); diff --git a/packages/ui-components/src/__tests__/DisclaimerModal.test.ts b/packages/ui-components/src/__tests__/DisclaimerModal.test.ts index 335fe4ea64..820a6ea98f 100644 --- a/packages/ui-components/src/__tests__/DisclaimerModal.test.ts +++ b/packages/ui-components/src/__tests__/DisclaimerModal.test.ts @@ -1,39 +1,39 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import { render, screen, fireEvent } from '@testing-library/svelte'; -import DisclaimerModal from '../lib/components/deployment/DisclaimerModal.svelte'; - -describe('DisclaimerModal', () => { - const mockOnAccept = vi.fn(); - - beforeEach(() => { - vi.clearAllMocks(); - }); - - it('calls onAccept when accepting disclaimer', async () => { - render(DisclaimerModal, { - props: { - open: true, - onAccept: mockOnAccept - } - }); - - const deployButton = await screen.findByText('Deploy'); - await fireEvent.click(deployButton); - - expect(mockOnAccept).toHaveBeenCalled(); - }); - - it('does not call onAccept when cancel button is clicked', async () => { - render(DisclaimerModal, { - props: { - open: true, - onAccept: mockOnAccept - } - }); - - const cancelButton = await screen.findByText('Cancel'); - await fireEvent.click(cancelButton); - - expect(mockOnAccept).not.toHaveBeenCalled(); - }); +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { render, screen, fireEvent } from "@testing-library/svelte"; +import DisclaimerModal from "../lib/components/deployment/DisclaimerModal.svelte"; + +describe("DisclaimerModal", () => { + const mockOnAccept = vi.fn(); + + beforeEach(() => { + vi.clearAllMocks(); + }); + + it("calls onAccept when accepting disclaimer", async () => { + render(DisclaimerModal, { + props: { + open: true, + onAccept: mockOnAccept, + }, + }); + + const deployButton = await screen.findByText("Deploy"); + await fireEvent.click(deployButton); + + expect(mockOnAccept).toHaveBeenCalled(); + }); + + it("does not call onAccept when cancel button is clicked", async () => { + render(DisclaimerModal, { + props: { + open: true, + onAccept: mockOnAccept, + }, + }); + + const cancelButton = await screen.findByText("Cancel"); + await fireEvent.click(cancelButton); + + expect(mockOnAccept).not.toHaveBeenCalled(); + }); }); diff --git a/packages/ui-components/src/__tests__/DotrainRegistryProvider.test.ts b/packages/ui-components/src/__tests__/DotrainRegistryProvider.test.ts index 386c3b75ff..ea9d37dbdb 100644 --- a/packages/ui-components/src/__tests__/DotrainRegistryProvider.test.ts +++ b/packages/ui-components/src/__tests__/DotrainRegistryProvider.test.ts @@ -1,57 +1,59 @@ -import { render } from '@testing-library/svelte'; -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import DotrainRegistryProvider from '../lib/providers/dotrainRegistry/DotrainRegistryProvider.svelte'; +import { render } from "@testing-library/svelte"; +import { describe, it, expect, vi, beforeEach } from "vitest"; +import DotrainRegistryProvider from "../lib/providers/dotrainRegistry/DotrainRegistryProvider.svelte"; import { - setDotrainRegistryContext, - type DotrainRegistryContext -} from '../lib/providers/dotrainRegistry/context'; + setDotrainRegistryContext, + type DotrainRegistryContext, +} from "../lib/providers/dotrainRegistry/context"; -vi.mock('../lib/providers/dotrainRegistry/context', () => ({ - setDotrainRegistryContext: vi.fn() +vi.mock("../lib/providers/dotrainRegistry/context", () => ({ + setDotrainRegistryContext: vi.fn(), })); -describe('DotrainRegistryProvider', () => { - const mockSetContext = vi.mocked(setDotrainRegistryContext); +describe("DotrainRegistryProvider", () => { + const mockSetContext = vi.mocked(setDotrainRegistryContext); - beforeEach(() => { - mockSetContext.mockReset(); - }); + beforeEach(() => { + mockSetContext.mockReset(); + }); - it('sets the registry context with provided props', () => { - const registryUrl = 'https://example.com/registry.txt'; - const wasmErrorResult = { - value: undefined, - error: { msg: 'not implemented', readableMsg: 'not implemented' } - }; + it("sets the registry context with provided props", () => { + const registryUrl = "https://example.com/registry.txt"; + const wasmErrorResult = { + value: undefined, + error: { msg: "not implemented", readableMsg: "not implemented" }, + }; - const registry: NonNullable = { - free: vi.fn(), - getAllOrderDetails: vi.fn(() => wasmErrorResult), - getOrderKeys: vi.fn(() => ({ value: [], error: undefined })), - getDeploymentDetails: vi.fn(() => wasmErrorResult), - getOrderBuilder: vi.fn(async () => wasmErrorResult), - getRaindexYaml: vi.fn(() => wasmErrorResult), - getRaindexClient: vi.fn(async () => wasmErrorResult), - registryUrl, - registry: 'registry-content', - settingsUrl: 'https://example.com/settings.yaml', - settings: 'settings-content', - orderUrls: new Map(), - orders: new Map() - }; - const manager = { - getCurrentRegistry: vi.fn().mockReturnValue(registryUrl), - setRegistry: vi.fn(), - resetToDefault: vi.fn(), - updateUrlWithRegistry: vi.fn(), - isCustomRegistry: vi.fn().mockReturnValue(false) - } as unknown as DotrainRegistryContext['manager']; - render(DotrainRegistryProvider, { props: { registry, manager, error: undefined } }); + const registry: NonNullable = { + free: vi.fn(), + getAllOrderDetails: vi.fn(() => wasmErrorResult), + getOrderKeys: vi.fn(() => ({ value: [], error: undefined })), + getDeploymentDetails: vi.fn(() => wasmErrorResult), + getOrderBuilder: vi.fn(async () => wasmErrorResult), + getRaindexYaml: vi.fn(() => wasmErrorResult), + getRaindexClient: vi.fn(async () => wasmErrorResult), + registryUrl, + registry: "registry-content", + settingsUrl: "https://example.com/settings.yaml", + settings: "settings-content", + orderUrls: new Map(), + orders: new Map(), + }; + const manager = { + getCurrentRegistry: vi.fn().mockReturnValue(registryUrl), + setRegistry: vi.fn(), + resetToDefault: vi.fn(), + updateUrlWithRegistry: vi.fn(), + isCustomRegistry: vi.fn().mockReturnValue(false), + } as unknown as DotrainRegistryContext["manager"]; + render(DotrainRegistryProvider, { + props: { registry, manager, error: undefined }, + }); - expect(mockSetContext).toHaveBeenCalledWith({ - registry, - manager, - error: undefined - }); - }); + expect(mockSetContext).toHaveBeenCalledWith({ + registry, + manager, + error: undefined, + }); + }); }); diff --git a/packages/ui-components/src/__tests__/DropdownActiveNetworks.test.ts b/packages/ui-components/src/__tests__/DropdownActiveNetworks.test.ts index e3f256e94e..56e0c4636b 100644 --- a/packages/ui-components/src/__tests__/DropdownActiveNetworks.test.ts +++ b/packages/ui-components/src/__tests__/DropdownActiveNetworks.test.ts @@ -1,80 +1,80 @@ -import { render, fireEvent, screen, waitFor } from '@testing-library/svelte'; -import { get, writable, type Writable } from 'svelte/store'; -import { beforeEach, expect, test, describe, type Mock } from 'vitest'; -import DropdownActiveNetworks from '../lib/components/dropdown/DropdownActiveNetworks.svelte'; -import { useRaindexClient } from '$lib/hooks/useRaindexClient'; -import type { NetworkCfg } from '@rainlanguage/raindex'; +import { render, fireEvent, screen, waitFor } from "@testing-library/svelte"; +import { get, writable, type Writable } from "svelte/store"; +import { beforeEach, expect, test, describe, type Mock } from "vitest"; +import DropdownActiveNetworks from "../lib/components/dropdown/DropdownActiveNetworks.svelte"; +import { useRaindexClient } from "$lib/hooks/useRaindexClient"; +import type { NetworkCfg } from "@rainlanguage/raindex"; -vi.mock('$lib/hooks/useRaindexClient', () => ({ - useRaindexClient: vi.fn() +vi.mock("$lib/hooks/useRaindexClient", () => ({ + useRaindexClient: vi.fn(), })); -describe('DropdownActiveNetworks', () => { - let selectedChainIdsStore: Writable; +describe("DropdownActiveNetworks", () => { + let selectedChainIdsStore: Writable; - beforeEach(() => { - (useRaindexClient as Mock).mockReturnValue({ - getUniqueChainIds: () => ({ - error: undefined, - value: [1, 2, 14] - }), - getAllNetworks: () => ({ - error: undefined, - value: new Map([ - ['mainnet', { key: 'Ethereum', chainId: 1 } as NetworkCfg], - ['testnet', { key: 'Expanse Network', chainId: 2 } as NetworkCfg], - ['local', { key: 'local', chainId: 14 } as NetworkCfg] - ]) - }) - }); - selectedChainIdsStore = writable([]); - }); + beforeEach(() => { + (useRaindexClient as Mock).mockReturnValue({ + getUniqueChainIds: () => ({ + error: undefined, + value: [1, 2, 14], + }), + getAllNetworks: () => ({ + error: undefined, + value: new Map([ + ["mainnet", { key: "Ethereum", chainId: 1 } as NetworkCfg], + ["testnet", { key: "Expanse Network", chainId: 2 } as NetworkCfg], + ["local", { key: "local", chainId: 14 } as NetworkCfg], + ]), + }), + }); + selectedChainIdsStore = writable([]); + }); - test('renders correctly', () => { - render(DropdownActiveNetworks, { - props: { - selectedChainIds: selectedChainIdsStore - } - }); - expect(screen.getByText('Networks')).toBeInTheDocument(); - }); + test("renders correctly", () => { + render(DropdownActiveNetworks, { + props: { + selectedChainIds: selectedChainIdsStore, + }, + }); + expect(screen.getByText("Networks")).toBeInTheDocument(); + }); - test('displays the correct number of options', async () => { - render(DropdownActiveNetworks, { - props: { - selectedChainIds: selectedChainIdsStore - } - }); + test("displays the correct number of options", async () => { + render(DropdownActiveNetworks, { + props: { + selectedChainIds: selectedChainIdsStore, + }, + }); - await fireEvent.click(screen.getByTestId('dropdown-checkbox-button')); + await fireEvent.click(screen.getByTestId("dropdown-checkbox-button")); - await waitFor(() => { - const options = screen.getAllByTestId('dropdown-checkbox-option'); - expect(options).toHaveLength(3); - }); - }); + await waitFor(() => { + const options = screen.getAllByTestId("dropdown-checkbox-option"); + expect(options).toHaveLength(3); + }); + }); - test('updates selected chain ids when an option is selected', async () => { - render(DropdownActiveNetworks, { - props: { - selectedChainIds: selectedChainIdsStore - } - }); + test("updates selected chain ids when an option is selected", async () => { + render(DropdownActiveNetworks, { + props: { + selectedChainIds: selectedChainIdsStore, + }, + }); - await fireEvent.click(screen.getByTestId('dropdown-checkbox-button')); - await fireEvent.click(screen.getByText('Ethereum')); - await waitFor(() => { - expect(get(selectedChainIdsStore)).toEqual([1]); - }); + await fireEvent.click(screen.getByTestId("dropdown-checkbox-button")); + await fireEvent.click(screen.getByText("Ethereum")); + await waitFor(() => { + expect(get(selectedChainIdsStore)).toEqual([1]); + }); - await fireEvent.click(screen.getByText('Expanse Network')); - await waitFor(() => { - expect(get(selectedChainIdsStore)).toEqual([1, 2]); - }); + await fireEvent.click(screen.getByText("Expanse Network")); + await waitFor(() => { + expect(get(selectedChainIdsStore)).toEqual([1, 2]); + }); - await fireEvent.click(screen.getByText('Flare Mainnet')); - await waitFor(() => { - expect(get(selectedChainIdsStore)).toEqual([1, 2, 14]); - }); - }); + await fireEvent.click(screen.getByText("Flare Mainnet")); + await waitFor(() => { + expect(get(selectedChainIdsStore)).toEqual([1, 2, 14]); + }); + }); }); diff --git a/packages/ui-components/src/__tests__/DropdownCheckbox.test.ts b/packages/ui-components/src/__tests__/DropdownCheckbox.test.ts index 234f3104e1..e6247de86f 100644 --- a/packages/ui-components/src/__tests__/DropdownCheckbox.test.ts +++ b/packages/ui-components/src/__tests__/DropdownCheckbox.test.ts @@ -1,194 +1,206 @@ -import { render, screen, fireEvent } from '@testing-library/svelte'; -import { describe, it, expect, vi } from 'vitest'; -import DropdownCheckbox from '../lib/components/dropdown/DropdownCheckbox.svelte'; - -describe('DropdownCheckbox', () => { - const defaultOptions = { - option1: 'Option 1', - option2: 'Option 2', - option3: 'Option 3' - }; - - describe('Rendering', () => { - it('renders with label', () => { - render(DropdownCheckbox, { - props: { options: defaultOptions, label: 'Test Label' } - }); - - expect(screen.getByText('Test Label')).toBeInTheDocument(); - }); - - it('renders dropdown button', () => { - render(DropdownCheckbox, { - props: { options: defaultOptions } - }); - - expect(screen.getByTestId('dropdown-checkbox-button')).toBeInTheDocument(); - }); - - it('shows "Select items" when nothing selected', () => { - render(DropdownCheckbox, { - props: { options: defaultOptions } - }); - - expect(screen.getByTestId('dropdown-checkbox-button')).toHaveTextContent('Select items'); - }); - - it('shows count when items selected', async () => { - render(DropdownCheckbox, { - props: { - options: defaultOptions, - value: { option1: 'Option 1', option2: 'Option 2' } - } - }); - - expect(screen.getByTestId('dropdown-checkbox-button')).toHaveTextContent('2 items'); - }); - - it('shows allLabel when all selected', () => { - render(DropdownCheckbox, { - props: { - options: defaultOptions, - value: { ...defaultOptions }, - allLabel: 'All Items' - } - }); - - expect(screen.getByTestId('dropdown-checkbox-button')).toHaveTextContent('All Items'); - }); - - it('shows emptyMessage when options empty', async () => { - render(DropdownCheckbox, { - props: { options: {}, emptyMessage: 'No items available' } - }); - - const button = screen.getByTestId('dropdown-checkbox-button'); - await fireEvent.click(button); - - expect(screen.getByText('No items available')).toBeInTheDocument(); - }); - }); - - describe('Interactions', () => { - it('toggles individual item on', async () => { - const handleChange = vi.fn(); - const { component } = render(DropdownCheckbox, { - props: { options: defaultOptions, value: {} } - }); - - component.$on('change', handleChange); - - const button = screen.getByTestId('dropdown-checkbox-button'); - await fireEvent.click(button); - - const option1Label = screen.getByText('Option 1').closest('label'); - if (option1Label) await fireEvent.click(option1Label); - - expect(handleChange).toHaveBeenCalledWith( - expect.objectContaining({ - detail: { option1: 'Option 1' } - }) - ); - }); - - it('toggles individual item off', async () => { - const handleChange = vi.fn(); - const { component } = render(DropdownCheckbox, { - props: { options: defaultOptions, value: { option1: 'Option 1' } } - }); - - component.$on('change', handleChange); - - const button = screen.getByTestId('dropdown-checkbox-button'); - await fireEvent.click(button); - - const option1Label = screen.getByText('Option 1').closest('label'); - if (option1Label) await fireEvent.click(option1Label); - - expect(handleChange).toHaveBeenCalledWith( - expect.objectContaining({ - detail: {} - }) - ); - }); - - it('toggles all items via "All items" checkbox', async () => { - const handleChange = vi.fn(); - const { component } = render(DropdownCheckbox, { - props: { options: defaultOptions, value: {}, allLabel: 'All Items' } - }); - - component.$on('change', handleChange); - - const button = screen.getByTestId('dropdown-checkbox-button'); - await fireEvent.click(button); - - const allItemsLabel = screen.getByText('All Items').closest('label'); - if (allItemsLabel) await fireEvent.click(allItemsLabel); - - expect(handleChange).toHaveBeenCalledWith( - expect.objectContaining({ - detail: defaultOptions - }) - ); - }); - - it('dispatches change event with updated value', async () => { - const handleChange = vi.fn(); - const { component } = render(DropdownCheckbox, { - props: { options: defaultOptions, value: {} } - }); - - component.$on('change', handleChange); - - const button = screen.getByTestId('dropdown-checkbox-button'); - await fireEvent.click(button); - - const option1Label = screen.getByText('Option 1').closest('label'); - if (option1Label) await fireEvent.click(option1Label); - - expect(handleChange).toHaveBeenCalledWith( - expect.objectContaining({ - detail: { option1: 'Option 1' } - }) - ); - }); - }); - - describe('Props', () => { - it('onlyTitle=true hides secondary text (keys)', async () => { - render(DropdownCheckbox, { - props: { options: defaultOptions, onlyTitle: true } - }); - - const button = screen.getByTestId('dropdown-checkbox-button'); - await fireEvent.click(button); - - expect(screen.getByText('Option 1')).toBeInTheDocument(); - expect(screen.queryByText('option1')).not.toBeInTheDocument(); - }); - - it('onlyTitle=false shows secondary text (keys)', async () => { - render(DropdownCheckbox, { - props: { options: defaultOptions, onlyTitle: false } - }); - - const button = screen.getByTestId('dropdown-checkbox-button'); - await fireEvent.click(button); - - expect(screen.getByText('Option 1')).toBeInTheDocument(); - expect(screen.getByText('option1')).toBeInTheDocument(); - }); - - it('showAllLabel=false hides "All items" option', async () => { - render(DropdownCheckbox, { - props: { options: defaultOptions, showAllLabel: false, allLabel: 'All Items' } - }); - - const button = screen.getByTestId('dropdown-checkbox-button'); - await fireEvent.click(button); - - expect(screen.queryByText('All Items')).not.toBeInTheDocument(); - }); - }); +import { render, screen, fireEvent } from "@testing-library/svelte"; +import { describe, it, expect, vi } from "vitest"; +import DropdownCheckbox from "../lib/components/dropdown/DropdownCheckbox.svelte"; + +describe("DropdownCheckbox", () => { + const defaultOptions = { + option1: "Option 1", + option2: "Option 2", + option3: "Option 3", + }; + + describe("Rendering", () => { + it("renders with label", () => { + render(DropdownCheckbox, { + props: { options: defaultOptions, label: "Test Label" }, + }); + + expect(screen.getByText("Test Label")).toBeInTheDocument(); + }); + + it("renders dropdown button", () => { + render(DropdownCheckbox, { + props: { options: defaultOptions }, + }); + + expect( + screen.getByTestId("dropdown-checkbox-button"), + ).toBeInTheDocument(); + }); + + it('shows "Select items" when nothing selected', () => { + render(DropdownCheckbox, { + props: { options: defaultOptions }, + }); + + expect(screen.getByTestId("dropdown-checkbox-button")).toHaveTextContent( + "Select items", + ); + }); + + it("shows count when items selected", async () => { + render(DropdownCheckbox, { + props: { + options: defaultOptions, + value: { option1: "Option 1", option2: "Option 2" }, + }, + }); + + expect(screen.getByTestId("dropdown-checkbox-button")).toHaveTextContent( + "2 items", + ); + }); + + it("shows allLabel when all selected", () => { + render(DropdownCheckbox, { + props: { + options: defaultOptions, + value: { ...defaultOptions }, + allLabel: "All Items", + }, + }); + + expect(screen.getByTestId("dropdown-checkbox-button")).toHaveTextContent( + "All Items", + ); + }); + + it("shows emptyMessage when options empty", async () => { + render(DropdownCheckbox, { + props: { options: {}, emptyMessage: "No items available" }, + }); + + const button = screen.getByTestId("dropdown-checkbox-button"); + await fireEvent.click(button); + + expect(screen.getByText("No items available")).toBeInTheDocument(); + }); + }); + + describe("Interactions", () => { + it("toggles individual item on", async () => { + const handleChange = vi.fn(); + const { component } = render(DropdownCheckbox, { + props: { options: defaultOptions, value: {} }, + }); + + component.$on("change", handleChange); + + const button = screen.getByTestId("dropdown-checkbox-button"); + await fireEvent.click(button); + + const option1Label = screen.getByText("Option 1").closest("label"); + if (option1Label) await fireEvent.click(option1Label); + + expect(handleChange).toHaveBeenCalledWith( + expect.objectContaining({ + detail: { option1: "Option 1" }, + }), + ); + }); + + it("toggles individual item off", async () => { + const handleChange = vi.fn(); + const { component } = render(DropdownCheckbox, { + props: { options: defaultOptions, value: { option1: "Option 1" } }, + }); + + component.$on("change", handleChange); + + const button = screen.getByTestId("dropdown-checkbox-button"); + await fireEvent.click(button); + + const option1Label = screen.getByText("Option 1").closest("label"); + if (option1Label) await fireEvent.click(option1Label); + + expect(handleChange).toHaveBeenCalledWith( + expect.objectContaining({ + detail: {}, + }), + ); + }); + + it('toggles all items via "All items" checkbox', async () => { + const handleChange = vi.fn(); + const { component } = render(DropdownCheckbox, { + props: { options: defaultOptions, value: {}, allLabel: "All Items" }, + }); + + component.$on("change", handleChange); + + const button = screen.getByTestId("dropdown-checkbox-button"); + await fireEvent.click(button); + + const allItemsLabel = screen.getByText("All Items").closest("label"); + if (allItemsLabel) await fireEvent.click(allItemsLabel); + + expect(handleChange).toHaveBeenCalledWith( + expect.objectContaining({ + detail: defaultOptions, + }), + ); + }); + + it("dispatches change event with updated value", async () => { + const handleChange = vi.fn(); + const { component } = render(DropdownCheckbox, { + props: { options: defaultOptions, value: {} }, + }); + + component.$on("change", handleChange); + + const button = screen.getByTestId("dropdown-checkbox-button"); + await fireEvent.click(button); + + const option1Label = screen.getByText("Option 1").closest("label"); + if (option1Label) await fireEvent.click(option1Label); + + expect(handleChange).toHaveBeenCalledWith( + expect.objectContaining({ + detail: { option1: "Option 1" }, + }), + ); + }); + }); + + describe("Props", () => { + it("onlyTitle=true hides secondary text (keys)", async () => { + render(DropdownCheckbox, { + props: { options: defaultOptions, onlyTitle: true }, + }); + + const button = screen.getByTestId("dropdown-checkbox-button"); + await fireEvent.click(button); + + expect(screen.getByText("Option 1")).toBeInTheDocument(); + expect(screen.queryByText("option1")).not.toBeInTheDocument(); + }); + + it("onlyTitle=false shows secondary text (keys)", async () => { + render(DropdownCheckbox, { + props: { options: defaultOptions, onlyTitle: false }, + }); + + const button = screen.getByTestId("dropdown-checkbox-button"); + await fireEvent.click(button); + + expect(screen.getByText("Option 1")).toBeInTheDocument(); + expect(screen.getByText("option1")).toBeInTheDocument(); + }); + + it('showAllLabel=false hides "All items" option', async () => { + render(DropdownCheckbox, { + props: { + options: defaultOptions, + showAllLabel: false, + allLabel: "All Items", + }, + }); + + const button = screen.getByTestId("dropdown-checkbox-button"); + await fireEvent.click(button); + + expect(screen.queryByText("All Items")).not.toBeInTheDocument(); + }); + }); }); diff --git a/packages/ui-components/src/__tests__/DropdownProperty.test.ts b/packages/ui-components/src/__tests__/DropdownProperty.test.ts index c30f10187b..7cf106fbd2 100644 --- a/packages/ui-components/src/__tests__/DropdownProperty.test.ts +++ b/packages/ui-components/src/__tests__/DropdownProperty.test.ts @@ -1,22 +1,22 @@ -import { render, screen } from '@testing-library/svelte'; -import { describe, it, expect } from 'vitest'; -import DropdownProperty from '../lib/components/DropdownProperty.svelte'; +import { render, screen } from "@testing-library/svelte"; +import { describe, it, expect } from "vitest"; +import DropdownProperty from "../lib/components/DropdownProperty.svelte"; -describe('DropdownProperty', () => { - it('should render the component', () => { - render(DropdownProperty, { - key: 'testKey', - value: 'testValue' - }); +describe("DropdownProperty", () => { + it("should render the component", () => { + render(DropdownProperty, { + key: "testKey", + value: "testValue", + }); - expect(screen.getByText('testKey')).toBeInTheDocument(); - expect(screen.getByText('testValue')).toBeInTheDocument(); - }); - it('should handle empty values', () => { - render(DropdownProperty, { - key: 'emptyTest', - value: '' - }); - expect(screen.getByText('emptyTest')).toBeInTheDocument(); - }); + expect(screen.getByText("testKey")).toBeInTheDocument(); + expect(screen.getByText("testValue")).toBeInTheDocument(); + }); + it("should handle empty values", () => { + render(DropdownProperty, { + key: "emptyTest", + value: "", + }); + expect(screen.getByText("emptyTest")).toBeInTheDocument(); + }); }); diff --git a/packages/ui-components/src/__tests__/DropdownRadio.test.ts b/packages/ui-components/src/__tests__/DropdownRadio.test.ts index 67939900fa..e3603cb125 100644 --- a/packages/ui-components/src/__tests__/DropdownRadio.test.ts +++ b/packages/ui-components/src/__tests__/DropdownRadio.test.ts @@ -1,120 +1,122 @@ -import { describe, it, expect } from 'vitest'; -import { render, fireEvent } from '@testing-library/svelte'; -import DropdownRadio from '../lib/components/dropdown/DropdownRadio.svelte'; -import { tick } from 'svelte'; - -describe('DropdownRadio', () => { - const options = { - option1: { label: 'Option 1' }, - option2: { label: 'Option 2' }, - option3: { label: 'Option 3' } - }; - - it('renders without crashing', () => { - const { container } = render(DropdownRadio, { props: { options } }); - expect(container).toBeTruthy(); - }); +import { describe, it, expect } from "vitest"; +import { render, fireEvent } from "@testing-library/svelte"; +import DropdownRadio from "../lib/components/dropdown/DropdownRadio.svelte"; +import { tick } from "svelte"; + +describe("DropdownRadio", () => { + const options = { + option1: { label: "Option 1" }, + option2: { label: "Option 2" }, + option3: { label: "Option 3" }, + }; + + it("renders without crashing", () => { + const { container } = render(DropdownRadio, { props: { options } }); + expect(container).toBeTruthy(); + }); + + it("displays options when clicked", async () => { + const { getByRole, getAllByRole } = render(DropdownRadio, { + props: { options }, + }); + + const button = getByRole("button"); + await fireEvent.click(button); + + const radioButtons = getAllByRole("radio"); + expect(radioButtons).toHaveLength(3); + }); + + it("selects an option when clicked", async () => { + const { getByRole, getAllByRole } = render(DropdownRadio, { + props: { options, value: undefined }, + }); + + const button = getByRole("button"); + await fireEvent.click(button); + + const radioButtons = getAllByRole("radio"); + await fireEvent.click(radioButtons[0]); + + expect(radioButtons[0]).toBeChecked(); + }); + + it("emits change event when option selected", async () => { + let selectedValue; + const { getByRole, getAllByRole, component } = render(DropdownRadio, { + props: { options }, + }); + + component.$on("change", (e) => { + selectedValue = e.detail.value; + }); + + const button = getByRole("button"); + await fireEvent.click(button); + + const radioButtons = getAllByRole("radio"); + await fireEvent.click(radioButtons[0]); + + expect(selectedValue).toBe("option1"); + }); + + it("closes dropdown after selection", async () => { + const { getByRole, getAllByRole, getByTestId } = render(DropdownRadio, { + props: { options }, + }); + + const button = getByRole("button"); + await fireEvent.click(button); + + const dropdown = getByTestId("dropdown"); + expect(dropdown).toBeVisible(); + + const radioButtons = getAllByRole("radio"); + await fireEvent.click(radioButtons[0]); + + expect(dropdown).not.toBeVisible(); + }); + + it("sorts options alphabetically", async () => { + const unsortedOptions = { + c: { label: "C Option" }, + a: { label: "A Option" }, + b: { label: "B Option" }, + }; + + const { getByRole, getAllByRole } = render(DropdownRadio, { + props: { options: unsortedOptions }, + }); + + const button = getByRole("button"); + await fireEvent.click(button); + + const radioButtons = getAllByRole("radio") as HTMLInputElement[]; + expect(radioButtons[0].value).toBe("a"); + expect(radioButtons[1].value).toBe("b"); + expect(radioButtons[2].value).toBe("c"); + }); + + it("emits change event and closes dropdown when value changes programmatically", async () => { + let selectedValue; + const { component, getByRole, getByTestId } = render(DropdownRadio, { + props: { options, value: undefined }, + }); - it('displays options when clicked', async () => { - const { getByRole, getAllByRole } = render(DropdownRadio, { props: { options } }); + const button = getByRole("button"); + await fireEvent.click(button); - const button = getByRole('button'); - await fireEvent.click(button); + const dropdown = getByTestId("dropdown"); + expect(dropdown).toBeVisible(); - const radioButtons = getAllByRole('radio'); - expect(radioButtons).toHaveLength(3); - }); + component.$on("change", (e) => { + selectedValue = e.detail.value; + }); - it('selects an option when clicked', async () => { - const { getByRole, getAllByRole } = render(DropdownRadio, { - props: { options, value: undefined } - }); + component.$set({ value: "option1" }); + await tick(); - const button = getByRole('button'); - await fireEvent.click(button); - - const radioButtons = getAllByRole('radio'); - await fireEvent.click(radioButtons[0]); - - expect(radioButtons[0]).toBeChecked(); - }); - - it('emits change event when option selected', async () => { - let selectedValue; - const { getByRole, getAllByRole, component } = render(DropdownRadio, { - props: { options } - }); - - component.$on('change', (e) => { - selectedValue = e.detail.value; - }); - - const button = getByRole('button'); - await fireEvent.click(button); - - const radioButtons = getAllByRole('radio'); - await fireEvent.click(radioButtons[0]); - - expect(selectedValue).toBe('option1'); - }); - - it('closes dropdown after selection', async () => { - const { getByRole, getAllByRole, getByTestId } = render(DropdownRadio, { - props: { options } - }); - - const button = getByRole('button'); - await fireEvent.click(button); - - const dropdown = getByTestId('dropdown'); - expect(dropdown).toBeVisible(); - - const radioButtons = getAllByRole('radio'); - await fireEvent.click(radioButtons[0]); - - expect(dropdown).not.toBeVisible(); - }); - - it('sorts options alphabetically', async () => { - const unsortedOptions = { - c: { label: 'C Option' }, - a: { label: 'A Option' }, - b: { label: 'B Option' } - }; - - const { getByRole, getAllByRole } = render(DropdownRadio, { - props: { options: unsortedOptions } - }); - - const button = getByRole('button'); - await fireEvent.click(button); - - const radioButtons = getAllByRole('radio') as HTMLInputElement[]; - expect(radioButtons[0].value).toBe('a'); - expect(radioButtons[1].value).toBe('b'); - expect(radioButtons[2].value).toBe('c'); - }); - - it('emits change event and closes dropdown when value changes programmatically', async () => { - let selectedValue; - const { component, getByRole, getByTestId } = render(DropdownRadio, { - props: { options, value: undefined } - }); - - const button = getByRole('button'); - await fireEvent.click(button); - - const dropdown = getByTestId('dropdown'); - expect(dropdown).toBeVisible(); - - component.$on('change', (e) => { - selectedValue = e.detail.value; - }); - - component.$set({ value: 'option1' }); - await tick(); - - expect(selectedValue).toBe('option1'); - expect(dropdown).not.toBeVisible(); - }); + expect(selectedValue).toBe("option1"); + expect(dropdown).not.toBeVisible(); + }); }); diff --git a/packages/ui-components/src/__tests__/DropdownRaindexesFilter.test.ts b/packages/ui-components/src/__tests__/DropdownRaindexesFilter.test.ts index 75a63d5e60..a691ae9ff1 100644 --- a/packages/ui-components/src/__tests__/DropdownRaindexesFilter.test.ts +++ b/packages/ui-components/src/__tests__/DropdownRaindexesFilter.test.ts @@ -1,496 +1,558 @@ -import { render, fireEvent, screen, waitFor } from '@testing-library/svelte'; -import { get, writable } from 'svelte/store'; -import DropdownRaindexesFilter from '../lib/components/dropdown/DropdownRaindexesFilter.svelte'; -import { expect, test, describe, beforeEach, vi, type Mock } from 'vitest'; -import type { Address } from '@rainlanguage/raindex'; -import { useRaindexClient } from '$lib/hooks/useRaindexClient'; - -vi.mock('$lib/hooks/useRaindexClient', () => ({ - useRaindexClient: vi.fn() +import { render, fireEvent, screen, waitFor } from "@testing-library/svelte"; +import { get, writable } from "svelte/store"; +import DropdownRaindexesFilter from "../lib/components/dropdown/DropdownRaindexesFilter.svelte"; +import { expect, test, describe, beforeEach, vi, type Mock } from "vitest"; +import type { Address } from "@rainlanguage/raindex"; +import { useRaindexClient } from "$lib/hooks/useRaindexClient"; + +vi.mock("$lib/hooks/useRaindexClient", () => ({ + useRaindexClient: vi.fn(), })); const mockRaindexesData = new Map([ - [ - 'raindex1', - { - key: 'raindex1', - address: '0x1234567890123456789012345678901234567890', - label: 'Raindex One', - network: { chainId: 1 } - } - ], - [ - 'raindex2', - { - key: 'raindex2', - address: '0x2345678901234567890123456789012345678901', - label: 'Raindex Two', - network: { chainId: 1 } - } - ], - [ - 'raindex3', - { - key: 'raindex3', - address: '0x3456789012345678901234567890123456789012', - label: null, - network: { chainId: 137 } - } - ] + [ + "raindex1", + { + key: "raindex1", + address: "0x1234567890123456789012345678901234567890", + label: "Raindex One", + network: { chainId: 1 }, + }, + ], + [ + "raindex2", + { + key: "raindex2", + address: "0x2345678901234567890123456789012345678901", + label: "Raindex Two", + network: { chainId: 1 }, + }, + ], + [ + "raindex3", + { + key: "raindex3", + address: "0x3456789012345678901234567890123456789012", + label: null, + network: { chainId: 137 }, + }, + ], ]); -describe('DropdownRaindexesFilter', () => { - let activeRaindexAddresses: ReturnType>; - - beforeEach(() => { - activeRaindexAddresses = writable([]); - - (useRaindexClient as Mock).mockReturnValue({ - getAllRaindexes: vi.fn(() => ({ - value: mockRaindexesData, - error: undefined - })) - }); - }); - - describe('Empty state', () => { - test('displays empty message when no raindexes available', async () => { - (useRaindexClient as Mock).mockReturnValue({ - getAllRaindexes: vi.fn(() => ({ - value: new Map(), - error: undefined - })) - }); - - render(DropdownRaindexesFilter, { - props: { - activeRaindexAddresses, - selectedRaindexAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); - - await waitFor(() => { - expect(screen.getByText('No raindexes available')).toBeInTheDocument(); - }); - }); - - test('displays custom empty message', async () => { - (useRaindexClient as Mock).mockReturnValue({ - getAllRaindexes: vi.fn(() => ({ - value: new Map(), - error: undefined - })) - }); - - const customEmptyMessage = 'Raindex list is empty'; - - render(DropdownRaindexesFilter, { - props: { - activeRaindexAddresses, - selectedRaindexAddresses: [], - selectedChainIds: [], - emptyMessage: customEmptyMessage - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); - - await waitFor(() => { - expect(screen.getByText(customEmptyMessage)).toBeInTheDocument(); - }); - }); - }); - - describe('Error state', () => { - test('displays error message when getAllRaindexes returns error', async () => { - const errorMessage = 'Failed to load raindexes'; - (useRaindexClient as Mock).mockReturnValue({ - getAllRaindexes: vi.fn(() => ({ - value: undefined, - error: { readableMsg: errorMessage } - })) - }); - - render(DropdownRaindexesFilter, { - props: { - activeRaindexAddresses, - selectedRaindexAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); - - await waitFor(() => { - expect(screen.getByText(`Cannot load raindexes list: ${errorMessage}`)).toBeInTheDocument(); - }); - }); - }); - - describe('Selected raindexes display', () => { - test('displays "Select raindexes" when no raindexes are selected', () => { - render(DropdownRaindexesFilter, { - props: { - activeRaindexAddresses, - selectedRaindexAddresses: [], - selectedChainIds: [] - } - }); - - expect(screen.getByText('Select raindexes')).toBeInTheDocument(); - }); - - test('displays "All raindexes" when all raindexes are selected', () => { - const allAddresses = Array.from(mockRaindexesData.values()).map( - (raindex) => raindex.address - ) as Address[]; - - render(DropdownRaindexesFilter, { - props: { - activeRaindexAddresses, - selectedRaindexAddresses: allAddresses, - selectedChainIds: [] - } - }); - - expect(screen.getByText('All raindexes')).toBeInTheDocument(); - }); - - test('displays custom all label when all raindexes are selected', () => { - const allAddresses = Array.from(mockRaindexesData.values()).map( - (raindex) => raindex.address - ) as Address[]; - const customAllLabel = 'Everything selected'; - - render(DropdownRaindexesFilter, { - props: { - activeRaindexAddresses, - selectedRaindexAddresses: allAddresses, - selectedChainIds: [], - allLabel: customAllLabel - } - }); - - expect(screen.getByText(customAllLabel)).toBeInTheDocument(); - }); - - test('displays count when one raindex is selected', () => { - const selectedAddress = Array.from(mockRaindexesData.values())[0].address as Address; - - render(DropdownRaindexesFilter, { - props: { - activeRaindexAddresses, - selectedRaindexAddresses: [selectedAddress], - selectedChainIds: [] - } - }); - - expect(screen.getByText('1 raindex')).toBeInTheDocument(); - }); - - test('displays plural count when multiple raindexes are selected', () => { - const selectedAddresses = Array.from(mockRaindexesData.values()) - .slice(0, 2) - .map((raindex) => raindex.address) as Address[]; - - render(DropdownRaindexesFilter, { - props: { - activeRaindexAddresses, - selectedRaindexAddresses: selectedAddresses, - selectedChainIds: [] - } - }); - - expect(screen.getByText('2 raindexes')).toBeInTheDocument(); - }); - - test('updates selected raindexes when checkbox is clicked', async () => { - render(DropdownRaindexesFilter, { - props: { - activeRaindexAddresses, - selectedRaindexAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); - - const checkboxes = screen.getAllByTestId('dropdown-raindexes-filter-option'); - await fireEvent.click(checkboxes[0]); - - await waitFor(() => { - const selected = get(activeRaindexAddresses); - expect(selected.length).toBe(1); - }); - }); - - test('shows selected raindexes as checked', async () => { - const selectedAddress = Array.from(mockRaindexesData.values())[0].address as Address; - - render(DropdownRaindexesFilter, { - props: { - activeRaindexAddresses, - selectedRaindexAddresses: [selectedAddress], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); - - await waitFor(() => { - expect(screen.getByText('1 raindex')).toBeInTheDocument(); - }); - }); - }); - - describe('Chain filtering', () => { - test('shows all raindexes when selectedChainIds is empty', async () => { - render(DropdownRaindexesFilter, { - props: { - activeRaindexAddresses, - selectedRaindexAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); - - await waitFor(() => { - const checkboxes = screen.getAllByTestId('dropdown-raindexes-filter-option'); - expect(checkboxes.length).toBe(3); - }); - }); - - test('filters raindexes by selected chain ID', async () => { - render(DropdownRaindexesFilter, { - props: { - activeRaindexAddresses, - selectedRaindexAddresses: [], - selectedChainIds: [1] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); - - await waitFor(() => { - const checkboxes = screen.getAllByTestId('dropdown-raindexes-filter-option'); - expect(checkboxes.length).toBe(2); - }); - }); - - test('shows raindexes from multiple selected chains', async () => { - render(DropdownRaindexesFilter, { - props: { - activeRaindexAddresses, - selectedRaindexAddresses: [], - selectedChainIds: [1, 137] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); - - await waitFor(() => { - const checkboxes = screen.getAllByTestId('dropdown-raindexes-filter-option'); - expect(checkboxes.length).toBe(3); - }); - }); - }); - - describe('Display format', () => { - test('displays label with truncated address when label exists', async () => { - render(DropdownRaindexesFilter, { - props: { - activeRaindexAddresses, - selectedRaindexAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); - - await waitFor(() => { - expect(screen.getByText(/Raindex One/)).toBeInTheDocument(); - expect(screen.getByText(/0x1234\.\.\.7890/)).toBeInTheDocument(); - }); - }); - - test('displays only truncated address when no label', async () => { - render(DropdownRaindexesFilter, { - props: { - activeRaindexAddresses, - selectedRaindexAddresses: [], - selectedChainIds: [137] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); - - await waitFor(() => { - expect(screen.getByText(/0x3456\.\.\.9012/)).toBeInTheDocument(); - }); - }); - - test('displays network name next to each raindex', async () => { - render(DropdownRaindexesFilter, { - props: { - activeRaindexAddresses, - selectedRaindexAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); - - await waitFor(() => { - expect(screen.getAllByText('Ethereum').length).toBeGreaterThan(0); - expect(screen.getByText('Polygon')).toBeInTheDocument(); - }); - }); - }); - - describe('Search and keyboard navigation', () => { - test('filters raindexes based on search term (label)', async () => { - render(DropdownRaindexesFilter, { - props: { - activeRaindexAddresses, - selectedRaindexAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); - - const searchInput = screen.getByTestId('raindexes-filter-search'); - await fireEvent.input(searchInput, { target: { value: 'One' } }); - - await waitFor(() => { - const options = screen.getAllByTestId('dropdown-raindexes-filter-option'); - expect(options).toHaveLength(1); - expect(screen.getByText(/Raindex One/)).toBeInTheDocument(); - }); - }); - - test('filters raindexes based on search term (address)', async () => { - render(DropdownRaindexesFilter, { - props: { - activeRaindexAddresses, - selectedRaindexAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); - - const searchInput = screen.getByTestId('raindexes-filter-search'); - await fireEvent.input(searchInput, { target: { value: '0x1234' } }); - - await waitFor(() => { - const options = screen.getAllByTestId('dropdown-raindexes-filter-option'); - expect(options).toHaveLength(1); - }); - }); - - test('shows "No raindexes match your search" when search yields no results', async () => { - render(DropdownRaindexesFilter, { - props: { - activeRaindexAddresses, - selectedRaindexAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); - - const searchInput = screen.getByTestId('raindexes-filter-search'); - await fireEvent.input(searchInput, { target: { value: 'NONEXISTENT' } }); - - await waitFor(() => { - expect(screen.getByText('No raindexes match your search')).toBeInTheDocument(); - }); - }); - - test('keyboard navigation works correctly (ArrowDown/ArrowUp)', async () => { - render(DropdownRaindexesFilter, { - props: { - activeRaindexAddresses, - selectedRaindexAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); - - const searchInput = screen.getByTestId('raindexes-filter-search'); - - await fireEvent.keyDown(searchInput, { key: 'ArrowDown' }); - - await waitFor(() => { - const options = screen.getAllByTestId('dropdown-raindexes-filter-option'); - const secondItemLabel = options[1].closest('label'); - expect(secondItemLabel).toHaveClass('bg-blue-100', 'dark:bg-blue-900'); - }); - - await fireEvent.keyDown(searchInput, { key: 'ArrowUp' }); - - await waitFor(() => { - const options = screen.getAllByTestId('dropdown-raindexes-filter-option'); - const firstItemLabel = options[0].closest('label'); - expect(firstItemLabel).toHaveClass('bg-blue-100', 'dark:bg-blue-900'); - }); - }); - - test('Enter key selects highlighted raindex', async () => { - render(DropdownRaindexesFilter, { - props: { - activeRaindexAddresses, - selectedRaindexAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); - - const searchInput = screen.getByTestId('raindexes-filter-search'); - - await fireEvent.input(searchInput, { target: { value: 'One' } }); - - await waitFor(() => { - const options = screen.getAllByTestId('dropdown-raindexes-filter-option'); - expect(options).toHaveLength(1); - }); - - await fireEvent.keyDown(searchInput, { key: 'Enter' }); - - await waitFor(() => { - const selected = get(activeRaindexAddresses); - expect(selected).toContain('0x1234567890123456789012345678901234567890'.toLowerCase()); - }); - }); - - test('Escape key clears search', async () => { - render(DropdownRaindexesFilter, { - props: { - activeRaindexAddresses, - selectedRaindexAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); - - const searchInput = screen.getByTestId('raindexes-filter-search') as HTMLInputElement; - - await fireEvent.input(searchInput, { target: { value: 'One' } }); - expect(searchInput.value).toBe('One'); - - await fireEvent.keyDown(searchInput, { key: 'Escape' }); - - await waitFor(() => { - expect(searchInput.value).toBe(''); - }); - }); - }); +describe("DropdownRaindexesFilter", () => { + let activeRaindexAddresses: ReturnType>; + + beforeEach(() => { + activeRaindexAddresses = writable([]); + + (useRaindexClient as Mock).mockReturnValue({ + getAllRaindexes: vi.fn(() => ({ + value: mockRaindexesData, + error: undefined, + })), + }); + }); + + describe("Empty state", () => { + test("displays empty message when no raindexes available", async () => { + (useRaindexClient as Mock).mockReturnValue({ + getAllRaindexes: vi.fn(() => ({ + value: new Map(), + error: undefined, + })), + }); + + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-raindexes-filter-button"), + ); + + await waitFor(() => { + expect(screen.getByText("No raindexes available")).toBeInTheDocument(); + }); + }); + + test("displays custom empty message", async () => { + (useRaindexClient as Mock).mockReturnValue({ + getAllRaindexes: vi.fn(() => ({ + value: new Map(), + error: undefined, + })), + }); + + const customEmptyMessage = "Raindex list is empty"; + + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [], + emptyMessage: customEmptyMessage, + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-raindexes-filter-button"), + ); + + await waitFor(() => { + expect(screen.getByText(customEmptyMessage)).toBeInTheDocument(); + }); + }); + }); + + describe("Error state", () => { + test("displays error message when getAllRaindexes returns error", async () => { + const errorMessage = "Failed to load raindexes"; + (useRaindexClient as Mock).mockReturnValue({ + getAllRaindexes: vi.fn(() => ({ + value: undefined, + error: { readableMsg: errorMessage }, + })), + }); + + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-raindexes-filter-button"), + ); + + await waitFor(() => { + expect( + screen.getByText(`Cannot load raindexes list: ${errorMessage}`), + ).toBeInTheDocument(); + }); + }); + }); + + describe("Selected raindexes display", () => { + test('displays "Select raindexes" when no raindexes are selected', () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [], + }, + }); + + expect(screen.getByText("Select raindexes")).toBeInTheDocument(); + }); + + test('displays "All raindexes" when all raindexes are selected', () => { + const allAddresses = Array.from(mockRaindexesData.values()).map( + (raindex) => raindex.address, + ) as Address[]; + + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: allAddresses, + selectedChainIds: [], + }, + }); + + expect(screen.getByText("All raindexes")).toBeInTheDocument(); + }); + + test("displays custom all label when all raindexes are selected", () => { + const allAddresses = Array.from(mockRaindexesData.values()).map( + (raindex) => raindex.address, + ) as Address[]; + const customAllLabel = "Everything selected"; + + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: allAddresses, + selectedChainIds: [], + allLabel: customAllLabel, + }, + }); + + expect(screen.getByText(customAllLabel)).toBeInTheDocument(); + }); + + test("displays count when one raindex is selected", () => { + const selectedAddress = Array.from(mockRaindexesData.values())[0] + .address as Address; + + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [selectedAddress], + selectedChainIds: [], + }, + }); + + expect(screen.getByText("1 raindex")).toBeInTheDocument(); + }); + + test("displays plural count when multiple raindexes are selected", () => { + const selectedAddresses = Array.from(mockRaindexesData.values()) + .slice(0, 2) + .map((raindex) => raindex.address) as Address[]; + + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: selectedAddresses, + selectedChainIds: [], + }, + }); + + expect(screen.getByText("2 raindexes")).toBeInTheDocument(); + }); + + test("updates selected raindexes when checkbox is clicked", async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-raindexes-filter-button"), + ); + + const checkboxes = screen.getAllByTestId( + "dropdown-raindexes-filter-option", + ); + await fireEvent.click(checkboxes[0]); + + await waitFor(() => { + const selected = get(activeRaindexAddresses); + expect(selected.length).toBe(1); + }); + }); + + test("shows selected raindexes as checked", async () => { + const selectedAddress = Array.from(mockRaindexesData.values())[0] + .address as Address; + + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [selectedAddress], + selectedChainIds: [], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-raindexes-filter-button"), + ); + + await waitFor(() => { + expect(screen.getByText("1 raindex")).toBeInTheDocument(); + }); + }); + }); + + describe("Chain filtering", () => { + test("shows all raindexes when selectedChainIds is empty", async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-raindexes-filter-button"), + ); + + await waitFor(() => { + const checkboxes = screen.getAllByTestId( + "dropdown-raindexes-filter-option", + ); + expect(checkboxes.length).toBe(3); + }); + }); + + test("filters raindexes by selected chain ID", async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [1], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-raindexes-filter-button"), + ); + + await waitFor(() => { + const checkboxes = screen.getAllByTestId( + "dropdown-raindexes-filter-option", + ); + expect(checkboxes.length).toBe(2); + }); + }); + + test("shows raindexes from multiple selected chains", async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [1, 137], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-raindexes-filter-button"), + ); + + await waitFor(() => { + const checkboxes = screen.getAllByTestId( + "dropdown-raindexes-filter-option", + ); + expect(checkboxes.length).toBe(3); + }); + }); + }); + + describe("Display format", () => { + test("displays label with truncated address when label exists", async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-raindexes-filter-button"), + ); + + await waitFor(() => { + expect(screen.getByText(/Raindex One/)).toBeInTheDocument(); + expect(screen.getByText(/0x1234\.\.\.7890/)).toBeInTheDocument(); + }); + }); + + test("displays only truncated address when no label", async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [137], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-raindexes-filter-button"), + ); + + await waitFor(() => { + expect(screen.getByText(/0x3456\.\.\.9012/)).toBeInTheDocument(); + }); + }); + + test("displays network name next to each raindex", async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-raindexes-filter-button"), + ); + + await waitFor(() => { + expect(screen.getAllByText("Ethereum").length).toBeGreaterThan(0); + expect(screen.getByText("Polygon")).toBeInTheDocument(); + }); + }); + }); + + describe("Search and keyboard navigation", () => { + test("filters raindexes based on search term (label)", async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-raindexes-filter-button"), + ); + + const searchInput = screen.getByTestId("raindexes-filter-search"); + await fireEvent.input(searchInput, { target: { value: "One" } }); + + await waitFor(() => { + const options = screen.getAllByTestId( + "dropdown-raindexes-filter-option", + ); + expect(options).toHaveLength(1); + expect(screen.getByText(/Raindex One/)).toBeInTheDocument(); + }); + }); + + test("filters raindexes based on search term (address)", async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-raindexes-filter-button"), + ); + + const searchInput = screen.getByTestId("raindexes-filter-search"); + await fireEvent.input(searchInput, { target: { value: "0x1234" } }); + + await waitFor(() => { + const options = screen.getAllByTestId( + "dropdown-raindexes-filter-option", + ); + expect(options).toHaveLength(1); + }); + }); + + test('shows "No raindexes match your search" when search yields no results', async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-raindexes-filter-button"), + ); + + const searchInput = screen.getByTestId("raindexes-filter-search"); + await fireEvent.input(searchInput, { target: { value: "NONEXISTENT" } }); + + await waitFor(() => { + expect( + screen.getByText("No raindexes match your search"), + ).toBeInTheDocument(); + }); + }); + + test("keyboard navigation works correctly (ArrowDown/ArrowUp)", async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-raindexes-filter-button"), + ); + + const searchInput = screen.getByTestId("raindexes-filter-search"); + + await fireEvent.keyDown(searchInput, { key: "ArrowDown" }); + + await waitFor(() => { + const options = screen.getAllByTestId( + "dropdown-raindexes-filter-option", + ); + const secondItemLabel = options[1].closest("label"); + expect(secondItemLabel).toHaveClass("bg-blue-100", "dark:bg-blue-900"); + }); + + await fireEvent.keyDown(searchInput, { key: "ArrowUp" }); + + await waitFor(() => { + const options = screen.getAllByTestId( + "dropdown-raindexes-filter-option", + ); + const firstItemLabel = options[0].closest("label"); + expect(firstItemLabel).toHaveClass("bg-blue-100", "dark:bg-blue-900"); + }); + }); + + test("Enter key selects highlighted raindex", async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-raindexes-filter-button"), + ); + + const searchInput = screen.getByTestId("raindexes-filter-search"); + + await fireEvent.input(searchInput, { target: { value: "One" } }); + + await waitFor(() => { + const options = screen.getAllByTestId( + "dropdown-raindexes-filter-option", + ); + expect(options).toHaveLength(1); + }); + + await fireEvent.keyDown(searchInput, { key: "Enter" }); + + await waitFor(() => { + const selected = get(activeRaindexAddresses); + expect(selected).toContain( + "0x1234567890123456789012345678901234567890".toLowerCase(), + ); + }); + }); + + test("Escape key clears search", async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-raindexes-filter-button"), + ); + + const searchInput = screen.getByTestId( + "raindexes-filter-search", + ) as HTMLInputElement; + + await fireEvent.input(searchInput, { target: { value: "One" } }); + expect(searchInput.value).toBe("One"); + + await fireEvent.keyDown(searchInput, { key: "Escape" }); + + await waitFor(() => { + expect(searchInput.value).toBe(""); + }); + }); + }); }); diff --git a/packages/ui-components/src/__tests__/DropdownTokensFilter.test.ts b/packages/ui-components/src/__tests__/DropdownTokensFilter.test.ts index 6df8345f2e..ed0c818e65 100644 --- a/packages/ui-components/src/__tests__/DropdownTokensFilter.test.ts +++ b/packages/ui-components/src/__tests__/DropdownTokensFilter.test.ts @@ -1,503 +1,566 @@ -import { render, fireEvent, screen, waitFor } from '@testing-library/svelte'; -import { get, writable, readable } from 'svelte/store'; -import DropdownTokensFilter from '../lib/components/dropdown/DropdownTokensFilter.svelte'; -import { expect, test, describe, beforeEach } from 'vitest'; -import type { Address, RaindexVaultToken } from '@rainlanguage/raindex'; -import type { QueryObserverResult } from '@tanstack/svelte-query'; - -describe('DropdownTokensFilter', () => { - let activeTokens: ReturnType>; - let selectedTokens: Address[]; - - const mockTokensData = [ - { - id: 'TOKEN1', - address: '0x1234567890123456789012345678901234567890', - symbol: 'TOKEN1', - name: 'Test Token 1', - decimals: BigInt(18) - }, - { - id: 'TOKEN2', - address: '0x2345678901234567890123456789012345678901', - symbol: 'TOKEN2', - name: 'Test Token 2', - decimals: BigInt(18) - }, - { - id: 'ETH', - address: '0x3456789012345678901234567890123456789012', - symbol: 'ETH', - name: 'Ethereum', - decimals: BigInt(18) - } - ] as unknown as RaindexVaultToken[]; - - beforeEach(() => { - activeTokens = writable([]); - selectedTokens = []; - }); - - function createMockTokensQuery( - data: RaindexVaultToken[] | undefined = undefined, - isLoading = false, - isError = false, - error: Error | null = null - ) { - return readable({ - data, - isLoading, - isError, - error - } as QueryObserverResult); - } - - describe('Loading state', () => { - test('displays loading message when tokens are loading', async () => { - const tokensQuery = createMockTokensQuery(undefined, true); - - render(DropdownTokensFilter, { - props: { - tokensQuery, - activeTokens, - selectedTokens - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-tokens-filter-button')); - - await waitFor(() => { - expect(screen.getByText('Loading tokens...')).toBeInTheDocument(); - }); - }); - - test('displays custom loading message', async () => { - const tokensQuery = createMockTokensQuery(undefined, true); - const customLoadingMessage = 'Fetching token data...'; - - render(DropdownTokensFilter, { - props: { - tokensQuery, - activeTokens, - selectedTokens, - loadingMessage: customLoadingMessage - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-tokens-filter-button')); - - await waitFor(() => { - expect(screen.getByText(customLoadingMessage)).toBeInTheDocument(); - }); - }); - }); - - describe('Error state', () => { - test('displays error message when query fails', async () => { - const errorMessage = 'Network connection failed'; - const tokensQuery = createMockTokensQuery(undefined, false, true, new Error(errorMessage)); - - render(DropdownTokensFilter, { - props: { - tokensQuery, - activeTokens, - selectedTokens - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-tokens-filter-button')); - - await waitFor(() => { - expect(screen.getByText(`Cannot load tokens list: ${errorMessage}`)).toBeInTheDocument(); - }); - }); - - test('displays generic error message when error has no message', async () => { - const tokensQuery = createMockTokensQuery(undefined, false, true, new Error()); - - render(DropdownTokensFilter, { - props: { - tokensQuery, - activeTokens, - selectedTokens - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-tokens-filter-button')); - - await waitFor(() => { - expect(screen.getByText('Cannot load tokens list: Unknown error')).toBeInTheDocument(); - }); - }); - }); - - describe('Empty state', () => { - test('displays empty message when no tokens available', async () => { - const tokensQuery = createMockTokensQuery([]); - - render(DropdownTokensFilter, { - props: { - tokensQuery, - activeTokens, - selectedTokens - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-tokens-filter-button')); - - await waitFor(() => { - expect(screen.getByText('No tokens available')).toBeInTheDocument(); - }); - }); - - test('displays custom empty message', async () => { - const tokensQuery = createMockTokensQuery([]); - const customEmptyMessage = 'Token list is empty'; - - render(DropdownTokensFilter, { - props: { - tokensQuery, - activeTokens, - selectedTokens, - emptyMessage: customEmptyMessage - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-tokens-filter-button')); - - await waitFor(() => { - expect(screen.getByText(customEmptyMessage)).toBeInTheDocument(); - }); - }); - }); - - describe('Selected tokens display', () => { - test('displays "Select tokens" when no tokens are selected', () => { - const tokensQuery = createMockTokensQuery(mockTokensData); - - render(DropdownTokensFilter, { - props: { - tokensQuery, - activeTokens, - selectedTokens: [] - } - }); - - expect(screen.getByText('Select tokens')).toBeInTheDocument(); - }); - - test('displays "All tokens" when all tokens are selected', () => { - const tokensQuery = createMockTokensQuery(mockTokensData); - const allTokenAddresses = mockTokensData.map((t) => t.address).filter(Boolean) as Address[]; - - render(DropdownTokensFilter, { - props: { - tokensQuery, - activeTokens, - selectedTokens: allTokenAddresses - } - }); - - expect(screen.getByText('All tokens')).toBeInTheDocument(); - }); - - test('displays custom all label when all tokens are selected', () => { - const tokensQuery = createMockTokensQuery(mockTokensData); - const allTokenAddresses = mockTokensData.map((t) => t.address).filter(Boolean) as Address[]; - const customAllLabel = 'Everything selected'; - - render(DropdownTokensFilter, { - props: { - tokensQuery, - activeTokens, - selectedTokens: allTokenAddresses, - allLabel: customAllLabel - } - }); - - expect(screen.getByText(customAllLabel)).toBeInTheDocument(); - }); - - test('displays count when some tokens are selected', () => { - const tokensQuery = createMockTokensQuery(mockTokensData); - const selectedAddresses = [mockTokensData[0].address] as Address[]; - - render(DropdownTokensFilter, { - props: { - tokensQuery, - activeTokens, - selectedTokens: selectedAddresses - } - }); - - expect(screen.getByText('1 token')).toBeInTheDocument(); - }); - - test('displays plural count when multiple tokens are selected', () => { - const tokensQuery = createMockTokensQuery(mockTokensData); - const selectedAddresses = [mockTokensData[0].address, mockTokensData[1].address] as Address[]; - - render(DropdownTokensFilter, { - props: { - tokensQuery, - activeTokens, - selectedTokens: selectedAddresses - } - }); - - expect(screen.getByText('2 tokens')).toBeInTheDocument(); - }); - - test('updates selected tokens when checkbox is clicked', async () => { - const tokensQuery = createMockTokensQuery(mockTokensData); - - render(DropdownTokensFilter, { - props: { - tokensQuery, - activeTokens, - selectedTokens: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-tokens-filter-button')); - - const checkboxes = screen.getAllByTestId('dropdown-tokens-filter-option'); - await fireEvent.click(checkboxes[0]); - - await waitFor(() => { - expect(get(activeTokens)).toContain(mockTokensData[0].address); - }); - }); - - test('shows selected tokens as checked', async () => { - const tokensQuery = createMockTokensQuery(mockTokensData); - const selectedAddress = mockTokensData[0].address; - - render(DropdownTokensFilter, { - props: { - tokensQuery, - activeTokens, - selectedTokens: [selectedAddress] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-tokens-filter-button')); - - await waitFor(() => { - const checkboxes = screen.getAllByTestId('dropdown-tokens-filter-option'); - expect(checkboxes.length).toBeGreaterThan(0); - - // Check the text displayed shows that there's a selection - expect(screen.getByText('1 token')).toBeInTheDocument(); - }); - }); - }); - - describe('Search and selectedIndex behavior', () => { - test('filters tokens based on search term', async () => { - const tokensQuery = createMockTokensQuery(mockTokensData); - - render(DropdownTokensFilter, { - props: { - tokensQuery, - activeTokens, - selectedTokens: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-tokens-filter-button')); - - const searchInput = screen.getByTestId('tokens-filter-search'); - await fireEvent.input(searchInput, { target: { value: 'ETH' } }); - - await waitFor(() => { - const options = screen.getAllByTestId('dropdown-tokens-filter-option'); - expect(options).toHaveLength(1); - expect(screen.getByText('ETH')).toBeInTheDocument(); - }); - }); - - test('shows "No tokens match your search" when search yields no results', async () => { - const tokensQuery = createMockTokensQuery(mockTokensData); - - render(DropdownTokensFilter, { - props: { - tokensQuery, - activeTokens, - selectedTokens: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-tokens-filter-button')); - - const searchInput = screen.getByTestId('tokens-filter-search'); - await fireEvent.input(searchInput, { target: { value: 'NONEXISTENT' } }); - - await waitFor(() => { - expect(screen.getByText('No tokens match your search')).toBeInTheDocument(); - }); - }); - - test('selectedIndex transitions correctly from empty to non-empty results', async () => { - const tokensQuery = createMockTokensQuery(mockTokensData); - - render(DropdownTokensFilter, { - props: { - tokensQuery, - activeTokens, - selectedTokens: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-tokens-filter-button')); - - const searchInput = screen.getByTestId('tokens-filter-search'); - - // First search for something that doesn't exist - await fireEvent.input(searchInput, { target: { value: 'NONEXISTENT' } }); - - await waitFor(() => { - expect(screen.getByText('No tokens match your search')).toBeInTheDocument(); - }); - - // Then search for something that exists - first item should be highlighted - await fireEvent.input(searchInput, { target: { value: 'ETH' } }); - - await waitFor(() => { - const options = screen.getAllByTestId('dropdown-tokens-filter-option'); - expect(options).toHaveLength(1); - // Check if the parent label has the selected styling - const parentLabel = options[0].closest('label'); - expect(parentLabel).toHaveClass('bg-blue-100', 'dark:bg-blue-900'); - }); - }); - - test('selectedIndex transitions correctly from non-empty to empty results', async () => { - const tokensQuery = createMockTokensQuery(mockTokensData); - - render(DropdownTokensFilter, { - props: { - tokensQuery, - activeTokens, - selectedTokens: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-tokens-filter-button')); - - const searchInput = screen.getByTestId('tokens-filter-search'); - - // First search for something that exists - await fireEvent.input(searchInput, { target: { value: 'TOKEN' } }); - - await waitFor(() => { - const options = screen.getAllByTestId('dropdown-tokens-filter-option'); - expect(options.length).toBeGreaterThan(0); - }); - - // Then search for something that doesn't exist - await fireEvent.input(searchInput, { target: { value: 'NONEXISTENT' } }); - - await waitFor(() => { - expect(screen.getByText('No tokens match your search')).toBeInTheDocument(); - // No options should be present - expect(screen.queryAllByTestId('dropdown-tokens-filter-option')).toHaveLength(0); - }); - }); - - test('keyboard navigation works correctly', async () => { - const tokensQuery = createMockTokensQuery(mockTokensData); - - render(DropdownTokensFilter, { - props: { - tokensQuery, - activeTokens, - selectedTokens: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-tokens-filter-button')); - - const searchInput = screen.getByTestId('tokens-filter-search'); - - // Arrow down should move selection - await fireEvent.keyDown(searchInput, { key: 'ArrowDown' }); - - await waitFor(() => { - const options = screen.getAllByTestId('dropdown-tokens-filter-option'); - // Check if second item's parent label is highlighted (index 1) - const secondItemLabel = options[1].closest('label'); - expect(secondItemLabel).toHaveClass('bg-blue-100', 'dark:bg-blue-900'); - }); - - // Arrow up should move selection back - await fireEvent.keyDown(searchInput, { key: 'ArrowUp' }); - - await waitFor(() => { - const options = screen.getAllByTestId('dropdown-tokens-filter-option'); - // Check if first item's parent label is highlighted again (index 0) - const firstItemLabel = options[0].closest('label'); - expect(firstItemLabel).toHaveClass('bg-blue-100', 'dark:bg-blue-900'); - }); - }); - - test('Enter key selects highlighted token', async () => { - const tokensQuery = createMockTokensQuery(mockTokensData); - - render(DropdownTokensFilter, { - props: { - tokensQuery, - activeTokens, - selectedTokens: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-tokens-filter-button')); - - const searchInput = screen.getByTestId('tokens-filter-search'); - - // Search for a specific token - await fireEvent.input(searchInput, { target: { value: 'ETH' } }); - - await waitFor(() => { - const options = screen.getAllByTestId('dropdown-tokens-filter-option'); - expect(options).toHaveLength(1); - }); - - // Press Enter to select the highlighted token - await fireEvent.keyDown(searchInput, { key: 'Enter' }); - - await waitFor(() => { - const ethToken = mockTokensData.find((t) => t.symbol === 'ETH'); - expect(get(activeTokens)).toContain(ethToken?.address); - }); - }); - - test('Escape key clears search', async () => { - const tokensQuery = createMockTokensQuery(mockTokensData); - - render(DropdownTokensFilter, { - props: { - tokensQuery, - activeTokens, - selectedTokens: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-tokens-filter-button')); - - const searchInput = screen.getByTestId('tokens-filter-search') as HTMLInputElement; - - // Enter search term - await fireEvent.input(searchInput, { target: { value: 'ETH' } }); - expect(searchInput.value).toBe('ETH'); - - // Press Escape to clear - await fireEvent.keyDown(searchInput, { key: 'Escape' }); - - await waitFor(() => { - expect(searchInput.value).toBe(''); - }); - }); - }); +import { render, fireEvent, screen, waitFor } from "@testing-library/svelte"; +import { get, writable, readable } from "svelte/store"; +import DropdownTokensFilter from "../lib/components/dropdown/DropdownTokensFilter.svelte"; +import { expect, test, describe, beforeEach } from "vitest"; +import type { Address, RaindexVaultToken } from "@rainlanguage/raindex"; +import type { QueryObserverResult } from "@tanstack/svelte-query"; + +describe("DropdownTokensFilter", () => { + let activeTokens: ReturnType>; + let selectedTokens: Address[]; + + const mockTokensData = [ + { + id: "TOKEN1", + address: "0x1234567890123456789012345678901234567890", + symbol: "TOKEN1", + name: "Test Token 1", + decimals: BigInt(18), + }, + { + id: "TOKEN2", + address: "0x2345678901234567890123456789012345678901", + symbol: "TOKEN2", + name: "Test Token 2", + decimals: BigInt(18), + }, + { + id: "ETH", + address: "0x3456789012345678901234567890123456789012", + symbol: "ETH", + name: "Ethereum", + decimals: BigInt(18), + }, + ] as unknown as RaindexVaultToken[]; + + beforeEach(() => { + activeTokens = writable([]); + selectedTokens = []; + }); + + function createMockTokensQuery( + data: RaindexVaultToken[] | undefined = undefined, + isLoading = false, + isError = false, + error: Error | null = null, + ) { + return readable({ + data, + isLoading, + isError, + error, + } as QueryObserverResult); + } + + describe("Loading state", () => { + test("displays loading message when tokens are loading", async () => { + const tokensQuery = createMockTokensQuery(undefined, true); + + render(DropdownTokensFilter, { + props: { + tokensQuery, + activeTokens, + selectedTokens, + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-tokens-filter-button"), + ); + + await waitFor(() => { + expect(screen.getByText("Loading tokens...")).toBeInTheDocument(); + }); + }); + + test("displays custom loading message", async () => { + const tokensQuery = createMockTokensQuery(undefined, true); + const customLoadingMessage = "Fetching token data..."; + + render(DropdownTokensFilter, { + props: { + tokensQuery, + activeTokens, + selectedTokens, + loadingMessage: customLoadingMessage, + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-tokens-filter-button"), + ); + + await waitFor(() => { + expect(screen.getByText(customLoadingMessage)).toBeInTheDocument(); + }); + }); + }); + + describe("Error state", () => { + test("displays error message when query fails", async () => { + const errorMessage = "Network connection failed"; + const tokensQuery = createMockTokensQuery( + undefined, + false, + true, + new Error(errorMessage), + ); + + render(DropdownTokensFilter, { + props: { + tokensQuery, + activeTokens, + selectedTokens, + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-tokens-filter-button"), + ); + + await waitFor(() => { + expect( + screen.getByText(`Cannot load tokens list: ${errorMessage}`), + ).toBeInTheDocument(); + }); + }); + + test("displays generic error message when error has no message", async () => { + const tokensQuery = createMockTokensQuery( + undefined, + false, + true, + new Error(), + ); + + render(DropdownTokensFilter, { + props: { + tokensQuery, + activeTokens, + selectedTokens, + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-tokens-filter-button"), + ); + + await waitFor(() => { + expect( + screen.getByText("Cannot load tokens list: Unknown error"), + ).toBeInTheDocument(); + }); + }); + }); + + describe("Empty state", () => { + test("displays empty message when no tokens available", async () => { + const tokensQuery = createMockTokensQuery([]); + + render(DropdownTokensFilter, { + props: { + tokensQuery, + activeTokens, + selectedTokens, + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-tokens-filter-button"), + ); + + await waitFor(() => { + expect(screen.getByText("No tokens available")).toBeInTheDocument(); + }); + }); + + test("displays custom empty message", async () => { + const tokensQuery = createMockTokensQuery([]); + const customEmptyMessage = "Token list is empty"; + + render(DropdownTokensFilter, { + props: { + tokensQuery, + activeTokens, + selectedTokens, + emptyMessage: customEmptyMessage, + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-tokens-filter-button"), + ); + + await waitFor(() => { + expect(screen.getByText(customEmptyMessage)).toBeInTheDocument(); + }); + }); + }); + + describe("Selected tokens display", () => { + test('displays "Select tokens" when no tokens are selected', () => { + const tokensQuery = createMockTokensQuery(mockTokensData); + + render(DropdownTokensFilter, { + props: { + tokensQuery, + activeTokens, + selectedTokens: [], + }, + }); + + expect(screen.getByText("Select tokens")).toBeInTheDocument(); + }); + + test('displays "All tokens" when all tokens are selected', () => { + const tokensQuery = createMockTokensQuery(mockTokensData); + const allTokenAddresses = mockTokensData + .map((t) => t.address) + .filter(Boolean) as Address[]; + + render(DropdownTokensFilter, { + props: { + tokensQuery, + activeTokens, + selectedTokens: allTokenAddresses, + }, + }); + + expect(screen.getByText("All tokens")).toBeInTheDocument(); + }); + + test("displays custom all label when all tokens are selected", () => { + const tokensQuery = createMockTokensQuery(mockTokensData); + const allTokenAddresses = mockTokensData + .map((t) => t.address) + .filter(Boolean) as Address[]; + const customAllLabel = "Everything selected"; + + render(DropdownTokensFilter, { + props: { + tokensQuery, + activeTokens, + selectedTokens: allTokenAddresses, + allLabel: customAllLabel, + }, + }); + + expect(screen.getByText(customAllLabel)).toBeInTheDocument(); + }); + + test("displays count when some tokens are selected", () => { + const tokensQuery = createMockTokensQuery(mockTokensData); + const selectedAddresses = [mockTokensData[0].address] as Address[]; + + render(DropdownTokensFilter, { + props: { + tokensQuery, + activeTokens, + selectedTokens: selectedAddresses, + }, + }); + + expect(screen.getByText("1 token")).toBeInTheDocument(); + }); + + test("displays plural count when multiple tokens are selected", () => { + const tokensQuery = createMockTokensQuery(mockTokensData); + const selectedAddresses = [ + mockTokensData[0].address, + mockTokensData[1].address, + ] as Address[]; + + render(DropdownTokensFilter, { + props: { + tokensQuery, + activeTokens, + selectedTokens: selectedAddresses, + }, + }); + + expect(screen.getByText("2 tokens")).toBeInTheDocument(); + }); + + test("updates selected tokens when checkbox is clicked", async () => { + const tokensQuery = createMockTokensQuery(mockTokensData); + + render(DropdownTokensFilter, { + props: { + tokensQuery, + activeTokens, + selectedTokens: [], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-tokens-filter-button"), + ); + + const checkboxes = screen.getAllByTestId("dropdown-tokens-filter-option"); + await fireEvent.click(checkboxes[0]); + + await waitFor(() => { + expect(get(activeTokens)).toContain(mockTokensData[0].address); + }); + }); + + test("shows selected tokens as checked", async () => { + const tokensQuery = createMockTokensQuery(mockTokensData); + const selectedAddress = mockTokensData[0].address; + + render(DropdownTokensFilter, { + props: { + tokensQuery, + activeTokens, + selectedTokens: [selectedAddress], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-tokens-filter-button"), + ); + + await waitFor(() => { + const checkboxes = screen.getAllByTestId( + "dropdown-tokens-filter-option", + ); + expect(checkboxes.length).toBeGreaterThan(0); + + // Check the text displayed shows that there's a selection + expect(screen.getByText("1 token")).toBeInTheDocument(); + }); + }); + }); + + describe("Search and selectedIndex behavior", () => { + test("filters tokens based on search term", async () => { + const tokensQuery = createMockTokensQuery(mockTokensData); + + render(DropdownTokensFilter, { + props: { + tokensQuery, + activeTokens, + selectedTokens: [], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-tokens-filter-button"), + ); + + const searchInput = screen.getByTestId("tokens-filter-search"); + await fireEvent.input(searchInput, { target: { value: "ETH" } }); + + await waitFor(() => { + const options = screen.getAllByTestId("dropdown-tokens-filter-option"); + expect(options).toHaveLength(1); + expect(screen.getByText("ETH")).toBeInTheDocument(); + }); + }); + + test('shows "No tokens match your search" when search yields no results', async () => { + const tokensQuery = createMockTokensQuery(mockTokensData); + + render(DropdownTokensFilter, { + props: { + tokensQuery, + activeTokens, + selectedTokens: [], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-tokens-filter-button"), + ); + + const searchInput = screen.getByTestId("tokens-filter-search"); + await fireEvent.input(searchInput, { target: { value: "NONEXISTENT" } }); + + await waitFor(() => { + expect( + screen.getByText("No tokens match your search"), + ).toBeInTheDocument(); + }); + }); + + test("selectedIndex transitions correctly from empty to non-empty results", async () => { + const tokensQuery = createMockTokensQuery(mockTokensData); + + render(DropdownTokensFilter, { + props: { + tokensQuery, + activeTokens, + selectedTokens: [], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-tokens-filter-button"), + ); + + const searchInput = screen.getByTestId("tokens-filter-search"); + + // First search for something that doesn't exist + await fireEvent.input(searchInput, { target: { value: "NONEXISTENT" } }); + + await waitFor(() => { + expect( + screen.getByText("No tokens match your search"), + ).toBeInTheDocument(); + }); + + // Then search for something that exists - first item should be highlighted + await fireEvent.input(searchInput, { target: { value: "ETH" } }); + + await waitFor(() => { + const options = screen.getAllByTestId("dropdown-tokens-filter-option"); + expect(options).toHaveLength(1); + // Check if the parent label has the selected styling + const parentLabel = options[0].closest("label"); + expect(parentLabel).toHaveClass("bg-blue-100", "dark:bg-blue-900"); + }); + }); + + test("selectedIndex transitions correctly from non-empty to empty results", async () => { + const tokensQuery = createMockTokensQuery(mockTokensData); + + render(DropdownTokensFilter, { + props: { + tokensQuery, + activeTokens, + selectedTokens: [], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-tokens-filter-button"), + ); + + const searchInput = screen.getByTestId("tokens-filter-search"); + + // First search for something that exists + await fireEvent.input(searchInput, { target: { value: "TOKEN" } }); + + await waitFor(() => { + const options = screen.getAllByTestId("dropdown-tokens-filter-option"); + expect(options.length).toBeGreaterThan(0); + }); + + // Then search for something that doesn't exist + await fireEvent.input(searchInput, { target: { value: "NONEXISTENT" } }); + + await waitFor(() => { + expect( + screen.getByText("No tokens match your search"), + ).toBeInTheDocument(); + // No options should be present + expect( + screen.queryAllByTestId("dropdown-tokens-filter-option"), + ).toHaveLength(0); + }); + }); + + test("keyboard navigation works correctly", async () => { + const tokensQuery = createMockTokensQuery(mockTokensData); + + render(DropdownTokensFilter, { + props: { + tokensQuery, + activeTokens, + selectedTokens: [], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-tokens-filter-button"), + ); + + const searchInput = screen.getByTestId("tokens-filter-search"); + + // Arrow down should move selection + await fireEvent.keyDown(searchInput, { key: "ArrowDown" }); + + await waitFor(() => { + const options = screen.getAllByTestId("dropdown-tokens-filter-option"); + // Check if second item's parent label is highlighted (index 1) + const secondItemLabel = options[1].closest("label"); + expect(secondItemLabel).toHaveClass("bg-blue-100", "dark:bg-blue-900"); + }); + + // Arrow up should move selection back + await fireEvent.keyDown(searchInput, { key: "ArrowUp" }); + + await waitFor(() => { + const options = screen.getAllByTestId("dropdown-tokens-filter-option"); + // Check if first item's parent label is highlighted again (index 0) + const firstItemLabel = options[0].closest("label"); + expect(firstItemLabel).toHaveClass("bg-blue-100", "dark:bg-blue-900"); + }); + }); + + test("Enter key selects highlighted token", async () => { + const tokensQuery = createMockTokensQuery(mockTokensData); + + render(DropdownTokensFilter, { + props: { + tokensQuery, + activeTokens, + selectedTokens: [], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-tokens-filter-button"), + ); + + const searchInput = screen.getByTestId("tokens-filter-search"); + + // Search for a specific token + await fireEvent.input(searchInput, { target: { value: "ETH" } }); + + await waitFor(() => { + const options = screen.getAllByTestId("dropdown-tokens-filter-option"); + expect(options).toHaveLength(1); + }); + + // Press Enter to select the highlighted token + await fireEvent.keyDown(searchInput, { key: "Enter" }); + + await waitFor(() => { + const ethToken = mockTokensData.find((t) => t.symbol === "ETH"); + expect(get(activeTokens)).toContain(ethToken?.address); + }); + }); + + test("Escape key clears search", async () => { + const tokensQuery = createMockTokensQuery(mockTokensData); + + render(DropdownTokensFilter, { + props: { + tokensQuery, + activeTokens, + selectedTokens: [], + }, + }); + + await fireEvent.click( + screen.getByTestId("dropdown-tokens-filter-button"), + ); + + const searchInput = screen.getByTestId( + "tokens-filter-search", + ) as HTMLInputElement; + + // Enter search term + await fireEvent.input(searchInput, { target: { value: "ETH" } }); + expect(searchInput.value).toBe("ETH"); + + // Press Escape to clear + await fireEvent.keyDown(searchInput, { key: "Escape" }); + + await waitFor(() => { + expect(searchInput.value).toBe(""); + }); + }); + }); }); diff --git a/packages/ui-components/src/__tests__/EditableSpan.test.ts b/packages/ui-components/src/__tests__/EditableSpan.test.ts index 1265ab3ce1..49e549369c 100644 --- a/packages/ui-components/src/__tests__/EditableSpan.test.ts +++ b/packages/ui-components/src/__tests__/EditableSpan.test.ts @@ -1,19 +1,19 @@ -import { describe, test, expect } from 'vitest'; -import { render } from '@testing-library/svelte'; -import EditableSpan from '../lib/components/EditableSpan.svelte'; +import { describe, test, expect } from "vitest"; +import { render } from "@testing-library/svelte"; +import EditableSpan from "../lib/components/EditableSpan.svelte"; -describe('Editable Span', () => { - test('should show the correct value', async () => { - const screen = render(EditableSpan, { - displayValue: '123' - }); +describe("Editable Span", () => { + test("should show the correct value", async () => { + const screen = render(EditableSpan, { + displayValue: "123", + }); - expect(screen.getByText('Block:')).toBeInTheDocument(); - expect(screen.getByTestId('editableSpan')).toHaveTextContent('123'); + expect(screen.getByText("Block:")).toBeInTheDocument(); + expect(screen.getByTestId("editableSpan")).toHaveTextContent("123"); - screen.getByTestId('editableSpan').click(); - screen - .getByTestId('editableSpan') - .dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' })); - }); + screen.getByTestId("editableSpan").click(); + screen + .getByTestId("editableSpan") + .dispatchEvent(new KeyboardEvent("keydown", { key: "Enter" })); + }); }); diff --git a/packages/ui-components/src/__tests__/FieldDefinitionInput.test.ts b/packages/ui-components/src/__tests__/FieldDefinitionInput.test.ts index 2f520d8219..2406e587ac 100644 --- a/packages/ui-components/src/__tests__/FieldDefinitionInput.test.ts +++ b/packages/ui-components/src/__tests__/FieldDefinitionInput.test.ts @@ -1,154 +1,170 @@ -import { render, fireEvent } from '@testing-library/svelte'; -import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; -import FieldDefinitionInput from '../lib/components/deployment/FieldDefinitionInput.svelte'; -import { RaindexOrderBuilder } from '@rainlanguage/raindex'; -import userEvent from '@testing-library/user-event'; -import { useRaindexOrderBuilder } from '$lib/hooks/useRaindexOrderBuilder'; -import type { ComponentProps } from 'svelte'; +import { render, fireEvent } from "@testing-library/svelte"; +import { describe, it, expect, vi, beforeEach, type Mock } from "vitest"; +import FieldDefinitionInput from "../lib/components/deployment/FieldDefinitionInput.svelte"; +import { RaindexOrderBuilder } from "@rainlanguage/raindex"; +import userEvent from "@testing-library/user-event"; +import { useRaindexOrderBuilder } from "$lib/hooks/useRaindexOrderBuilder"; +import type { ComponentProps } from "svelte"; type FieldDefinitionInputProps = ComponentProps; -vi.mock('@rainlanguage/raindex', () => ({ - RaindexOrderBuilder: vi.fn() +vi.mock("@rainlanguage/raindex", () => ({ + RaindexOrderBuilder: vi.fn(), })); -vi.mock('$lib/hooks/useRaindexOrderBuilder', () => ({ - useRaindexOrderBuilder: vi.fn() +vi.mock("$lib/hooks/useRaindexOrderBuilder", () => ({ + useRaindexOrderBuilder: vi.fn(), })); -describe('FieldDefinitionInput', () => { - let builderInstance: RaindexOrderBuilder; - let mockStateUpdateCallback: Mock; - - const mockFieldDefinition = { - binding: 'test-binding', - name: 'Test Field', - description: 'Test Description', - presets: [ - { id: 'preset1', name: 'Preset 1', value: 'value1' }, - { id: 'preset2', name: 'Preset 2', value: 'value2' } - ] - }; - - beforeEach(() => { - mockStateUpdateCallback = vi.fn(); - - builderInstance = { - getFieldValue: vi.fn().mockReturnValue({}), - setFieldValue: vi.fn().mockImplementation(() => { - mockStateUpdateCallback(); - }) - } as unknown as RaindexOrderBuilder; - - (useRaindexOrderBuilder as Mock).mockReturnValue(builderInstance); - }); - - it('renders field name and description', () => { - const { getByText } = render(FieldDefinitionInput, { - props: { - fieldDefinition: mockFieldDefinition - } as unknown as FieldDefinitionInputProps - }); - - expect(getByText('Test Field')).toBeTruthy(); - expect(getByText('Test Description')).toBeTruthy(); - }); - - it('renders preset buttons', () => { - const { getByText } = render(FieldDefinitionInput, { - props: { - fieldDefinition: mockFieldDefinition - } as unknown as FieldDefinitionInputProps - }); - - expect(getByText('Preset 1')).toBeTruthy(); - expect(getByText('Preset 2')).toBeTruthy(); - }); - - it('handles preset button clicks and triggers state update', async () => { - const { getByText } = render(FieldDefinitionInput, { - props: { - fieldDefinition: mockFieldDefinition - } as unknown as FieldDefinitionInputProps - }); - - await fireEvent.click(getByText('Preset 1')); - - expect(builderInstance.setFieldValue).toHaveBeenCalledWith('test-binding', 'value1'); - expect(mockStateUpdateCallback).toHaveBeenCalled(); - }); - - it('handles custom input changes and triggers state update', async () => { - const { getByPlaceholderText } = render(FieldDefinitionInput, { - props: { - fieldDefinition: { ...mockFieldDefinition, showCustomField: true } - } as unknown as FieldDefinitionInputProps - }); - - const input = getByPlaceholderText('Enter custom value'); - await fireEvent.input(input, { target: { value: 'custom value' } }); - - expect(builderInstance.setFieldValue).toHaveBeenCalledWith('test-binding', 'custom value'); - expect(mockStateUpdateCallback).toHaveBeenCalled(); - }); - - it('does not show Custom button for is-fast-exit binding', () => { - const fastExitFieldDef = { - ...mockFieldDefinition, - binding: 'is-fast-exit' - }; - - const { queryByText } = render(FieldDefinitionInput, { - props: { - fieldDefinition: fastExitFieldDef - } as unknown as FieldDefinitionInputProps - }); - - expect(queryByText('Custom')).toBeNull(); - }); - - it('renders default value if it exists', async () => { - const { getByPlaceholderText } = render(FieldDefinitionInput, { - props: { - fieldDefinition: { - ...mockFieldDefinition, - default: 'default value', - showCustomField: true - } - } as unknown as FieldDefinitionInputProps - }); - - const input = getByPlaceholderText('Enter custom value') as HTMLInputElement; - expect(input.value).toBe('default value'); - - await userEvent.type(input, '@'); - - expect(builderInstance.setFieldValue).toHaveBeenCalledWith('test-binding', 'default value@'); - }); - it('renders selected value instead of default value', async () => { - (builderInstance.getFieldValue as Mock).mockReturnValue({ - value: { - binding: 'test-binding', - value: 'preset1', - is_preset: false - } - }); - - const { getByPlaceholderText } = render(FieldDefinitionInput, { - props: { - fieldDefinition: { - ...mockFieldDefinition, - default: 'default value', - showCustomField: true - } - } as unknown as FieldDefinitionInputProps - }); - - const input = getByPlaceholderText('Enter custom value') as HTMLInputElement; - expect(input.value).toBe('preset1'); - - await userEvent.type(input, '@'); - - expect(builderInstance.setFieldValue).toHaveBeenCalledWith('test-binding', 'preset1@'); - }); +describe("FieldDefinitionInput", () => { + let builderInstance: RaindexOrderBuilder; + let mockStateUpdateCallback: Mock; + + const mockFieldDefinition = { + binding: "test-binding", + name: "Test Field", + description: "Test Description", + presets: [ + { id: "preset1", name: "Preset 1", value: "value1" }, + { id: "preset2", name: "Preset 2", value: "value2" }, + ], + }; + + beforeEach(() => { + mockStateUpdateCallback = vi.fn(); + + builderInstance = { + getFieldValue: vi.fn().mockReturnValue({}), + setFieldValue: vi.fn().mockImplementation(() => { + mockStateUpdateCallback(); + }), + } as unknown as RaindexOrderBuilder; + + (useRaindexOrderBuilder as Mock).mockReturnValue(builderInstance); + }); + + it("renders field name and description", () => { + const { getByText } = render(FieldDefinitionInput, { + props: { + fieldDefinition: mockFieldDefinition, + } as unknown as FieldDefinitionInputProps, + }); + + expect(getByText("Test Field")).toBeTruthy(); + expect(getByText("Test Description")).toBeTruthy(); + }); + + it("renders preset buttons", () => { + const { getByText } = render(FieldDefinitionInput, { + props: { + fieldDefinition: mockFieldDefinition, + } as unknown as FieldDefinitionInputProps, + }); + + expect(getByText("Preset 1")).toBeTruthy(); + expect(getByText("Preset 2")).toBeTruthy(); + }); + + it("handles preset button clicks and triggers state update", async () => { + const { getByText } = render(FieldDefinitionInput, { + props: { + fieldDefinition: mockFieldDefinition, + } as unknown as FieldDefinitionInputProps, + }); + + await fireEvent.click(getByText("Preset 1")); + + expect(builderInstance.setFieldValue).toHaveBeenCalledWith( + "test-binding", + "value1", + ); + expect(mockStateUpdateCallback).toHaveBeenCalled(); + }); + + it("handles custom input changes and triggers state update", async () => { + const { getByPlaceholderText } = render(FieldDefinitionInput, { + props: { + fieldDefinition: { ...mockFieldDefinition, showCustomField: true }, + } as unknown as FieldDefinitionInputProps, + }); + + const input = getByPlaceholderText("Enter custom value"); + await fireEvent.input(input, { target: { value: "custom value" } }); + + expect(builderInstance.setFieldValue).toHaveBeenCalledWith( + "test-binding", + "custom value", + ); + expect(mockStateUpdateCallback).toHaveBeenCalled(); + }); + + it("does not show Custom button for is-fast-exit binding", () => { + const fastExitFieldDef = { + ...mockFieldDefinition, + binding: "is-fast-exit", + }; + + const { queryByText } = render(FieldDefinitionInput, { + props: { + fieldDefinition: fastExitFieldDef, + } as unknown as FieldDefinitionInputProps, + }); + + expect(queryByText("Custom")).toBeNull(); + }); + + it("renders default value if it exists", async () => { + const { getByPlaceholderText } = render(FieldDefinitionInput, { + props: { + fieldDefinition: { + ...mockFieldDefinition, + default: "default value", + showCustomField: true, + }, + } as unknown as FieldDefinitionInputProps, + }); + + const input = getByPlaceholderText( + "Enter custom value", + ) as HTMLInputElement; + expect(input.value).toBe("default value"); + + await userEvent.type(input, "@"); + + expect(builderInstance.setFieldValue).toHaveBeenCalledWith( + "test-binding", + "default value@", + ); + }); + it("renders selected value instead of default value", async () => { + (builderInstance.getFieldValue as Mock).mockReturnValue({ + value: { + binding: "test-binding", + value: "preset1", + is_preset: false, + }, + }); + + const { getByPlaceholderText } = render(FieldDefinitionInput, { + props: { + fieldDefinition: { + ...mockFieldDefinition, + default: "default value", + showCustomField: true, + }, + } as unknown as FieldDefinitionInputProps, + }); + + const input = getByPlaceholderText( + "Enter custom value", + ) as HTMLInputElement; + expect(input.value).toBe("preset1"); + + await userEvent.type(input, "@"); + + expect(builderInstance.setFieldValue).toHaveBeenCalledWith( + "test-binding", + "preset1@", + ); + }); }); diff --git a/packages/ui-components/src/__tests__/FixedBottomTransaction.test.ts b/packages/ui-components/src/__tests__/FixedBottomTransaction.test.ts index 5b57af3bd5..f74022dcc1 100644 --- a/packages/ui-components/src/__tests__/FixedBottomTransaction.test.ts +++ b/packages/ui-components/src/__tests__/FixedBottomTransaction.test.ts @@ -1,384 +1,412 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import { render, screen, waitFor, fireEvent } from '@testing-library/svelte'; -import FixedBottomTransaction from '../lib/components/transactions/FixedBottomTransaction.svelte'; -import { TransactionManager } from '../lib/providers/transactions/TransactionManager'; -import { writable } from 'svelte/store'; -import type { Transaction, TransactionStoreState } from '../lib/models/Transaction'; +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { render, screen, waitFor, fireEvent } from "@testing-library/svelte"; +import FixedBottomTransaction from "../lib/components/transactions/FixedBottomTransaction.svelte"; +import { TransactionManager } from "../lib/providers/transactions/TransactionManager"; +import { writable } from "svelte/store"; +import type { + Transaction, + TransactionStoreState, +} from "../lib/models/Transaction"; import { - TransactionStatusMessage, - TransactionName, - TransactionStoreErrorMessage -} from '../lib/types/transaction'; -import { useTransactions } from '../lib/providers/transactions/useTransactions'; -import { getStatusEmoji } from '$lib/components/transactions/getStatusEmoji'; - -vi.mock('../lib/providers/transactions/useTransactions', () => ({ - useTransactions: vi.fn() + TransactionStatusMessage, + TransactionName, + TransactionStoreErrorMessage, +} from "../lib/types/transaction"; +import { useTransactions } from "../lib/providers/transactions/useTransactions"; +import { getStatusEmoji } from "$lib/components/transactions/getStatusEmoji"; + +vi.mock("../lib/providers/transactions/useTransactions", () => ({ + useTransactions: vi.fn(), })); -describe('FixedBottomTransaction', () => { - let mockTransactionManager: TransactionManager; - let mockTransactionsStore: ReturnType>; - - beforeEach(() => { - vi.clearAllMocks(); - - mockTransactionsStore = writable([]); - - mockTransactionManager = { - transactions: vi.fn().mockReturnValue(mockTransactionsStore) - } as unknown as TransactionManager; - - vi.mocked(useTransactions).mockReturnValue({ - manager: mockTransactionManager, - transactions: mockTransactionsStore - }); - }); - - it('should not render anything when there are no transactions', () => { - const { container } = render(FixedBottomTransaction); - expect(container.innerHTML).toBe(''); - }); - - it('should render the latest transaction when transactions exist', () => { - const mockTransactions = [ - { - state: writable({ - status: TransactionStatusMessage.IDLE, - name: TransactionName.REMOVAL, - links: [] - }) - }, - { - state: writable({ - status: TransactionStatusMessage.SUCCESS, - name: TransactionName.REMOVAL, - links: [ - { - label: 'View on Explorer', - link: 'https://etherscan.io/tx/0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890' - } - ] - }) - } - ] as unknown as Transaction[]; - - mockTransactionsStore.set(mockTransactions); - - render(FixedBottomTransaction); - - // Should render the latest transaction (second one) - expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); - expect(screen.getByText(TransactionStatusMessage.SUCCESS)).toBeInTheDocument(); - expect(screen.getByText(getStatusEmoji(TransactionStatusMessage.SUCCESS))).toBeInTheDocument(); - expect(screen.getByText('View on Explorer')).toBeInTheDocument(); - }); - - it('should have proper mobile-only styling with fixed positioning', () => { - const mockTransactions = [ - { - state: writable({ - status: TransactionStatusMessage.PENDING_RECEIPT, - name: TransactionName.REMOVAL, - links: [] - }) - } - ] as unknown as Transaction[]; - - mockTransactionsStore.set(mockTransactions); - - const { container } = render(FixedBottomTransaction); - - const transactionElement = container.querySelector('div'); - expect(transactionElement).toHaveClass( - 'fixed', - 'bottom-0', - 'left-0', - 'right-0', - 'z-40', - 'lg:hidden' - ); - }); - - it('should display transaction details correctly', () => { - const mockTransactions = [ - { - state: writable({ - status: TransactionStatusMessage.PENDING_RECEIPT, - name: TransactionName.REMOVAL, - links: [ - { - label: 'Etherscan', - link: 'https://etherscan.io/tx/0x123' - }, - { - label: 'Block Explorer', - link: 'https://explorer.com/tx/0x456' - } - ], - errorDetails: undefined - }) - } - ] as unknown as Transaction[]; - - mockTransactionsStore.set(mockTransactions); - - render(FixedBottomTransaction); - - expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); - expect(screen.getByText(TransactionStatusMessage.PENDING_RECEIPT)).toBeInTheDocument(); - expect( - screen.getByText(getStatusEmoji(TransactionStatusMessage.PENDING_RECEIPT)) - ).toBeInTheDocument(); - expect(screen.getByText('Etherscan')).toBeInTheDocument(); - expect(screen.getByText('Block Explorer')).toBeInTheDocument(); - }); - - it('should display error details when present', () => { - const mockTransactions = [ - { - state: writable({ - status: TransactionStatusMessage.ERROR, - name: TransactionName.REMOVAL, - links: [], - errorDetails: 'Transaction failed due to insufficient gas' as TransactionStoreErrorMessage - }) - } - ] as unknown as Transaction[]; - - mockTransactionsStore.set(mockTransactions); - - render(FixedBottomTransaction); - - expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); - expect(screen.getByText('Transaction failed due to insufficient gas')).toBeInTheDocument(); - expect(screen.getByText(getStatusEmoji(TransactionStatusMessage.ERROR))).toBeInTheDocument(); - }); - - it('should limit links to maximum of 2', () => { - const mockTransactions = [ - { - state: writable({ - status: TransactionStatusMessage.SUCCESS, - name: TransactionName.REMOVAL, - links: [ - { label: 'Link 1', link: 'https://example1.com' }, - { label: 'Link 2', link: 'https://example2.com' }, - { label: 'Link 3', link: 'https://example3.com' }, - { label: 'Link 4', link: 'https://example4.com' } - ] - }) - } - ] as unknown as Transaction[]; - - mockTransactionsStore.set(mockTransactions); - - render(FixedBottomTransaction); - - expect(screen.getByText('Link 1')).toBeInTheDocument(); - expect(screen.getByText('Link 2')).toBeInTheDocument(); - expect(screen.queryByText('Link 3')).not.toBeInTheDocument(); - expect(screen.queryByText('Link 4')).not.toBeInTheDocument(); - }); - - it('should dismiss transaction when close button is clicked', async () => { - const mockTransactions = [ - { - state: writable({ - status: TransactionStatusMessage.SUCCESS, - name: TransactionName.REMOVAL, - links: [] - }) - } - ] as unknown as Transaction[]; - - mockTransactionsStore.set(mockTransactions); - - const { container } = render(FixedBottomTransaction); - - expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); - - const closeButton = screen.getByRole('button', { name: 'Dismiss transaction' }); - expect(closeButton).toBeInTheDocument(); - - await fireEvent.click(closeButton); - - await waitFor(() => { - expect(container.innerHTML).toBe(''); - }); - }); - - it('should reset dismiss state when new transaction appears', async () => { - const { container } = render(FixedBottomTransaction); - - // Start with one transaction - const firstTransaction = [ - { - state: writable({ - status: TransactionStatusMessage.SUCCESS, - name: TransactionName.REMOVAL, - links: [] - }) - } - ] as unknown as Transaction[]; - - mockTransactionsStore.set(firstTransaction); - - await waitFor(() => { - expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); - }); - - // Dismiss it - const closeButton = screen.getByRole('button', { name: 'Dismiss transaction' }); - await fireEvent.click(closeButton); - - await waitFor(() => { - expect(container.innerHTML).toBe(''); - }); - - // Add a new transaction - const secondTransaction = [ - { - state: writable({ - status: TransactionStatusMessage.PENDING_RECEIPT, - name: TransactionName.REMOVAL, - links: [] - }) - } - ] as unknown as Transaction[]; - - mockTransactionsStore.set(secondTransaction); - - // Should show the new transaction (dismiss state reset) - await waitFor(() => { - expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); - }); - }); - - it('should update when transactions change', async () => { - const { container } = render(FixedBottomTransaction); - - expect(container.innerHTML).toBe(''); - - // Add first transaction - mockTransactionsStore.set([ - { - state: writable({ - status: TransactionStatusMessage.IDLE, - name: TransactionName.REMOVAL, - links: [] - }) - } - ] as unknown as Transaction[]); - - await waitFor(() => { - expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); - }); - - // Add second transaction (should show the latest one) - mockTransactionsStore.set([ - { - state: writable({ - status: TransactionStatusMessage.IDLE, - name: TransactionName.REMOVAL, - links: [] - }) - }, - { - state: writable({ - status: TransactionStatusMessage.SUCCESS, - name: 'Latest Transaction' as TransactionName, - links: [] - }) - } - ] as unknown as Transaction[]); - - await waitFor(() => { - expect(screen.getByText('Latest Transaction')).toBeInTheDocument(); - expect(screen.queryByText(TransactionName.REMOVAL)).not.toBeInTheDocument(); - }); - - // Remove all transactions - mockTransactionsStore.set([]); - - await waitFor(() => { - expect(container.innerHTML).toBe(''); - }); - }); - - it('should get transactions from the useTransactions hook', () => { - render(FixedBottomTransaction); - expect(useTransactions).toHaveBeenCalled(); - }); - - it('should handle transactions without links', () => { - const mockTransactions = [ - { - state: writable({ - status: TransactionStatusMessage.PENDING_SUBGRAPH, - name: TransactionName.REMOVAL, - links: [] - }) - } - ] as unknown as Transaction[]; - - mockTransactionsStore.set(mockTransactions); - - render(FixedBottomTransaction); - - expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); - expect(screen.getByText(TransactionStatusMessage.PENDING_SUBGRAPH)).toBeInTheDocument(); - expect( - screen.getByText(getStatusEmoji(TransactionStatusMessage.PENDING_SUBGRAPH)) - ).toBeInTheDocument(); - - // Should not render links section - const linkContainer = screen.queryByRole('link'); - expect(linkContainer).not.toBeInTheDocument(); - }); - - it('should have proper accessibility attributes', () => { - const mockTransactions = [ - { - state: writable({ - status: TransactionStatusMessage.SUCCESS, - name: TransactionName.REMOVAL, - links: [] - }) - } - ] as unknown as Transaction[]; - - mockTransactionsStore.set(mockTransactions); - - render(FixedBottomTransaction); - - const closeButton = screen.getByRole('button', { name: 'Dismiss transaction' }); - expect(closeButton).toHaveAttribute('aria-label', 'Dismiss transaction'); - }); - - it('should open links in new tab with proper attributes', () => { - const mockTransactions = [ - { - state: writable({ - status: TransactionStatusMessage.SUCCESS, - name: TransactionName.REMOVAL, - links: [ - { - label: 'External Link', - link: 'https://example.com' - } - ] - }) - } - ] as unknown as Transaction[]; - - mockTransactionsStore.set(mockTransactions); - - render(FixedBottomTransaction); - - const link = screen.getByRole('link', { name: 'External Link' }); - expect(link).toHaveAttribute('href', 'https://example.com'); - expect(link).toHaveAttribute('target', '_blank'); - expect(link).toHaveAttribute('rel', 'noopener noreferrer'); - }); +describe("FixedBottomTransaction", () => { + let mockTransactionManager: TransactionManager; + let mockTransactionsStore: ReturnType>; + + beforeEach(() => { + vi.clearAllMocks(); + + mockTransactionsStore = writable([]); + + mockTransactionManager = { + transactions: vi.fn().mockReturnValue(mockTransactionsStore), + } as unknown as TransactionManager; + + vi.mocked(useTransactions).mockReturnValue({ + manager: mockTransactionManager, + transactions: mockTransactionsStore, + }); + }); + + it("should not render anything when there are no transactions", () => { + const { container } = render(FixedBottomTransaction); + expect(container.innerHTML).toBe(""); + }); + + it("should render the latest transaction when transactions exist", () => { + const mockTransactions = [ + { + state: writable({ + status: TransactionStatusMessage.IDLE, + name: TransactionName.REMOVAL, + links: [], + }), + }, + { + state: writable({ + status: TransactionStatusMessage.SUCCESS, + name: TransactionName.REMOVAL, + links: [ + { + label: "View on Explorer", + link: "https://etherscan.io/tx/0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890", + }, + ], + }), + }, + ] as unknown as Transaction[]; + + mockTransactionsStore.set(mockTransactions); + + render(FixedBottomTransaction); + + // Should render the latest transaction (second one) + expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); + expect( + screen.getByText(TransactionStatusMessage.SUCCESS), + ).toBeInTheDocument(); + expect( + screen.getByText(getStatusEmoji(TransactionStatusMessage.SUCCESS)), + ).toBeInTheDocument(); + expect(screen.getByText("View on Explorer")).toBeInTheDocument(); + }); + + it("should have proper mobile-only styling with fixed positioning", () => { + const mockTransactions = [ + { + state: writable({ + status: TransactionStatusMessage.PENDING_RECEIPT, + name: TransactionName.REMOVAL, + links: [], + }), + }, + ] as unknown as Transaction[]; + + mockTransactionsStore.set(mockTransactions); + + const { container } = render(FixedBottomTransaction); + + const transactionElement = container.querySelector("div"); + expect(transactionElement).toHaveClass( + "fixed", + "bottom-0", + "left-0", + "right-0", + "z-40", + "lg:hidden", + ); + }); + + it("should display transaction details correctly", () => { + const mockTransactions = [ + { + state: writable({ + status: TransactionStatusMessage.PENDING_RECEIPT, + name: TransactionName.REMOVAL, + links: [ + { + label: "Etherscan", + link: "https://etherscan.io/tx/0x123", + }, + { + label: "Block Explorer", + link: "https://explorer.com/tx/0x456", + }, + ], + errorDetails: undefined, + }), + }, + ] as unknown as Transaction[]; + + mockTransactionsStore.set(mockTransactions); + + render(FixedBottomTransaction); + + expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); + expect( + screen.getByText(TransactionStatusMessage.PENDING_RECEIPT), + ).toBeInTheDocument(); + expect( + screen.getByText( + getStatusEmoji(TransactionStatusMessage.PENDING_RECEIPT), + ), + ).toBeInTheDocument(); + expect(screen.getByText("Etherscan")).toBeInTheDocument(); + expect(screen.getByText("Block Explorer")).toBeInTheDocument(); + }); + + it("should display error details when present", () => { + const mockTransactions = [ + { + state: writable({ + status: TransactionStatusMessage.ERROR, + name: TransactionName.REMOVAL, + links: [], + errorDetails: + "Transaction failed due to insufficient gas" as TransactionStoreErrorMessage, + }), + }, + ] as unknown as Transaction[]; + + mockTransactionsStore.set(mockTransactions); + + render(FixedBottomTransaction); + + expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); + expect( + screen.getByText("Transaction failed due to insufficient gas"), + ).toBeInTheDocument(); + expect( + screen.getByText(getStatusEmoji(TransactionStatusMessage.ERROR)), + ).toBeInTheDocument(); + }); + + it("should limit links to maximum of 2", () => { + const mockTransactions = [ + { + state: writable({ + status: TransactionStatusMessage.SUCCESS, + name: TransactionName.REMOVAL, + links: [ + { label: "Link 1", link: "https://example1.com" }, + { label: "Link 2", link: "https://example2.com" }, + { label: "Link 3", link: "https://example3.com" }, + { label: "Link 4", link: "https://example4.com" }, + ], + }), + }, + ] as unknown as Transaction[]; + + mockTransactionsStore.set(mockTransactions); + + render(FixedBottomTransaction); + + expect(screen.getByText("Link 1")).toBeInTheDocument(); + expect(screen.getByText("Link 2")).toBeInTheDocument(); + expect(screen.queryByText("Link 3")).not.toBeInTheDocument(); + expect(screen.queryByText("Link 4")).not.toBeInTheDocument(); + }); + + it("should dismiss transaction when close button is clicked", async () => { + const mockTransactions = [ + { + state: writable({ + status: TransactionStatusMessage.SUCCESS, + name: TransactionName.REMOVAL, + links: [], + }), + }, + ] as unknown as Transaction[]; + + mockTransactionsStore.set(mockTransactions); + + const { container } = render(FixedBottomTransaction); + + expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); + + const closeButton = screen.getByRole("button", { + name: "Dismiss transaction", + }); + expect(closeButton).toBeInTheDocument(); + + await fireEvent.click(closeButton); + + await waitFor(() => { + expect(container.innerHTML).toBe(""); + }); + }); + + it("should reset dismiss state when new transaction appears", async () => { + const { container } = render(FixedBottomTransaction); + + // Start with one transaction + const firstTransaction = [ + { + state: writable({ + status: TransactionStatusMessage.SUCCESS, + name: TransactionName.REMOVAL, + links: [], + }), + }, + ] as unknown as Transaction[]; + + mockTransactionsStore.set(firstTransaction); + + await waitFor(() => { + expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); + }); + + // Dismiss it + const closeButton = screen.getByRole("button", { + name: "Dismiss transaction", + }); + await fireEvent.click(closeButton); + + await waitFor(() => { + expect(container.innerHTML).toBe(""); + }); + + // Add a new transaction + const secondTransaction = [ + { + state: writable({ + status: TransactionStatusMessage.PENDING_RECEIPT, + name: TransactionName.REMOVAL, + links: [], + }), + }, + ] as unknown as Transaction[]; + + mockTransactionsStore.set(secondTransaction); + + // Should show the new transaction (dismiss state reset) + await waitFor(() => { + expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); + }); + }); + + it("should update when transactions change", async () => { + const { container } = render(FixedBottomTransaction); + + expect(container.innerHTML).toBe(""); + + // Add first transaction + mockTransactionsStore.set([ + { + state: writable({ + status: TransactionStatusMessage.IDLE, + name: TransactionName.REMOVAL, + links: [], + }), + }, + ] as unknown as Transaction[]); + + await waitFor(() => { + expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); + }); + + // Add second transaction (should show the latest one) + mockTransactionsStore.set([ + { + state: writable({ + status: TransactionStatusMessage.IDLE, + name: TransactionName.REMOVAL, + links: [], + }), + }, + { + state: writable({ + status: TransactionStatusMessage.SUCCESS, + name: "Latest Transaction" as TransactionName, + links: [], + }), + }, + ] as unknown as Transaction[]); + + await waitFor(() => { + expect(screen.getByText("Latest Transaction")).toBeInTheDocument(); + expect( + screen.queryByText(TransactionName.REMOVAL), + ).not.toBeInTheDocument(); + }); + + // Remove all transactions + mockTransactionsStore.set([]); + + await waitFor(() => { + expect(container.innerHTML).toBe(""); + }); + }); + + it("should get transactions from the useTransactions hook", () => { + render(FixedBottomTransaction); + expect(useTransactions).toHaveBeenCalled(); + }); + + it("should handle transactions without links", () => { + const mockTransactions = [ + { + state: writable({ + status: TransactionStatusMessage.PENDING_SUBGRAPH, + name: TransactionName.REMOVAL, + links: [], + }), + }, + ] as unknown as Transaction[]; + + mockTransactionsStore.set(mockTransactions); + + render(FixedBottomTransaction); + + expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); + expect( + screen.getByText(TransactionStatusMessage.PENDING_SUBGRAPH), + ).toBeInTheDocument(); + expect( + screen.getByText( + getStatusEmoji(TransactionStatusMessage.PENDING_SUBGRAPH), + ), + ).toBeInTheDocument(); + + // Should not render links section + const linkContainer = screen.queryByRole("link"); + expect(linkContainer).not.toBeInTheDocument(); + }); + + it("should have proper accessibility attributes", () => { + const mockTransactions = [ + { + state: writable({ + status: TransactionStatusMessage.SUCCESS, + name: TransactionName.REMOVAL, + links: [], + }), + }, + ] as unknown as Transaction[]; + + mockTransactionsStore.set(mockTransactions); + + render(FixedBottomTransaction); + + const closeButton = screen.getByRole("button", { + name: "Dismiss transaction", + }); + expect(closeButton).toHaveAttribute("aria-label", "Dismiss transaction"); + }); + + it("should open links in new tab with proper attributes", () => { + const mockTransactions = [ + { + state: writable({ + status: TransactionStatusMessage.SUCCESS, + name: TransactionName.REMOVAL, + links: [ + { + label: "External Link", + link: "https://example.com", + }, + ], + }), + }, + ] as unknown as Transaction[]; + + mockTransactionsStore.set(mockTransactions); + + render(FixedBottomTransaction); + + const link = screen.getByRole("link", { name: "External Link" }); + expect(link).toHaveAttribute("href", "https://example.com"); + expect(link).toHaveAttribute("target", "_blank"); + expect(link).toHaveAttribute("rel", "noopener noreferrer"); + }); }); diff --git a/packages/ui-components/src/__tests__/Hash.test.ts b/packages/ui-components/src/__tests__/Hash.test.ts index 636fe88369..f4831709ff 100644 --- a/packages/ui-components/src/__tests__/Hash.test.ts +++ b/packages/ui-components/src/__tests__/Hash.test.ts @@ -1,65 +1,65 @@ -import { render } from '@testing-library/svelte'; -import Hash from '../lib/components/Hash.svelte'; -import { describe, it, expect } from 'vitest'; -import userEvent from '@testing-library/user-event'; +import { render } from "@testing-library/svelte"; +import Hash from "../lib/components/Hash.svelte"; +import { describe, it, expect } from "vitest"; +import userEvent from "@testing-library/user-event"; -describe('Hash Component', () => { - it('renders with shortened hash display', () => { - const { getByText } = render(Hash, { - props: { - value: 'abcdef1234567890', - type: 1, // HashType.Wallet - shorten: true, - sliceLen: 5 - } - }); - expect(getByText('abcde...67890')).toBeInTheDocument(); - }); +describe("Hash Component", () => { + it("renders with shortened hash display", () => { + const { getByText } = render(Hash, { + props: { + value: "abcdef1234567890", + type: 1, // HashType.Wallet + shorten: true, + sliceLen: 5, + }, + }); + expect(getByText("abcde...67890")).toBeInTheDocument(); + }); - it('renders full hash when shorten is false', () => { - const { getByText } = render(Hash, { - props: { - value: 'abcdef1234567890', - type: 1, - shorten: false - } - }); + it("renders full hash when shorten is false", () => { + const { getByText } = render(Hash, { + props: { + value: "abcdef1234567890", + type: 1, + shorten: false, + }, + }); - expect(getByText('abcdef1234567890')).toBeInTheDocument(); - }); + expect(getByText("abcdef1234567890")).toBeInTheDocument(); + }); - it('copies hash to clipboard and shows copied message', async () => { - const user = userEvent.setup(); + it("copies hash to clipboard and shows copied message", async () => { + const user = userEvent.setup(); - const { getByRole, findByText } = render(Hash, { - props: { - value: 'abcdef1234567890', - type: 1, - copyOnClick: true - } - }); + const { getByRole, findByText } = render(Hash, { + props: { + value: "abcdef1234567890", + type: 1, + copyOnClick: true, + }, + }); - const button = getByRole('button'); - await user.click(button); - expect(await findByText('Copied to clipboard')).toBeInTheDocument(); - const clipboardText = await navigator.clipboard.readText(); - expect(clipboardText).toBe('abcdef1234567890'); - }); + const button = getByRole("button"); + await user.click(button); + expect(await findByText("Copied to clipboard")).toBeInTheDocument(); + const clipboardText = await navigator.clipboard.readText(); + expect(clipboardText).toBe("abcdef1234567890"); + }); - it('does not copy to clipboard if copyOnClick is false', async () => { - const user = userEvent.setup(); + it("does not copy to clipboard if copyOnClick is false", async () => { + const user = userEvent.setup(); - const { getByRole } = render(Hash, { - props: { - value: 'abcdef1234567890', - type: 1, - copyOnClick: false - } - }); + const { getByRole } = render(Hash, { + props: { + value: "abcdef1234567890", + type: 1, + copyOnClick: false, + }, + }); - const button = getByRole('button'); - await user.click(button); - const clipboardText = await navigator.clipboard.readText(); - expect(clipboardText).toBe(''); - }); + const button = getByRole("button"); + await user.click(button); + const clipboardText = await navigator.clipboard.readText(); + expect(clipboardText).toBe(""); + }); }); diff --git a/packages/ui-components/src/__tests__/InputHex.test.ts b/packages/ui-components/src/__tests__/InputHex.test.ts index 5e038c0698..35a680da63 100644 --- a/packages/ui-components/src/__tests__/InputHex.test.ts +++ b/packages/ui-components/src/__tests__/InputHex.test.ts @@ -1,22 +1,22 @@ -import { describe, it, expect } from 'vitest'; -import { render, screen } from '@testing-library/svelte'; -import InputHex from '../lib/components/input/InputHex.svelte'; +import { describe, it, expect } from "vitest"; +import { render, screen } from "@testing-library/svelte"; +import InputHex from "../lib/components/input/InputHex.svelte"; -describe('InputHex', () => { - it('renders an input element', () => { - render(InputHex); - expect(screen.getByRole('textbox')).toBeTruthy(); - }); +describe("InputHex", () => { + it("renders an input element", () => { + render(InputHex); + expect(screen.getByRole("textbox")).toBeTruthy(); + }); - it('initializes with empty string when no value provided', () => { - render(InputHex); - const input = screen.getByRole('textbox') as HTMLInputElement; - expect(input.value).toBe(''); - }); + it("initializes with empty string when no value provided", () => { + render(InputHex); + const input = screen.getByRole("textbox") as HTMLInputElement; + expect(input.value).toBe(""); + }); - it('displays hex value when bigint is provided', () => { - render(InputHex, { props: { value: 255n } }); - const input = screen.getByRole('textbox') as HTMLInputElement; - expect(input.value).toBe('0xff'); - }); + it("displays hex value when bigint is provided", () => { + render(InputHex, { props: { value: 255n } }); + const input = screen.getByRole("textbox") as HTMLInputElement; + expect(input.value).toBe("0xff"); + }); }); diff --git a/packages/ui-components/src/__tests__/InputOrderHash.test.ts b/packages/ui-components/src/__tests__/InputOrderHash.test.ts index 0c3838380d..a393cd1da6 100644 --- a/packages/ui-components/src/__tests__/InputOrderHash.test.ts +++ b/packages/ui-components/src/__tests__/InputOrderHash.test.ts @@ -1,33 +1,35 @@ -import { render, fireEvent } from '@testing-library/svelte'; -import { writable, get } from 'svelte/store'; -import InputOrderHash from '../lib/components/input/InputOrderHash.svelte'; -import type { Hex } from '@rainlanguage/raindex'; +import { render, fireEvent } from "@testing-library/svelte"; +import { writable, get } from "svelte/store"; +import InputOrderHash from "../lib/components/input/InputOrderHash.svelte"; +import type { Hex } from "@rainlanguage/raindex"; -describe('InputOrderHash', () => { - it('renders with initial value', () => { - const orderHash = writable('0x0123'); - const { getByTestId } = render(InputOrderHash, { props: { orderHash } }); +describe("InputOrderHash", () => { + it("renders with initial value", () => { + const orderHash = writable("0x0123"); + const { getByTestId } = render(InputOrderHash, { props: { orderHash } }); - const input = getByTestId('order-hash-input').querySelector('input'); - expect(input?.value).toBe('0x0123'); - }); + const input = getByTestId("order-hash-input").querySelector("input"); + expect(input?.value).toBe("0x0123"); + }); - it('updates store value when input changes', async () => { - const orderHash = writable('0x0123'); - const { getByTestId } = render(InputOrderHash, { props: { orderHash } }); + it("updates store value when input changes", async () => { + const orderHash = writable("0x0123"); + const { getByTestId } = render(InputOrderHash, { props: { orderHash } }); - const input = getByTestId('order-hash-input').querySelector('input') as HTMLInputElement; - await fireEvent.input(input, { target: { value: '0xabc' } }); + const input = getByTestId("order-hash-input").querySelector( + "input", + ) as HTMLInputElement; + await fireEvent.input(input, { target: { value: "0xabc" } }); - expect(input.value).toBe('0xabc'); - expect(get(orderHash)).toBe('0xabc'); - }); + expect(input.value).toBe("0xabc"); + expect(get(orderHash)).toBe("0xabc"); + }); - it('renders with placeholder', () => { - const orderHash = writable('0x0345'); - const { getByTestId } = render(InputOrderHash, { props: { orderHash } }); + it("renders with placeholder", () => { + const orderHash = writable("0x0345"); + const { getByTestId } = render(InputOrderHash, { props: { orderHash } }); - const input = getByTestId('order-hash-input').querySelector('input'); - expect(input?.placeholder).toBe('0x...'); - }); + const input = getByTestId("order-hash-input").querySelector("input"); + expect(input?.placeholder).toBe("0x..."); + }); }); diff --git a/packages/ui-components/src/__tests__/InputRegistryUrl.test.ts b/packages/ui-components/src/__tests__/InputRegistryUrl.test.ts index ccf1f97a9d..3ecfe41761 100644 --- a/packages/ui-components/src/__tests__/InputRegistryUrl.test.ts +++ b/packages/ui-components/src/__tests__/InputRegistryUrl.test.ts @@ -1,95 +1,103 @@ -import { render, screen, fireEvent } from '@testing-library/svelte'; -import { vi } from 'vitest'; -import InputRegistryUrl from '../lib/components/input/InputRegistryUrl.svelte'; -import userEvent from '@testing-library/user-event'; -import { loadRegistryUrl } from '../lib/services/loadRegistryUrl'; -import { initialRegistry } from '../__fixtures__/RegistryManager'; -import { useRegistry } from '$lib/providers/registry/useRegistry'; -import type { RegistryManager } from '$lib/providers/registry/RegistryManager'; - -vi.mock('../lib/services/loadRegistryUrl', () => ({ - loadRegistryUrl: vi.fn() +import { render, screen, fireEvent } from "@testing-library/svelte"; +import { vi } from "vitest"; +import InputRegistryUrl from "../lib/components/input/InputRegistryUrl.svelte"; +import userEvent from "@testing-library/user-event"; +import { loadRegistryUrl } from "../lib/services/loadRegistryUrl"; +import { initialRegistry } from "../__fixtures__/RegistryManager"; +import { useRegistry } from "$lib/providers/registry/useRegistry"; +import type { RegistryManager } from "$lib/providers/registry/RegistryManager"; + +vi.mock("../lib/services/loadRegistryUrl", () => ({ + loadRegistryUrl: vi.fn(), })); -vi.mock('../lib/providers/registry/useRegistry', () => ({ - useRegistry: vi.fn() +vi.mock("../lib/providers/registry/useRegistry", () => ({ + useRegistry: vi.fn(), })); -describe('InputRegistryUrl', () => { - beforeEach(() => { - vi.clearAllMocks(); - vi.mocked(loadRegistryUrl).mockResolvedValue(undefined); - vi.mocked(useRegistry).mockReturnValue(initialRegistry as RegistryManager); - }); +describe("InputRegistryUrl", () => { + beforeEach(() => { + vi.clearAllMocks(); + vi.mocked(loadRegistryUrl).mockResolvedValue(undefined); + vi.mocked(useRegistry).mockReturnValue(initialRegistry as RegistryManager); + }); - it('should render input and button', () => { - render(InputRegistryUrl); + it("should render input and button", () => { + render(InputRegistryUrl); - const input = screen.getByPlaceholderText('Enter URL to raw order registry file'); - const button = screen.getByText('Load registry URL'); + const input = screen.getByPlaceholderText( + "Enter URL to raw order registry file", + ); + const button = screen.getByText("Load registry URL"); - expect(input).toBeInTheDocument(); - expect(button).toBeInTheDocument(); - }); + expect(input).toBeInTheDocument(); + expect(button).toBeInTheDocument(); + }); - it('should call loadRegistryUrl when button is clicked', async () => { - render(InputRegistryUrl); + it("should call loadRegistryUrl when button is clicked", async () => { + render(InputRegistryUrl); - const input = screen.getByPlaceholderText('Enter URL to raw order registry file'); - const testUrl = 'https://example.com/registry.json'; - await userEvent.clear(input); - await userEvent.type(input, testUrl); + const input = screen.getByPlaceholderText( + "Enter URL to raw order registry file", + ); + const testUrl = "https://example.com/registry.json"; + await userEvent.clear(input); + await userEvent.type(input, testUrl); - const button = screen.getByText('Load registry URL'); - await fireEvent.click(button); + const button = screen.getByText("Load registry URL"); + await fireEvent.click(button); - expect(loadRegistryUrl).toHaveBeenCalledWith(testUrl, initialRegistry); - }); + expect(loadRegistryUrl).toHaveBeenCalledWith(testUrl, initialRegistry); + }); - it('should load initial value from registry manager', () => { - const initialUrl = 'https://example.com/registry.json'; - initialRegistry.getCurrentRegistry = vi.fn().mockReturnValue(initialUrl); - render(InputRegistryUrl); + it("should load initial value from registry manager", () => { + const initialUrl = "https://example.com/registry.json"; + initialRegistry.getCurrentRegistry = vi.fn().mockReturnValue(initialUrl); + render(InputRegistryUrl); - const input = screen.getByPlaceholderText('Enter URL to raw order registry file'); - expect(input).toHaveValue(initialUrl); - }); + const input = screen.getByPlaceholderText( + "Enter URL to raw order registry file", + ); + expect(input).toHaveValue(initialUrl); + }); - it('should display error message when loadRegistryUrl fails', async () => { - vi.mocked(loadRegistryUrl).mockRejectedValueOnce(new Error('Test error')); + it("should display error message when loadRegistryUrl fails", async () => { + vi.mocked(loadRegistryUrl).mockRejectedValueOnce(new Error("Test error")); - render(InputRegistryUrl); + render(InputRegistryUrl); - const button = screen.getByText('Load registry URL'); - await fireEvent.click(button); + const button = screen.getByText("Load registry URL"); + await fireEvent.click(button); - expect(await screen.findByTestId('registry-error')).toHaveTextContent('Test error'); - }); + expect(await screen.findByTestId("registry-error")).toHaveTextContent( + "Test error", + ); + }); - it('should show loading state when request is in progress', async () => { - vi.useFakeTimers(); + it("should show loading state when request is in progress", async () => { + vi.useFakeTimers(); - vi.mocked(loadRegistryUrl).mockImplementation(() => { - return new Promise((resolve) => { - setTimeout(() => resolve(), 1000); - }); - }); + vi.mocked(loadRegistryUrl).mockImplementation(() => { + return new Promise((resolve) => { + setTimeout(() => resolve(), 1000); + }); + }); - const user = userEvent.setup({ advanceTimers: vi.advanceTimersByTime }); + const user = userEvent.setup({ advanceTimers: vi.advanceTimersByTime }); - render(InputRegistryUrl); + render(InputRegistryUrl); - const button = screen.getByText('Load registry URL'); - await user.click(button); + const button = screen.getByText("Load registry URL"); + await user.click(button); - expect(screen.getByText('Loading registry...')).toBeInTheDocument(); - expect(button).toBeDisabled(); + expect(screen.getByText("Loading registry...")).toBeInTheDocument(); + expect(button).toBeDisabled(); - await vi.runAllTimersAsync(); + await vi.runAllTimersAsync(); - expect(screen.getByText('Load registry URL')).toBeInTheDocument(); - expect(button).not.toBeDisabled(); + expect(screen.getByText("Load registry URL")).toBeInTheDocument(); + expect(button).not.toBeDisabled(); - vi.useRealTimers(); - }); + vi.useRealTimers(); + }); }); diff --git a/packages/ui-components/src/__tests__/InputToken.test.ts b/packages/ui-components/src/__tests__/InputToken.test.ts index 28a051d6e0..28704c02cf 100644 --- a/packages/ui-components/src/__tests__/InputToken.test.ts +++ b/packages/ui-components/src/__tests__/InputToken.test.ts @@ -1,39 +1,53 @@ -import { render, fireEvent } from '@testing-library/svelte'; -import InputToken from '../lib/components/input/InputToken.svelte'; - -describe('InputToken', () => { - it('renders with initial values', () => { - const address = '0xc0D477556c25C9d67E1f57245C7453DA776B51cf'; - const decimals = 10; - const { getByTestId } = render(InputToken, { props: { address, decimals } }); - - const input = getByTestId('token-address').querySelector('input'); - expect(input?.value).toBe('0xc0D477556c25C9d67E1f57245C7453DA776B51cf'); - const decimalsInput = getByTestId('token-decimals-input').querySelector('input'); - expect(decimalsInput?.value).toBe('10'); - }); - - it('shows error for invalid address', async () => { - const address = 'abc'; - const decimals = 0; - const { getByTestId, getByText } = render(InputToken, { props: { address, decimals } }); - - const addressInput = getByTestId('token-address').querySelector('input') as HTMLInputElement; - await fireEvent.input(addressInput, { target: { value: 'invalidAddress' } }); - - expect(getByText('Invalid address')).toBeInTheDocument(); - }); - - it('does not show error for valid address', async () => { - const address = ''; - const decimals = 0; - const { getByTestId, queryByText } = render(InputToken, { props: { address, decimals } }); - - const addressInput = getByTestId('token-address').querySelector('input') as HTMLInputElement; - await fireEvent.input(addressInput, { - target: { value: '0xc0D477556c25C9d67E1f57245C7453DA776B51cf' } - }); - - expect(queryByText('Invalid address')).toBeNull(); - }); +import { render, fireEvent } from "@testing-library/svelte"; +import InputToken from "../lib/components/input/InputToken.svelte"; + +describe("InputToken", () => { + it("renders with initial values", () => { + const address = "0xc0D477556c25C9d67E1f57245C7453DA776B51cf"; + const decimals = 10; + const { getByTestId } = render(InputToken, { + props: { address, decimals }, + }); + + const input = getByTestId("token-address").querySelector("input"); + expect(input?.value).toBe("0xc0D477556c25C9d67E1f57245C7453DA776B51cf"); + const decimalsInput = getByTestId("token-decimals-input").querySelector( + "input", + ); + expect(decimalsInput?.value).toBe("10"); + }); + + it("shows error for invalid address", async () => { + const address = "abc"; + const decimals = 0; + const { getByTestId, getByText } = render(InputToken, { + props: { address, decimals }, + }); + + const addressInput = getByTestId("token-address").querySelector( + "input", + ) as HTMLInputElement; + await fireEvent.input(addressInput, { + target: { value: "invalidAddress" }, + }); + + expect(getByText("Invalid address")).toBeInTheDocument(); + }); + + it("does not show error for valid address", async () => { + const address = ""; + const decimals = 0; + const { getByTestId, queryByText } = render(InputToken, { + props: { address, decimals }, + }); + + const addressInput = getByTestId("token-address").querySelector( + "input", + ) as HTMLInputElement; + await fireEvent.input(addressInput, { + target: { value: "0xc0D477556c25C9d67E1f57245C7453DA776B51cf" }, + }); + + expect(queryByText("Invalid address")).toBeNull(); + }); }); diff --git a/packages/ui-components/src/__tests__/InputTokenAmount.test.ts b/packages/ui-components/src/__tests__/InputTokenAmount.test.ts index cce7f7faea..101376b675 100644 --- a/packages/ui-components/src/__tests__/InputTokenAmount.test.ts +++ b/packages/ui-components/src/__tests__/InputTokenAmount.test.ts @@ -1,40 +1,43 @@ -import { render, fireEvent } from '@testing-library/svelte'; -import { describe, it, expect } from 'vitest'; -import InputTokenAmount from '$lib/components/input/InputTokenAmount.svelte'; -import { Float } from '@rainlanguage/raindex'; +import { render, fireEvent } from "@testing-library/svelte"; +import { describe, it, expect } from "vitest"; +import InputTokenAmount from "$lib/components/input/InputTokenAmount.svelte"; +import { Float } from "@rainlanguage/raindex"; -vi.mock('@rainlanguage/raindex', async (importOriginal) => ({ - ...(await importOriginal()) +vi.mock("@rainlanguage/raindex", async (importOriginal) => ({ + ...(await importOriginal()), })); -describe('InputTokenAmount', () => { - it('should handle empty input', async () => { - const { getByRole, component } = render(InputTokenAmount, { - props: { value: Float.parse('0').value } - }); - const input = getByRole('textbox'); +describe("InputTokenAmount", () => { + it("should handle empty input", async () => { + const { getByRole, component } = render(InputTokenAmount, { + props: { value: Float.parse("0").value }, + }); + const input = getByRole("textbox"); - await fireEvent.input(input, { target: { value: '' } }); - expect(component.$$.ctx[component.$$.props.value].format().value).toBe('0'); - }); + await fireEvent.input(input, { target: { value: "" } }); + expect(component.$$.ctx[component.$$.props.value].format().value).toBe("0"); + }); - it('should handle invalid input', async () => { - const { getByRole, component } = render(InputTokenAmount, { - props: { value: Float.parse('0').value } - }); - const input = getByRole('textbox'); + it("should handle invalid input", async () => { + const { getByRole, component } = render(InputTokenAmount, { + props: { value: Float.parse("0").value }, + }); + const input = getByRole("textbox"); - await fireEvent.input(input, { target: { value: 'abc' } }); - expect(component.$$.ctx[component.$$.props.value].format().value).toBe('0'); - }); + await fireEvent.input(input, { target: { value: "abc" } }); + expect(component.$$.ctx[component.$$.props.value].format().value).toBe("0"); + }); - it('should handle maxValue prop', async () => { - const { getByText, component } = render(InputTokenAmount, { - props: { maxValue: Float.parse('1').value, value: Float.parse('0').value } - }); - const maxButton = getByText('MAX'); + it("should handle maxValue prop", async () => { + const { getByText, component } = render(InputTokenAmount, { + props: { + maxValue: Float.parse("1").value, + value: Float.parse("0").value, + }, + }); + const maxButton = getByText("MAX"); - await fireEvent.click(maxButton); - expect(component.$$.ctx[component.$$.props.value].format().value).toBe('1'); - }); + await fireEvent.click(maxButton); + expect(component.$$.ctx[component.$$.props.value].format().value).toBe("1"); + }); }); diff --git a/packages/ui-components/src/__tests__/InvalidOrdersSection.test.ts b/packages/ui-components/src/__tests__/InvalidOrdersSection.test.ts index e5c38760d4..80a04b8ccf 100644 --- a/packages/ui-components/src/__tests__/InvalidOrdersSection.test.ts +++ b/packages/ui-components/src/__tests__/InvalidOrdersSection.test.ts @@ -1,26 +1,28 @@ -import { describe, it, expect } from 'vitest'; -import { render, screen } from '@testing-library/svelte'; -import InvalidOrdersSection from '../lib/components/deployment/InvalidOrdersSection.svelte'; -import type { InvalidOrderDetail } from '$lib/types/order'; +import { describe, it, expect } from "vitest"; +import { render, screen } from "@testing-library/svelte"; +import InvalidOrdersSection from "../lib/components/deployment/InvalidOrdersSection.svelte"; +import type { InvalidOrderDetail } from "$lib/types/order"; -describe('InvalidOrdersSection', () => { - const mockInvalidOrders: InvalidOrderDetail[] = [ - { - name: 'Order 1', - error: 'Invalid configuration' - }, - { - name: 'Order 2', - error: 'Missing required field' - } - ]; +describe("InvalidOrdersSection", () => { + const mockInvalidOrders: InvalidOrderDetail[] = [ + { + name: "Order 1", + error: "Invalid configuration", + }, + { + name: "Order 2", + error: "Missing required field", + }, + ]; - it('displays multiple invalid orders with their errors', () => { - render(InvalidOrdersSection, { props: { ordersWithErrors: mockInvalidOrders } }); + it("displays multiple invalid orders with their errors", () => { + render(InvalidOrdersSection, { + props: { ordersWithErrors: mockInvalidOrders }, + }); - expect(screen.getByText('Order 1')).toBeInTheDocument(); - expect(screen.getByText('Order 2')).toBeInTheDocument(); - expect(screen.getByText('Invalid configuration')).toBeInTheDocument(); - expect(screen.getByText('Missing required field')).toBeInTheDocument(); - }); + expect(screen.getByText("Order 1")).toBeInTheDocument(); + expect(screen.getByText("Order 2")).toBeInTheDocument(); + expect(screen.getByText("Invalid configuration")).toBeInTheDocument(); + expect(screen.getByText("Missing required field")).toBeInTheDocument(); + }); }); diff --git a/packages/ui-components/src/__tests__/License.test.ts b/packages/ui-components/src/__tests__/License.test.ts index 07b9a750d4..cbbce27322 100644 --- a/packages/ui-components/src/__tests__/License.test.ts +++ b/packages/ui-components/src/__tests__/License.test.ts @@ -1,82 +1,85 @@ -import { render, screen, waitFor } from '@testing-library/svelte'; -import { beforeEach, expect, describe, vi, afterEach } from 'vitest'; -import License from '../lib/components/License.svelte'; -import { LICENSE_URL } from '../lib/consts'; +import { render, screen, waitFor } from "@testing-library/svelte"; +import { beforeEach, expect, describe, vi, afterEach } from "vitest"; +import License from "../lib/components/License.svelte"; +import { LICENSE_URL } from "../lib/consts"; // Mock the global fetch function const mockFetch = vi.fn(); -vi.stubGlobal('fetch', mockFetch); +vi.stubGlobal("fetch", mockFetch); -vi.mock('svelte-markdown', async () => { - const MockMarkdown = (await import('../lib/__mocks__/MockComponent.svelte')).default; - return { default: MockMarkdown }; +vi.mock("svelte-markdown", async () => { + const MockMarkdown = (await import("../lib/__mocks__/MockComponent.svelte")) + .default; + return { default: MockMarkdown }; }); -describe('License', () => { - const mockMarkdownContent = 'This is license text.'; - - beforeEach(() => { - mockFetch.mockReset(); - }); - - afterEach(() => { - vi.restoreAllMocks(); - }); - - it('fetches and renders markdown content on mount', async () => { - mockFetch.mockResolvedValue({ - ok: true, - text: async () => mockMarkdownContent - }); - - render(License); - - await waitFor(() => { - expect(mockFetch).toHaveBeenCalledTimes(1); - expect(mockFetch).toHaveBeenCalledWith(LICENSE_URL); - }); - - await waitFor(() => { - expect(screen.getByTestId('mock-component').getAttribute('source')).toBe(mockMarkdownContent); - }); - }); - - it('handles fetch network error gracefully', async () => { - mockFetch.mockRejectedValue(new Error('Network error')); - - render(License); - - await waitFor(() => { - expect(mockFetch).toHaveBeenCalledTimes(1); - expect(mockFetch).toHaveBeenCalledWith(LICENSE_URL); - }); - - await waitFor(() => { - expect(screen.getByTestId('mock-component').getAttribute('source')).toBe( - 'Failed to fetch license.' - ); - }); - }); - - it('handles non-OK HTTP responses gracefully', async () => { - mockFetch.mockResolvedValue({ - ok: false, - status: 404, - statusText: 'Not Found' - }); - - render(License); - - await waitFor(() => { - expect(mockFetch).toHaveBeenCalledTimes(1); - expect(mockFetch).toHaveBeenCalledWith(LICENSE_URL); - }); - - await waitFor(() => { - expect(screen.getByTestId('mock-component').getAttribute('source')).toBe( - 'Failed to fetch license: HTTP 404' - ); - }); - }); +describe("License", () => { + const mockMarkdownContent = "This is license text."; + + beforeEach(() => { + mockFetch.mockReset(); + }); + + afterEach(() => { + vi.restoreAllMocks(); + }); + + it("fetches and renders markdown content on mount", async () => { + mockFetch.mockResolvedValue({ + ok: true, + text: async () => mockMarkdownContent, + }); + + render(License); + + await waitFor(() => { + expect(mockFetch).toHaveBeenCalledTimes(1); + expect(mockFetch).toHaveBeenCalledWith(LICENSE_URL); + }); + + await waitFor(() => { + expect(screen.getByTestId("mock-component").getAttribute("source")).toBe( + mockMarkdownContent, + ); + }); + }); + + it("handles fetch network error gracefully", async () => { + mockFetch.mockRejectedValue(new Error("Network error")); + + render(License); + + await waitFor(() => { + expect(mockFetch).toHaveBeenCalledTimes(1); + expect(mockFetch).toHaveBeenCalledWith(LICENSE_URL); + }); + + await waitFor(() => { + expect(screen.getByTestId("mock-component").getAttribute("source")).toBe( + "Failed to fetch license.", + ); + }); + }); + + it("handles non-OK HTTP responses gracefully", async () => { + mockFetch.mockResolvedValue({ + ok: false, + status: 404, + statusText: "Not Found", + }); + + render(License); + + await waitFor(() => { + expect(mockFetch).toHaveBeenCalledTimes(1); + expect(mockFetch).toHaveBeenCalledWith(LICENSE_URL); + }); + + await waitFor(() => { + expect(screen.getByTestId("mock-component").getAttribute("source")).toBe( + "Failed to fetch license: HTTP 404", + ); + }); + }); }); diff --git a/packages/ui-components/src/__tests__/LightweightChart.test.ts b/packages/ui-components/src/__tests__/LightweightChart.test.ts index 023bf11e96..bda203333b 100644 --- a/packages/ui-components/src/__tests__/LightweightChart.test.ts +++ b/packages/ui-components/src/__tests__/LightweightChart.test.ts @@ -1,289 +1,303 @@ -import { act, fireEvent, render, screen, waitFor } from '@testing-library/svelte'; -import { test, vi } from 'vitest'; -import { expect } from '../lib/test/matchers'; -import LightweightChart from '../lib/components/charts/LightweightChart.svelte'; -import { type IChartApi, type UTCTimestamp } from 'lightweight-charts'; -import { readable } from 'svelte/store'; +import { + act, + fireEvent, + render, + screen, + waitFor, +} from "@testing-library/svelte"; +import { test, vi } from "vitest"; +import { expect } from "../lib/test/matchers"; +import LightweightChart from "../lib/components/charts/LightweightChart.svelte"; +import { type IChartApi, type UTCTimestamp } from "lightweight-charts"; +import { readable } from "svelte/store"; const setDataMock = vi.fn(); const applyOptionsMock = vi.fn(); const setVisibleRangeMock = vi.fn(); const removeMock = vi.fn(); const updateMock = vi.fn(); -vi.mock('lightweight-charts', async (importOriginal) => ({ - ...((await importOriginal()) as object), - createChart: vi.fn(() => ({ - addLineSeries: vi.fn(() => ({ - setData: setDataMock, - update: updateMock - })), - remove: removeMock, - applyOptions: applyOptionsMock, - timeScale: vi.fn(() => ({ - setVisibleRange: setVisibleRangeMock - })) - })) +vi.mock("lightweight-charts", async (importOriginal) => ({ + ...((await importOriginal()) as object), + createChart: vi.fn(() => ({ + addLineSeries: vi.fn(() => ({ + setData: setDataMock, + update: updateMock, + })), + remove: removeMock, + applyOptions: applyOptionsMock, + timeScale: vi.fn(() => ({ + setVisibleRange: setVisibleRangeMock, + })), + })), })); -test('renders without data correctly', async () => { - const title = 'test title'; - const emptyMessage = 'empty message'; - let loading = true; - const priceSymbol = '$'; - const createSeries = (chart: IChartApi) => chart.addLineSeries(); - - const { component } = render(LightweightChart, { - title, - emptyMessage, - loading, - priceSymbol, - createSeries, - lightweightChartsTheme: readable({ test: 'test' }) - }); - - await waitFor(() => { - expect(screen.getByTestId('lightweightChartTitle')).toHaveTextContent(title); - expect(screen.getByTestId('lightweightChartSpinner')).toBeInTheDocument(); - }); - - loading = false; - - await act(() => component.$set({ loading: false })); - - await waitFor(() => { - expect(screen.getByTestId('lightweightChartEmptyMessage')).toHaveTextContent(emptyMessage); - }); +test("renders without data correctly", async () => { + const title = "test title"; + const emptyMessage = "empty message"; + let loading = true; + const priceSymbol = "$"; + const createSeries = (chart: IChartApi) => chart.addLineSeries(); + + const { component } = render(LightweightChart, { + title, + emptyMessage, + loading, + priceSymbol, + createSeries, + lightweightChartsTheme: readable({ test: "test" }), + }); + + await waitFor(() => { + expect(screen.getByTestId("lightweightChartTitle")).toHaveTextContent( + title, + ); + expect(screen.getByTestId("lightweightChartSpinner")).toBeInTheDocument(); + }); + + loading = false; + + await act(() => component.$set({ loading: false })); + + await waitFor(() => { + expect( + screen.getByTestId("lightweightChartEmptyMessage"), + ).toHaveTextContent(emptyMessage); + }); }); -test('renders with data correctly', async () => { - const title = 'test title'; - const emptyMessage = 'empty message'; - const loading = true; - const priceSymbol = '$'; - - const createSeries = (chart: IChartApi) => chart.addLineSeries(); - - const data: { value: number; time: UTCTimestamp; color?: string }[] = [ - { - value: 10, - time: 1529899200 as UTCTimestamp - }, - { - value: 20, - time: 1529899300 as UTCTimestamp - }, - { - value: 5, - time: 1529899500 as UTCTimestamp - } - ]; - - render(LightweightChart, { - title, - emptyMessage, - loading, - priceSymbol, - createSeries, - data, - lightweightChartsTheme: readable({ test: 'test' }) - }); - - await waitFor(() => { - expect(screen.getByTestId('lightweightChartTitle')).toHaveTextContent(title); - expect(screen.getByTestId('lightweightChartSpinner')).toBeInTheDocument(); - expect(screen.getByTestId('lightweightChartElement')).toBeInTheDocument(); - expect(screen.queryByTestId('lightweightChartYearButtons')).toBeInTheDocument(); - - expect(setDataMock).toHaveBeenCalledWith(data); - }); +test("renders with data correctly", async () => { + const title = "test title"; + const emptyMessage = "empty message"; + const loading = true; + const priceSymbol = "$"; + + const createSeries = (chart: IChartApi) => chart.addLineSeries(); + + const data: { value: number; time: UTCTimestamp; color?: string }[] = [ + { + value: 10, + time: 1529899200 as UTCTimestamp, + }, + { + value: 20, + time: 1529899300 as UTCTimestamp, + }, + { + value: 5, + time: 1529899500 as UTCTimestamp, + }, + ]; + + render(LightweightChart, { + title, + emptyMessage, + loading, + priceSymbol, + createSeries, + data, + lightweightChartsTheme: readable({ test: "test" }), + }); + + await waitFor(() => { + expect(screen.getByTestId("lightweightChartTitle")).toHaveTextContent( + title, + ); + expect(screen.getByTestId("lightweightChartSpinner")).toBeInTheDocument(); + expect(screen.getByTestId("lightweightChartElement")).toBeInTheDocument(); + expect( + screen.queryByTestId("lightweightChartYearButtons"), + ).toBeInTheDocument(); + + expect(setDataMock).toHaveBeenCalledWith(data); + }); }); -test('updates data correctly when new data points are added', async () => { - const title = 'test title'; - const emptyMessage = 'empty message'; - const loading = false; - const priceSymbol = '$'; - const createSeries = (chart: IChartApi) => chart.addLineSeries(); - - const initialData = [ - { value: 10, time: 1529899200 as UTCTimestamp }, - { value: 20, time: 1529899300 as UTCTimestamp } - ]; - - const { component } = render(LightweightChart, { - title, - emptyMessage, - loading, - priceSymbol, - createSeries, - data: initialData, - lightweightChartsTheme: readable({ test: 'test' }) - }); - - // First render should call setData with initial data - await waitFor(() => { - expect(setDataMock).toHaveBeenCalledWith(initialData); - }); - - // Add new data points - const newDataPoints = [ - ...initialData, - { value: 30, time: 1529899400 as UTCTimestamp }, - { value: 40, time: 1529899500 as UTCTimestamp } - ]; - - // Update with new data that includes additional points - await act(() => component.$set({ data: newDataPoints })); - - // Should call update for each new point - await waitFor(() => { - expect(updateMock).toHaveBeenCalledTimes(2); - expect(updateMock).toHaveBeenCalledWith({ - value: 30, - time: 1529899400 as UTCTimestamp - }); - expect(updateMock).toHaveBeenCalledWith({ - value: 40, - time: 1529899500 as UTCTimestamp - }); - }); +test("updates data correctly when new data points are added", async () => { + const title = "test title"; + const emptyMessage = "empty message"; + const loading = false; + const priceSymbol = "$"; + const createSeries = (chart: IChartApi) => chart.addLineSeries(); + + const initialData = [ + { value: 10, time: 1529899200 as UTCTimestamp }, + { value: 20, time: 1529899300 as UTCTimestamp }, + ]; + + const { component } = render(LightweightChart, { + title, + emptyMessage, + loading, + priceSymbol, + createSeries, + data: initialData, + lightweightChartsTheme: readable({ test: "test" }), + }); + + // First render should call setData with initial data + await waitFor(() => { + expect(setDataMock).toHaveBeenCalledWith(initialData); + }); + + // Add new data points + const newDataPoints = [ + ...initialData, + { value: 30, time: 1529899400 as UTCTimestamp }, + { value: 40, time: 1529899500 as UTCTimestamp }, + ]; + + // Update with new data that includes additional points + await act(() => component.$set({ data: newDataPoints })); + + // Should call update for each new point + await waitFor(() => { + expect(updateMock).toHaveBeenCalledTimes(2); + expect(updateMock).toHaveBeenCalledWith({ + value: 30, + time: 1529899400 as UTCTimestamp, + }); + expect(updateMock).toHaveBeenCalledWith({ + value: 40, + time: 1529899500 as UTCTimestamp, + }); + }); }); -test('setOptions is called correctly', async () => { - const title = 'test title'; - const emptyMessage = 'empty message'; - const loading = false; - const priceSymbol = '$'; - - render(LightweightChart, { - title, - emptyMessage, - loading, - priceSymbol, - createSeries: (chart: IChartApi) => chart.addLineSeries(), - lightweightChartsTheme: readable({ test: 'test' }) - }); - - await waitFor(() => { - expect(applyOptionsMock).toHaveBeenCalled(); - - const callArgs = applyOptionsMock.mock.calls[0][0]; - expect(callArgs).toMatchObject({ - test: 'test' - }); - }); +test("setOptions is called correctly", async () => { + const title = "test title"; + const emptyMessage = "empty message"; + const loading = false; + const priceSymbol = "$"; + + render(LightweightChart, { + title, + emptyMessage, + loading, + priceSymbol, + createSeries: (chart: IChartApi) => chart.addLineSeries(), + lightweightChartsTheme: readable({ test: "test" }), + }); + + await waitFor(() => { + expect(applyOptionsMock).toHaveBeenCalled(); + + const callArgs = applyOptionsMock.mock.calls[0][0]; + expect(callArgs).toMatchObject({ + test: "test", + }); + }); }); -test('setTimeScale is called correctly', async () => { - const fakeNow = new Date('2025-06-15T12:00:00Z'); - vi.useFakeTimers({ shouldAdvanceTime: true }); - vi.setSystemTime(fakeNow); - - const title = 'test title'; - const emptyMessage = 'empty message'; - const loading = false; - const priceSymbol = '$'; - - const data: { value: number; time: UTCTimestamp; color?: string }[] = [ - { - value: 10, - time: 1529899200 as UTCTimestamp - }, - { - value: 20, - time: 1529899300 as UTCTimestamp - }, - { - value: 5, - time: 1529899500 as UTCTimestamp - } - ]; - - render(LightweightChart, { - title, - emptyMessage, - loading, - priceSymbol, - createSeries: (chart: IChartApi) => chart.addLineSeries(), - data, - lightweightChartsTheme: readable({ test: 'test' }) - }); - - // Simulate clicking the "30 Days" button to change the timeDelta - await waitFor(async () => { - const timeDeltaButton = screen.getByText('30 Days'); - await act(() => fireEvent.click(timeDeltaButton)); - }); - - const timeDelta = 60 * 60 * 24 * 30; // 30 days in seconds - const timeTo = Math.floor(fakeNow.getTime() / 1000) as UTCTimestamp; - const timeFrom = (timeTo - timeDelta) as UTCTimestamp; - - await waitFor(() => { - expect(setVisibleRangeMock).toHaveBeenCalledWith({ - from: timeFrom, - to: timeTo - }); - }); - - vi.useRealTimers(); +test("setTimeScale is called correctly", async () => { + const fakeNow = new Date("2025-06-15T12:00:00Z"); + vi.useFakeTimers({ shouldAdvanceTime: true }); + vi.setSystemTime(fakeNow); + + const title = "test title"; + const emptyMessage = "empty message"; + const loading = false; + const priceSymbol = "$"; + + const data: { value: number; time: UTCTimestamp; color?: string }[] = [ + { + value: 10, + time: 1529899200 as UTCTimestamp, + }, + { + value: 20, + time: 1529899300 as UTCTimestamp, + }, + { + value: 5, + time: 1529899500 as UTCTimestamp, + }, + ]; + + render(LightweightChart, { + title, + emptyMessage, + loading, + priceSymbol, + createSeries: (chart: IChartApi) => chart.addLineSeries(), + data, + lightweightChartsTheme: readable({ test: "test" }), + }); + + // Simulate clicking the "30 Days" button to change the timeDelta + await waitFor(async () => { + const timeDeltaButton = screen.getByText("30 Days"); + await act(() => fireEvent.click(timeDeltaButton)); + }); + + const timeDelta = 60 * 60 * 24 * 30; // 30 days in seconds + const timeTo = Math.floor(fakeNow.getTime() / 1000) as UTCTimestamp; + const timeFrom = (timeTo - timeDelta) as UTCTimestamp; + + await waitFor(() => { + expect(setVisibleRangeMock).toHaveBeenCalledWith({ + from: timeFrom, + to: timeTo, + }); + }); + + vi.useRealTimers(); }); -test('setupChart is called correctly', async () => { - const title = 'test title'; - const emptyMessage = 'empty message'; - const loading = false; - const priceSymbol = '$'; - - const data: { value: number; time: UTCTimestamp; color?: string }[] = [ - { - value: 10, - time: 1529899200 as UTCTimestamp - }, - { - value: 20, - time: 1529899300 as UTCTimestamp - }, - { - value: 5, - time: 1529899500 as UTCTimestamp - } - ]; - - render(LightweightChart, { - title, - emptyMessage, - loading, - priceSymbol, - createSeries: (chart: IChartApi) => chart.addLineSeries(), - data, - lightweightChartsTheme: readable({ test: 'test' }) - }); - - await waitFor(() => { - expect(screen.getByTestId('lightweightChartElement')).toBeInTheDocument(); - expect(setDataMock).toHaveBeenCalledWith(data); - }); +test("setupChart is called correctly", async () => { + const title = "test title"; + const emptyMessage = "empty message"; + const loading = false; + const priceSymbol = "$"; + + const data: { value: number; time: UTCTimestamp; color?: string }[] = [ + { + value: 10, + time: 1529899200 as UTCTimestamp, + }, + { + value: 20, + time: 1529899300 as UTCTimestamp, + }, + { + value: 5, + time: 1529899500 as UTCTimestamp, + }, + ]; + + render(LightweightChart, { + title, + emptyMessage, + loading, + priceSymbol, + createSeries: (chart: IChartApi) => chart.addLineSeries(), + data, + lightweightChartsTheme: readable({ test: "test" }), + }); + + await waitFor(() => { + expect(screen.getByTestId("lightweightChartElement")).toBeInTheDocument(); + expect(setDataMock).toHaveBeenCalledWith(data); + }); }); -test('destroyChart is called correctly', async () => { - const title = 'test title'; - const emptyMessage = 'empty message'; - const loading = false; - const priceSymbol = '$'; - - const { component } = render(LightweightChart, { - title, - emptyMessage, - loading, - priceSymbol, - createSeries: (chart: IChartApi) => chart.addLineSeries(), - lightweightChartsTheme: readable({ test: 'test' }) - }); - - component.$destroy(); - - await waitFor(() => { - expect(removeMock).toHaveBeenCalled(); - }); +test("destroyChart is called correctly", async () => { + const title = "test title"; + const emptyMessage = "empty message"; + const loading = false; + const priceSymbol = "$"; + + const { component } = render(LightweightChart, { + title, + emptyMessage, + loading, + priceSymbol, + createSeries: (chart: IChartApi) => chart.addLineSeries(), + lightweightChartsTheme: readable({ test: "test" }), + }); + + component.$destroy(); + + await waitFor(() => { + expect(removeMock).toHaveBeenCalled(); + }); }); diff --git a/packages/ui-components/src/__tests__/ListViewRaindexFilters.test.ts b/packages/ui-components/src/__tests__/ListViewRaindexFilters.test.ts index 9c75187bda..cc8d386b3c 100644 --- a/packages/ui-components/src/__tests__/ListViewRaindexFilters.test.ts +++ b/packages/ui-components/src/__tests__/ListViewRaindexFilters.test.ts @@ -1,205 +1,227 @@ -import { render, screen } from '@testing-library/svelte'; -import { readable, writable } from 'svelte/store'; -import { beforeEach, expect, test, describe, vi, type Mock } from 'vitest'; -import ListViewRaindexFilters from '../lib/components/ListViewRaindexFilters.svelte'; -import type { Address, RaindexVaultToken } from '@rainlanguage/raindex'; -import type { ComponentProps } from 'svelte'; -import type { QueryObserverResult } from '@tanstack/svelte-query'; -import { useRaindexClient } from '$lib/hooks/useRaindexClient'; - -const { mockPageStore } = await vi.hoisted(() => import('$lib/__mocks__/stores.ts')); +import { render, screen } from "@testing-library/svelte"; +import { readable, writable } from "svelte/store"; +import { beforeEach, expect, test, describe, vi, type Mock } from "vitest"; +import ListViewRaindexFilters from "../lib/components/ListViewRaindexFilters.svelte"; +import type { Address, RaindexVaultToken } from "@rainlanguage/raindex"; +import type { ComponentProps } from "svelte"; +import type { QueryObserverResult } from "@tanstack/svelte-query"; +import { useRaindexClient } from "$lib/hooks/useRaindexClient"; + +const { mockPageStore } = await vi.hoisted( + () => import("$lib/__mocks__/stores.ts"), +); const mockAccount = writable(null); -vi.mock('$lib/providers/wallet/useAccount', () => ({ - useAccount: () => ({ - account: mockAccount, - matchesAccount: vi.fn() - }) +vi.mock("$lib/providers/wallet/useAccount", () => ({ + useAccount: () => ({ + account: mockAccount, + matchesAccount: vi.fn(), + }), })); -vi.mock('$app/stores', () => ({ - page: mockPageStore +vi.mock("$app/stores", () => ({ + page: mockPageStore, })); -vi.mock('@tanstack/svelte-query', () => ({ - createInfiniteQuery: vi.fn() +vi.mock("@tanstack/svelte-query", () => ({ + createInfiniteQuery: vi.fn(), })); -vi.mock('$lib/hooks/useRaindexClient', () => ({ - useRaindexClient: vi.fn() +vi.mock("$lib/hooks/useRaindexClient", () => ({ + useRaindexClient: vi.fn(), })); type ListViewRaindexFiltersProps = ComponentProps; -describe('ListViewRaindexFilters', () => { - const mockGetAllRaindexes = vi.fn(); - - const defaultProps: ListViewRaindexFiltersProps = { - hideZeroBalanceVaults: writable(false), - hideInactiveOrdersVaults: writable(false), - selectedChainIds: writable([]), - showInactiveOrders: writable(true), - orderHash: writable('0x0234'), - activeTokens: writable([]), - selectedTokens: [], - tokensQuery: readable({ - isLoading: false, - isError: false, - data: [] as RaindexVaultToken[], - error: null - } as QueryObserverResult), - activeRaindexAddresses: writable([]), - selectedRaindexAddresses: [], - ownerFilter: writable
    ('' as unknown as Address) - } as ListViewRaindexFiltersProps; - - beforeEach(() => { - mockGetAllRaindexes.mockReturnValue({ - value: new Map(), - error: undefined - }); - - (useRaindexClient as Mock).mockReturnValue({ - getUniqueChainIds: vi.fn(() => ({ - value: [1], - error: undefined - })), - getAllNetworks: vi.fn(() => ({ - value: new Map([ - [ - 'ethereum', - { - key: 'ethereum', - rpcs: ['https://rpc.ankr.com/eth'], - chainId: 1, - networkId: 1, - currency: 'ETH' - } - ] - ]), - error: undefined - })), - getAllRaindexes: mockGetAllRaindexes - }); - - mockAccount.set(null); - }); - - test('shows no networks alert when networks are empty', () => { - (useRaindexClient as Mock).mockReturnValue({ - getAllNetworks: vi.fn(() => ({ - value: new Map(), - error: undefined - })) - }); - render(ListViewRaindexFilters, defaultProps); - - expect(screen.getByTestId('no-networks-alert')).toBeInTheDocument(); - }); - - test('shows vault-specific components on vault page', () => { - mockPageStore.mockSetSubscribeValue({ - url: { - pathname: '/vaults' - } as URL - }); - render(ListViewRaindexFilters, defaultProps); - - expect(screen.getByTestId('zero-balance-vault-checkbox')).toBeInTheDocument(); - expect(screen.getByTestId('inactive-orders-vault-checkbox')).toBeInTheDocument(); - expect(screen.queryByTestId('order-hash-input')).not.toBeInTheDocument(); - expect(screen.queryByTestId('order-status-checkbox')).not.toBeInTheDocument(); - }); - - test('shows order-specific components on orders page', () => { - mockPageStore.mockSetSubscribeValue({ - url: { - pathname: '/orders' - } as URL - }); - render(ListViewRaindexFilters, defaultProps); - - expect(screen.getByTestId('order-hash-input')).toBeInTheDocument(); - expect(screen.getByTestId('order-status-checkbox')).toBeInTheDocument(); - expect(screen.queryByTestId('zero-balance-vault-checkbox')).not.toBeInTheDocument(); - expect(screen.queryByTestId('inactive-orders-vault-checkbox')).not.toBeInTheDocument(); - }); - - test('shows common components when networks exist', () => { - render(ListViewRaindexFilters, defaultProps); - - expect(screen.getByTestId('subgraphs-dropdown')).toBeInTheDocument(); - }); - - test('does not show page-specific components on default view', () => { - mockPageStore.reset(); - render(ListViewRaindexFilters, defaultProps); - - expect(screen.queryByTestId('zero-balance-vault-checkbox')).not.toBeInTheDocument(); - expect(screen.queryByTestId('inactive-orders-vault-checkbox')).not.toBeInTheDocument(); - expect(screen.queryByTestId('order-hash-input')).not.toBeInTheDocument(); - expect(screen.queryByTestId('order-status-checkbox')).not.toBeInTheDocument(); - }); - - test('shows owner filter input', () => { - render(ListViewRaindexFilters, defaultProps); - - expect(screen.getByTestId('owner-filter-input')).toBeInTheDocument(); - }); - - test('shows raindexes dropdown when raindexes exist', () => { - mockGetAllRaindexes.mockReturnValue({ - value: new Map([ - [ - 'raindex1', - { - key: 'raindex1', - address: '0x1234567890123456789012345678901234567890', - label: 'Test Raindex', - network: { chainId: 1 } - } - ] - ]), - error: undefined - }); - - (useRaindexClient as Mock).mockReturnValue({ - getUniqueChainIds: vi.fn(() => ({ - value: [1], - error: undefined - })), - getAllNetworks: vi.fn(() => ({ - value: new Map([ - [ - 'ethereum', - { - key: 'ethereum', - rpcs: ['https://rpc.ankr.com/eth'], - chainId: 1, - networkId: 1, - currency: 'ETH' - } - ] - ]), - error: undefined - })), - getAllRaindexes: mockGetAllRaindexes - }); - - render(ListViewRaindexFilters, defaultProps); - - expect(screen.getByTestId('dropdown-raindexes-filter-button')).toBeInTheDocument(); - }); - - test('shows raindexes dropdown even when no raindexes exist', () => { - mockGetAllRaindexes.mockReturnValue({ - value: new Map(), - error: undefined - }); - - render(ListViewRaindexFilters, defaultProps); - - expect(screen.getByTestId('dropdown-raindexes-filter-button')).toBeInTheDocument(); - }); +describe("ListViewRaindexFilters", () => { + const mockGetAllRaindexes = vi.fn(); + + const defaultProps: ListViewRaindexFiltersProps = { + hideZeroBalanceVaults: writable(false), + hideInactiveOrdersVaults: writable(false), + selectedChainIds: writable([]), + showInactiveOrders: writable(true), + orderHash: writable("0x0234"), + activeTokens: writable([]), + selectedTokens: [], + tokensQuery: readable({ + isLoading: false, + isError: false, + data: [] as RaindexVaultToken[], + error: null, + } as QueryObserverResult), + activeRaindexAddresses: writable([]), + selectedRaindexAddresses: [], + ownerFilter: writable
    ("" as unknown as Address), + } as ListViewRaindexFiltersProps; + + beforeEach(() => { + mockGetAllRaindexes.mockReturnValue({ + value: new Map(), + error: undefined, + }); + + (useRaindexClient as Mock).mockReturnValue({ + getUniqueChainIds: vi.fn(() => ({ + value: [1], + error: undefined, + })), + getAllNetworks: vi.fn(() => ({ + value: new Map([ + [ + "ethereum", + { + key: "ethereum", + rpcs: ["https://rpc.ankr.com/eth"], + chainId: 1, + networkId: 1, + currency: "ETH", + }, + ], + ]), + error: undefined, + })), + getAllRaindexes: mockGetAllRaindexes, + }); + + mockAccount.set(null); + }); + + test("shows no networks alert when networks are empty", () => { + (useRaindexClient as Mock).mockReturnValue({ + getAllNetworks: vi.fn(() => ({ + value: new Map(), + error: undefined, + })), + }); + render(ListViewRaindexFilters, defaultProps); + + expect(screen.getByTestId("no-networks-alert")).toBeInTheDocument(); + }); + + test("shows vault-specific components on vault page", () => { + mockPageStore.mockSetSubscribeValue({ + url: { + pathname: "/vaults", + } as URL, + }); + render(ListViewRaindexFilters, defaultProps); + + expect( + screen.getByTestId("zero-balance-vault-checkbox"), + ).toBeInTheDocument(); + expect( + screen.getByTestId("inactive-orders-vault-checkbox"), + ).toBeInTheDocument(); + expect(screen.queryByTestId("order-hash-input")).not.toBeInTheDocument(); + expect( + screen.queryByTestId("order-status-checkbox"), + ).not.toBeInTheDocument(); + }); + + test("shows order-specific components on orders page", () => { + mockPageStore.mockSetSubscribeValue({ + url: { + pathname: "/orders", + } as URL, + }); + render(ListViewRaindexFilters, defaultProps); + + expect(screen.getByTestId("order-hash-input")).toBeInTheDocument(); + expect(screen.getByTestId("order-status-checkbox")).toBeInTheDocument(); + expect( + screen.queryByTestId("zero-balance-vault-checkbox"), + ).not.toBeInTheDocument(); + expect( + screen.queryByTestId("inactive-orders-vault-checkbox"), + ).not.toBeInTheDocument(); + }); + + test("shows common components when networks exist", () => { + render(ListViewRaindexFilters, defaultProps); + + expect(screen.getByTestId("subgraphs-dropdown")).toBeInTheDocument(); + }); + + test("does not show page-specific components on default view", () => { + mockPageStore.reset(); + render(ListViewRaindexFilters, defaultProps); + + expect( + screen.queryByTestId("zero-balance-vault-checkbox"), + ).not.toBeInTheDocument(); + expect( + screen.queryByTestId("inactive-orders-vault-checkbox"), + ).not.toBeInTheDocument(); + expect(screen.queryByTestId("order-hash-input")).not.toBeInTheDocument(); + expect( + screen.queryByTestId("order-status-checkbox"), + ).not.toBeInTheDocument(); + }); + + test("shows owner filter input", () => { + render(ListViewRaindexFilters, defaultProps); + + expect(screen.getByTestId("owner-filter-input")).toBeInTheDocument(); + }); + + test("shows raindexes dropdown when raindexes exist", () => { + mockGetAllRaindexes.mockReturnValue({ + value: new Map([ + [ + "raindex1", + { + key: "raindex1", + address: "0x1234567890123456789012345678901234567890", + label: "Test Raindex", + network: { chainId: 1 }, + }, + ], + ]), + error: undefined, + }); + + (useRaindexClient as Mock).mockReturnValue({ + getUniqueChainIds: vi.fn(() => ({ + value: [1], + error: undefined, + })), + getAllNetworks: vi.fn(() => ({ + value: new Map([ + [ + "ethereum", + { + key: "ethereum", + rpcs: ["https://rpc.ankr.com/eth"], + chainId: 1, + networkId: 1, + currency: "ETH", + }, + ], + ]), + error: undefined, + })), + getAllRaindexes: mockGetAllRaindexes, + }); + + render(ListViewRaindexFilters, defaultProps); + + expect( + screen.getByTestId("dropdown-raindexes-filter-button"), + ).toBeInTheDocument(); + }); + + test("shows raindexes dropdown even when no raindexes exist", () => { + mockGetAllRaindexes.mockReturnValue({ + value: new Map(), + error: undefined, + }); + + render(ListViewRaindexFilters, defaultProps); + + expect( + screen.getByTestId("dropdown-raindexes-filter-button"), + ).toBeInTheDocument(); + }); }); diff --git a/packages/ui-components/src/__tests__/LocalDbStatusBadge.test.ts b/packages/ui-components/src/__tests__/LocalDbStatusBadge.test.ts index 9de8f10876..a74116422f 100644 --- a/packages/ui-components/src/__tests__/LocalDbStatusBadge.test.ts +++ b/packages/ui-components/src/__tests__/LocalDbStatusBadge.test.ts @@ -1,22 +1,22 @@ -import { render, screen } from '@testing-library/svelte'; -import { describe, it, expect } from 'vitest'; -import { tick } from 'svelte'; -import LocalDbStatusBadge from '../lib/components/LocalDbStatusBadge.svelte'; +import { render, screen } from "@testing-library/svelte"; +import { describe, it, expect } from "vitest"; +import { tick } from "svelte"; +import LocalDbStatusBadge from "../lib/components/LocalDbStatusBadge.svelte"; -describe('LocalDbStatusBadge', () => { - it('renders the active state by default', () => { - render(LocalDbStatusBadge); - expect(screen.getByText('Active')).toBeInTheDocument(); - }); +describe("LocalDbStatusBadge", () => { + it("renders the active state by default", () => { + render(LocalDbStatusBadge); + expect(screen.getByText("Active")).toBeInTheDocument(); + }); - it('updates when the status store changes', async () => { - const { component } = render(LocalDbStatusBadge); - component.$set({ status: 'syncing' }); - await tick(); - expect(screen.getByText('Syncing')).toBeInTheDocument(); + it("updates when the status store changes", async () => { + const { component } = render(LocalDbStatusBadge); + component.$set({ status: "syncing" }); + await tick(); + expect(screen.getByText("Syncing")).toBeInTheDocument(); - component.$set({ status: 'failure' }); - await tick(); - expect(screen.getByText('Failure')).toBeInTheDocument(); - }); + component.$set({ status: "failure" }); + await tick(); + expect(screen.getByText("Failure")).toBeInTheDocument(); + }); }); diff --git a/packages/ui-components/src/__tests__/LocalDbStatusCard.test.ts b/packages/ui-components/src/__tests__/LocalDbStatusCard.test.ts index e500d9beb9..3b026e862f 100644 --- a/packages/ui-components/src/__tests__/LocalDbStatusCard.test.ts +++ b/packages/ui-components/src/__tests__/LocalDbStatusCard.test.ts @@ -1,152 +1,171 @@ -import { render, screen, cleanup, fireEvent } from '@testing-library/svelte'; -import { describe, it, expect, afterEach, vi } from 'vitest'; -import LocalDbStatusCard from '../lib/components/LocalDbStatusCard.svelte'; -import type { NetworkSyncStatus, RaindexSyncStatus } from '@rainlanguage/raindex'; - -vi.mock('$lib/utils/getNetworkName', () => ({ - getNetworkName: (chainId: number) => { - const names: Record = { - 1: 'Ethereum', - 137: 'Polygon', - 42161: 'Arbitrum' - }; - return names[chainId] ?? null; - } +import { render, screen, cleanup, fireEvent } from "@testing-library/svelte"; +import { describe, it, expect, afterEach, vi } from "vitest"; +import LocalDbStatusCard from "../lib/components/LocalDbStatusCard.svelte"; +import type { + NetworkSyncStatus, + RaindexSyncStatus, +} from "@rainlanguage/raindex"; + +vi.mock("$lib/utils/getNetworkName", () => ({ + getNetworkName: (chainId: number) => { + const names: Record = { + 1: "Ethereum", + 137: "Polygon", + 42161: "Arbitrum", + }; + return names[chainId] ?? null; + }, })); -describe('LocalDbStatusCard', () => { - afterEach(() => { - cleanup(); - }); - - it('renders the default label and badge', () => { - render(LocalDbStatusCard); - - expect(screen.getByText('LocalDB')).toBeInTheDocument(); - expect(screen.getByTestId('local-db-status')).toBeInTheDocument(); - }); - - it('shows active status when no networks have failures', () => { - const networkStatuses = new Map([ - [1, { chainId: 1, status: 'active', schedulerState: 'leader' }], - [137, { chainId: 137, status: 'syncing', schedulerState: 'leader' }] - ]); - - render(LocalDbStatusCard, { - props: { networkStatuses } - }); - - expect(screen.getByText('LocalDB')).toBeInTheDocument(); - expect(screen.getByText('Active')).toBeInTheDocument(); - }); - - it('shows failure status when any network has a failure', () => { - const networkStatuses = new Map([ - [1, { chainId: 1, status: 'active', schedulerState: 'leader' }], - [137, { chainId: 137, status: 'failure', schedulerState: 'leader', error: 'RPC error' }] - ]); - - render(LocalDbStatusCard, { - props: { networkStatuses } - }); - - expect(screen.getByText('LocalDB')).toBeInTheDocument(); - expect(screen.getByText('Failure')).toBeInTheDocument(); - }); - - it('shows chevron when networks are present', () => { - const networkStatuses = new Map([ - [1, { chainId: 1, status: 'active', schedulerState: 'leader' }] - ]); - - render(LocalDbStatusCard, { - props: { networkStatuses } - }); - - expect(screen.getByTestId('local-db-status-header')).toBeInTheDocument(); - }); - - it('shows active status when all networks are syncing but none failing', () => { - const networkStatuses = new Map([ - [137, { chainId: 137, status: 'syncing', schedulerState: 'leader' }], - [42161, { chainId: 42161, status: 'syncing', schedulerState: 'leader' }] - ]); - - render(LocalDbStatusCard, { - props: { networkStatuses } - }); - - expect(screen.getByText('Active')).toBeInTheDocument(); - }); - - it('shows active status when empty maps are provided', () => { - render(LocalDbStatusCard, { - props: { - networkStatuses: new Map(), - raindexStatuses: new Map() - } - }); - - expect(screen.getByText('Active')).toBeInTheDocument(); - }); - - it('accepts raindexStatuses prop', () => { - const networkStatuses = new Map([ - [137, { chainId: 137, status: 'active', schedulerState: 'leader' }] - ]); - const raindexStatuses = new Map([ - [ - '137:0x1234567890123456789012345678901234567890', - { - raindexId: { - chainId: 137, - raindexAddress: '0x1234567890123456789012345678901234567890' - }, - status: 'active', - schedulerState: 'leader' - } - ] - ]); - - render(LocalDbStatusCard, { - props: { networkStatuses, raindexStatuses } - }); - - expect(screen.getByText('Active')).toBeInTheDocument(); - }); - - it('shows failure when first network is active but second has failure', () => { - const networkStatuses = new Map([ - [1, { chainId: 1, status: 'active', schedulerState: 'leader' }], - [137, { chainId: 137, status: 'active', schedulerState: 'leader' }], - [42161, { chainId: 42161, status: 'failure', schedulerState: 'leader', error: 'Timeout' }] - ]); - - render(LocalDbStatusCard, { - props: { networkStatuses } - }); - - expect(screen.getByText('Failure')).toBeInTheDocument(); - }); - - it('opens modal when header button is clicked', async () => { - const networkStatuses = new Map([ - [137, { chainId: 137, status: 'active', schedulerState: 'leader' }] - ]); - - render(LocalDbStatusCard, { - props: { networkStatuses } - }); - - const headerButton = screen.getByTestId('local-db-status-header'); - await fireEvent.click(headerButton); - - expect(screen.getByTestId('local-db-status-modal')).toBeInTheDocument(); - }); - - it('renders data-testid on card container', () => { - render(LocalDbStatusCard); - - expect(screen.getByTestId('local-db-status-card')).toBeInTheDocument(); - }); +describe("LocalDbStatusCard", () => { + afterEach(() => { + cleanup(); + }); + + it("renders the default label and badge", () => { + render(LocalDbStatusCard); + + expect(screen.getByText("LocalDB")).toBeInTheDocument(); + expect(screen.getByTestId("local-db-status")).toBeInTheDocument(); + }); + + it("shows active status when no networks have failures", () => { + const networkStatuses = new Map([ + [1, { chainId: 1, status: "active", schedulerState: "leader" }], + [137, { chainId: 137, status: "syncing", schedulerState: "leader" }], + ]); + + render(LocalDbStatusCard, { + props: { networkStatuses }, + }); + + expect(screen.getByText("LocalDB")).toBeInTheDocument(); + expect(screen.getByText("Active")).toBeInTheDocument(); + }); + + it("shows failure status when any network has a failure", () => { + const networkStatuses = new Map([ + [1, { chainId: 1, status: "active", schedulerState: "leader" }], + [ + 137, + { + chainId: 137, + status: "failure", + schedulerState: "leader", + error: "RPC error", + }, + ], + ]); + + render(LocalDbStatusCard, { + props: { networkStatuses }, + }); + + expect(screen.getByText("LocalDB")).toBeInTheDocument(); + expect(screen.getByText("Failure")).toBeInTheDocument(); + }); + + it("shows chevron when networks are present", () => { + const networkStatuses = new Map([ + [1, { chainId: 1, status: "active", schedulerState: "leader" }], + ]); + + render(LocalDbStatusCard, { + props: { networkStatuses }, + }); + + expect(screen.getByTestId("local-db-status-header")).toBeInTheDocument(); + }); + + it("shows active status when all networks are syncing but none failing", () => { + const networkStatuses = new Map([ + [137, { chainId: 137, status: "syncing", schedulerState: "leader" }], + [42161, { chainId: 42161, status: "syncing", schedulerState: "leader" }], + ]); + + render(LocalDbStatusCard, { + props: { networkStatuses }, + }); + + expect(screen.getByText("Active")).toBeInTheDocument(); + }); + + it("shows active status when empty maps are provided", () => { + render(LocalDbStatusCard, { + props: { + networkStatuses: new Map(), + raindexStatuses: new Map(), + }, + }); + + expect(screen.getByText("Active")).toBeInTheDocument(); + }); + + it("accepts raindexStatuses prop", () => { + const networkStatuses = new Map([ + [137, { chainId: 137, status: "active", schedulerState: "leader" }], + ]); + const raindexStatuses = new Map([ + [ + "137:0x1234567890123456789012345678901234567890", + { + raindexId: { + chainId: 137, + raindexAddress: "0x1234567890123456789012345678901234567890", + }, + status: "active", + schedulerState: "leader", + }, + ], + ]); + + render(LocalDbStatusCard, { + props: { networkStatuses, raindexStatuses }, + }); + + expect(screen.getByText("Active")).toBeInTheDocument(); + }); + + it("shows failure when first network is active but second has failure", () => { + const networkStatuses = new Map([ + [1, { chainId: 1, status: "active", schedulerState: "leader" }], + [137, { chainId: 137, status: "active", schedulerState: "leader" }], + [ + 42161, + { + chainId: 42161, + status: "failure", + schedulerState: "leader", + error: "Timeout", + }, + ], + ]); + + render(LocalDbStatusCard, { + props: { networkStatuses }, + }); + + expect(screen.getByText("Failure")).toBeInTheDocument(); + }); + + it("opens modal when header button is clicked", async () => { + const networkStatuses = new Map([ + [137, { chainId: 137, status: "active", schedulerState: "leader" }], + ]); + + render(LocalDbStatusCard, { + props: { networkStatuses }, + }); + + const headerButton = screen.getByTestId("local-db-status-header"); + await fireEvent.click(headerButton); + + expect(screen.getByTestId("local-db-status-modal")).toBeInTheDocument(); + }); + + it("renders data-testid on card container", () => { + render(LocalDbStatusCard); + + expect(screen.getByTestId("local-db-status-card")).toBeInTheDocument(); + }); }); diff --git a/packages/ui-components/src/__tests__/LocalDbStatusModal.test.ts b/packages/ui-components/src/__tests__/LocalDbStatusModal.test.ts index 49681786a4..881ed4bedd 100644 --- a/packages/ui-components/src/__tests__/LocalDbStatusModal.test.ts +++ b/packages/ui-components/src/__tests__/LocalDbStatusModal.test.ts @@ -1,405 +1,426 @@ -import { describe, it, expect, afterEach, vi } from 'vitest'; -import { render, screen, cleanup } from '@testing-library/svelte'; -import LocalDbStatusModal from '../lib/components/LocalDbStatusModal.svelte'; -import type { NetworkSyncStatus, RaindexSyncStatus } from '@rainlanguage/raindex'; - -vi.mock('$lib/utils/getNetworkName', () => ({ - getNetworkName: (chainId: number) => { - const names: Record = { - 137: 'Polygon', - 42161: 'Arbitrum', - 8453: 'Base' - }; - return names[chainId] ?? null; - } +import { describe, it, expect, afterEach, vi } from "vitest"; +import { render, screen, cleanup } from "@testing-library/svelte"; +import LocalDbStatusModal from "../lib/components/LocalDbStatusModal.svelte"; +import type { + NetworkSyncStatus, + RaindexSyncStatus, +} from "@rainlanguage/raindex"; + +vi.mock("$lib/utils/getNetworkName", () => ({ + getNetworkName: (chainId: number) => { + const names: Record = { + 137: "Polygon", + 42161: "Arbitrum", + 8453: "Base", + }; + return names[chainId] ?? null; + }, })); -describe('LocalDbStatusModal', () => { - afterEach(() => { - cleanup(); - }); - - it('renders modal with header when open', () => { - render(LocalDbStatusModal, { - props: { - open: true, - networkStatuses: new Map(), - raindexStatuses: new Map() - } - }); - - expect(screen.getByText('Database Sync Status')).toBeInTheDocument(); - }); - - it('shows empty state message when no networks are syncing', () => { - render(LocalDbStatusModal, { - props: { - open: true, - networkStatuses: new Map(), - raindexStatuses: new Map() - } - }); - - expect(screen.getByText('No networks are being synced.')).toBeInTheDocument(); - }); - - it('renders network groups with correct network names', () => { - const networkStatuses = new Map([ - [137, { chainId: 137, status: 'active', schedulerState: 'leader' }], - [42161, { chainId: 42161, status: 'syncing', schedulerState: 'leader' }] - ]); - - render(LocalDbStatusModal, { - props: { - open: true, - networkStatuses, - raindexStatuses: new Map() - } - }); - - expect(screen.getByText('Polygon')).toBeInTheDocument(); - expect(screen.getByText('Arbitrum')).toBeInTheDocument(); - }); - - it('falls back to chain ID when network name is unknown', () => { - const networkStatuses = new Map([ - [99999, { chainId: 99999, status: 'active', schedulerState: 'leader' }] - ]); - - render(LocalDbStatusModal, { - props: { - open: true, - networkStatuses, - raindexStatuses: new Map() - } - }); - - expect(screen.getByText('Chain 99999')).toBeInTheDocument(); - }); - - it('shows Observing badge when schedulerState is notLeader', () => { - const networkStatuses = new Map([ - [137, { chainId: 137, status: 'active', schedulerState: 'notLeader' }] - ]); - - render(LocalDbStatusModal, { - props: { - open: true, - networkStatuses, - raindexStatuses: new Map() - } - }); - - expect(screen.getByText('Observing')).toBeInTheDocument(); - }); - - it('does not show Observing badge when schedulerState is leader', () => { - const networkStatuses = new Map([ - [137, { chainId: 137, status: 'active', schedulerState: 'leader' }] - ]); - - render(LocalDbStatusModal, { - props: { - open: true, - networkStatuses, - raindexStatuses: new Map() - } - }); - - expect(screen.queryByText('Observing')).not.toBeInTheDocument(); - }); - - it('displays raindex addresses under their network', () => { - const networkStatuses = new Map([ - [137, { chainId: 137, status: 'active', schedulerState: 'leader' }] - ]); - const raindexStatuses = new Map([ - [ - '137:0x1234567890123456789012345678901234567890', - { - raindexId: { - chainId: 137, - raindexAddress: '0x1234567890123456789012345678901234567890' - }, - status: 'active', - schedulerState: 'leader' - } - ] - ]); - - render(LocalDbStatusModal, { - props: { - open: true, - networkStatuses, - raindexStatuses - } - }); - - expect(screen.getByText('0x1234567890123456789012345678901234567890')).toBeInTheDocument(); - }); - - it('shows phase message when raindex is syncing', () => { - const networkStatuses = new Map([ - [137, { chainId: 137, status: 'syncing', schedulerState: 'leader' }] - ]); - const raindexStatuses = new Map([ - [ - '137:0x1234567890123456789012345678901234567890', - { - raindexId: { - chainId: 137, - raindexAddress: '0x1234567890123456789012345678901234567890' - }, - status: 'syncing', - schedulerState: 'leader', - phaseMessage: 'Fetching latest block' - } - ] - ]); - - render(LocalDbStatusModal, { - props: { - open: true, - networkStatuses, - raindexStatuses - } - }); - - expect(screen.getByText('Fetching latest block')).toBeInTheDocument(); - }); - - it('does not show phase message when raindex status is not syncing', () => { - const networkStatuses = new Map([ - [137, { chainId: 137, status: 'active', schedulerState: 'leader' }] - ]); - const raindexStatuses = new Map([ - [ - '137:0x1234567890123456789012345678901234567890', - { - raindexId: { - chainId: 137, - raindexAddress: '0x1234567890123456789012345678901234567890' - }, - status: 'active', - schedulerState: 'leader', - phaseMessage: 'This should not appear' - } - ] - ]); - - render(LocalDbStatusModal, { - props: { - open: true, - networkStatuses, - raindexStatuses - } - }); - - expect(screen.queryByText('This should not appear')).not.toBeInTheDocument(); - }); - - it('shows error message when raindex has failure', () => { - const networkStatuses = new Map([ - [137, { chainId: 137, status: 'failure', schedulerState: 'leader' }] - ]); - const raindexStatuses = new Map([ - [ - '137:0x1234567890123456789012345678901234567890', - { - raindexId: { - chainId: 137, - raindexAddress: '0x1234567890123456789012345678901234567890' - }, - status: 'failure', - schedulerState: 'leader', - error: 'RPC connection failed' - } - ] - ]); - - render(LocalDbStatusModal, { - props: { - open: true, - networkStatuses, - raindexStatuses - } - }); - - expect(screen.getByText('RPC connection failed')).toBeInTheDocument(); - }); - - it('shows network-level error when network has failure', () => { - const networkStatuses = new Map([ - [ - 137, - { - chainId: 137, - status: 'failure', - schedulerState: 'leader', - error: 'Network initialization failed' - } - ] - ]); - - render(LocalDbStatusModal, { - props: { - open: true, - networkStatuses, - raindexStatuses: new Map() - } - }); - - expect(screen.getByText('Network initialization failed')).toBeInTheDocument(); - }); - - it('groups raindexes correctly by chain ID', () => { - const networkStatuses = new Map([ - [137, { chainId: 137, status: 'active', schedulerState: 'leader' }], - [42161, { chainId: 42161, status: 'active', schedulerState: 'leader' }] - ]); - const raindexStatuses = new Map([ - [ - '137:0x1111111111111111111111111111111111111111', - { - raindexId: { - chainId: 137, - raindexAddress: '0x1111111111111111111111111111111111111111' - }, - status: 'active', - schedulerState: 'leader' - } - ], - [ - '42161:0x2222222222222222222222222222222222222222', - { - raindexId: { - chainId: 42161, - raindexAddress: '0x2222222222222222222222222222222222222222' - }, - status: 'syncing', - schedulerState: 'leader' - } - ] - ]); - - render(LocalDbStatusModal, { - props: { - open: true, - networkStatuses, - raindexStatuses - } - }); - - const polygonGroup = screen.getByTestId('network-group-137'); - const arbitrumGroup = screen.getByTestId('network-group-42161'); - - expect(polygonGroup).toBeInTheDocument(); - expect(arbitrumGroup).toBeInTheDocument(); - expect(screen.getByText('0x1111111111111111111111111111111111111111')).toBeInTheDocument(); - expect(screen.getByText('0x2222222222222222222222222222222222222222')).toBeInTheDocument(); - }); - - it('handles multiple raindexes on the same network', () => { - const networkStatuses = new Map([ - [137, { chainId: 137, status: 'active', schedulerState: 'leader' }] - ]); - const raindexStatuses = new Map([ - [ - '137:0x1111111111111111111111111111111111111111', - { - raindexId: { - chainId: 137, - raindexAddress: '0x1111111111111111111111111111111111111111' - }, - status: 'active', - schedulerState: 'leader' - } - ], - [ - '137:0x2222222222222222222222222222222222222222', - { - raindexId: { - chainId: 137, - raindexAddress: '0x2222222222222222222222222222222222222222' - }, - status: 'syncing', - schedulerState: 'leader', - phaseMessage: 'Running bootstrap' - } - ] - ]); - - render(LocalDbStatusModal, { - props: { - open: true, - networkStatuses, - raindexStatuses - } - }); - - expect(screen.getByText('0x1111111111111111111111111111111111111111')).toBeInTheDocument(); - expect(screen.getByText('0x2222222222222222222222222222222222222222')).toBeInTheDocument(); - expect(screen.getByText('Running bootstrap')).toBeInTheDocument(); - }); - - it('does not show raindex error when status is not failure', () => { - const networkStatuses = new Map([ - [137, { chainId: 137, status: 'active', schedulerState: 'leader' }] - ]); - const raindexStatuses = new Map([ - [ - '137:0x1234567890123456789012345678901234567890', - { - raindexId: { - chainId: 137, - raindexAddress: '0x1234567890123456789012345678901234567890' - }, - status: 'active', - schedulerState: 'leader', - error: 'This error should not appear' - } - ] - ]); - - render(LocalDbStatusModal, { - props: { - open: true, - networkStatuses, - raindexStatuses - } - }); - - expect(screen.queryByText('This error should not appear')).not.toBeInTheDocument(); - }); - - it('does not show phase message when schedulerState is notLeader even if status is syncing', () => { - const networkStatuses = new Map([ - [137, { chainId: 137, status: 'syncing', schedulerState: 'notLeader' }] - ]); - const raindexStatuses = new Map([ - [ - '137:0x1234567890123456789012345678901234567890', - { - raindexId: { - chainId: 137, - raindexAddress: '0x1234567890123456789012345678901234567890' - }, - status: 'syncing', - schedulerState: 'notLeader', - phaseMessage: 'Fetching latest block' - } - ] - ]); - - render(LocalDbStatusModal, { - props: { - open: true, - networkStatuses, - raindexStatuses - } - }); - - expect(screen.getByText('Observing')).toBeInTheDocument(); - expect(screen.queryByText('Fetching latest block')).not.toBeInTheDocument(); - }); +describe("LocalDbStatusModal", () => { + afterEach(() => { + cleanup(); + }); + + it("renders modal with header when open", () => { + render(LocalDbStatusModal, { + props: { + open: true, + networkStatuses: new Map(), + raindexStatuses: new Map(), + }, + }); + + expect(screen.getByText("Database Sync Status")).toBeInTheDocument(); + }); + + it("shows empty state message when no networks are syncing", () => { + render(LocalDbStatusModal, { + props: { + open: true, + networkStatuses: new Map(), + raindexStatuses: new Map(), + }, + }); + + expect( + screen.getByText("No networks are being synced."), + ).toBeInTheDocument(); + }); + + it("renders network groups with correct network names", () => { + const networkStatuses = new Map([ + [137, { chainId: 137, status: "active", schedulerState: "leader" }], + [42161, { chainId: 42161, status: "syncing", schedulerState: "leader" }], + ]); + + render(LocalDbStatusModal, { + props: { + open: true, + networkStatuses, + raindexStatuses: new Map(), + }, + }); + + expect(screen.getByText("Polygon")).toBeInTheDocument(); + expect(screen.getByText("Arbitrum")).toBeInTheDocument(); + }); + + it("falls back to chain ID when network name is unknown", () => { + const networkStatuses = new Map([ + [99999, { chainId: 99999, status: "active", schedulerState: "leader" }], + ]); + + render(LocalDbStatusModal, { + props: { + open: true, + networkStatuses, + raindexStatuses: new Map(), + }, + }); + + expect(screen.getByText("Chain 99999")).toBeInTheDocument(); + }); + + it("shows Observing badge when schedulerState is notLeader", () => { + const networkStatuses = new Map([ + [137, { chainId: 137, status: "active", schedulerState: "notLeader" }], + ]); + + render(LocalDbStatusModal, { + props: { + open: true, + networkStatuses, + raindexStatuses: new Map(), + }, + }); + + expect(screen.getByText("Observing")).toBeInTheDocument(); + }); + + it("does not show Observing badge when schedulerState is leader", () => { + const networkStatuses = new Map([ + [137, { chainId: 137, status: "active", schedulerState: "leader" }], + ]); + + render(LocalDbStatusModal, { + props: { + open: true, + networkStatuses, + raindexStatuses: new Map(), + }, + }); + + expect(screen.queryByText("Observing")).not.toBeInTheDocument(); + }); + + it("displays raindex addresses under their network", () => { + const networkStatuses = new Map([ + [137, { chainId: 137, status: "active", schedulerState: "leader" }], + ]); + const raindexStatuses = new Map([ + [ + "137:0x1234567890123456789012345678901234567890", + { + raindexId: { + chainId: 137, + raindexAddress: "0x1234567890123456789012345678901234567890", + }, + status: "active", + schedulerState: "leader", + }, + ], + ]); + + render(LocalDbStatusModal, { + props: { + open: true, + networkStatuses, + raindexStatuses, + }, + }); + + expect( + screen.getByText("0x1234567890123456789012345678901234567890"), + ).toBeInTheDocument(); + }); + + it("shows phase message when raindex is syncing", () => { + const networkStatuses = new Map([ + [137, { chainId: 137, status: "syncing", schedulerState: "leader" }], + ]); + const raindexStatuses = new Map([ + [ + "137:0x1234567890123456789012345678901234567890", + { + raindexId: { + chainId: 137, + raindexAddress: "0x1234567890123456789012345678901234567890", + }, + status: "syncing", + schedulerState: "leader", + phaseMessage: "Fetching latest block", + }, + ], + ]); + + render(LocalDbStatusModal, { + props: { + open: true, + networkStatuses, + raindexStatuses, + }, + }); + + expect(screen.getByText("Fetching latest block")).toBeInTheDocument(); + }); + + it("does not show phase message when raindex status is not syncing", () => { + const networkStatuses = new Map([ + [137, { chainId: 137, status: "active", schedulerState: "leader" }], + ]); + const raindexStatuses = new Map([ + [ + "137:0x1234567890123456789012345678901234567890", + { + raindexId: { + chainId: 137, + raindexAddress: "0x1234567890123456789012345678901234567890", + }, + status: "active", + schedulerState: "leader", + phaseMessage: "This should not appear", + }, + ], + ]); + + render(LocalDbStatusModal, { + props: { + open: true, + networkStatuses, + raindexStatuses, + }, + }); + + expect( + screen.queryByText("This should not appear"), + ).not.toBeInTheDocument(); + }); + + it("shows error message when raindex has failure", () => { + const networkStatuses = new Map([ + [137, { chainId: 137, status: "failure", schedulerState: "leader" }], + ]); + const raindexStatuses = new Map([ + [ + "137:0x1234567890123456789012345678901234567890", + { + raindexId: { + chainId: 137, + raindexAddress: "0x1234567890123456789012345678901234567890", + }, + status: "failure", + schedulerState: "leader", + error: "RPC connection failed", + }, + ], + ]); + + render(LocalDbStatusModal, { + props: { + open: true, + networkStatuses, + raindexStatuses, + }, + }); + + expect(screen.getByText("RPC connection failed")).toBeInTheDocument(); + }); + + it("shows network-level error when network has failure", () => { + const networkStatuses = new Map([ + [ + 137, + { + chainId: 137, + status: "failure", + schedulerState: "leader", + error: "Network initialization failed", + }, + ], + ]); + + render(LocalDbStatusModal, { + props: { + open: true, + networkStatuses, + raindexStatuses: new Map(), + }, + }); + + expect( + screen.getByText("Network initialization failed"), + ).toBeInTheDocument(); + }); + + it("groups raindexes correctly by chain ID", () => { + const networkStatuses = new Map([ + [137, { chainId: 137, status: "active", schedulerState: "leader" }], + [42161, { chainId: 42161, status: "active", schedulerState: "leader" }], + ]); + const raindexStatuses = new Map([ + [ + "137:0x1111111111111111111111111111111111111111", + { + raindexId: { + chainId: 137, + raindexAddress: "0x1111111111111111111111111111111111111111", + }, + status: "active", + schedulerState: "leader", + }, + ], + [ + "42161:0x2222222222222222222222222222222222222222", + { + raindexId: { + chainId: 42161, + raindexAddress: "0x2222222222222222222222222222222222222222", + }, + status: "syncing", + schedulerState: "leader", + }, + ], + ]); + + render(LocalDbStatusModal, { + props: { + open: true, + networkStatuses, + raindexStatuses, + }, + }); + + const polygonGroup = screen.getByTestId("network-group-137"); + const arbitrumGroup = screen.getByTestId("network-group-42161"); + + expect(polygonGroup).toBeInTheDocument(); + expect(arbitrumGroup).toBeInTheDocument(); + expect( + screen.getByText("0x1111111111111111111111111111111111111111"), + ).toBeInTheDocument(); + expect( + screen.getByText("0x2222222222222222222222222222222222222222"), + ).toBeInTheDocument(); + }); + + it("handles multiple raindexes on the same network", () => { + const networkStatuses = new Map([ + [137, { chainId: 137, status: "active", schedulerState: "leader" }], + ]); + const raindexStatuses = new Map([ + [ + "137:0x1111111111111111111111111111111111111111", + { + raindexId: { + chainId: 137, + raindexAddress: "0x1111111111111111111111111111111111111111", + }, + status: "active", + schedulerState: "leader", + }, + ], + [ + "137:0x2222222222222222222222222222222222222222", + { + raindexId: { + chainId: 137, + raindexAddress: "0x2222222222222222222222222222222222222222", + }, + status: "syncing", + schedulerState: "leader", + phaseMessage: "Running bootstrap", + }, + ], + ]); + + render(LocalDbStatusModal, { + props: { + open: true, + networkStatuses, + raindexStatuses, + }, + }); + + expect( + screen.getByText("0x1111111111111111111111111111111111111111"), + ).toBeInTheDocument(); + expect( + screen.getByText("0x2222222222222222222222222222222222222222"), + ).toBeInTheDocument(); + expect(screen.getByText("Running bootstrap")).toBeInTheDocument(); + }); + + it("does not show raindex error when status is not failure", () => { + const networkStatuses = new Map([ + [137, { chainId: 137, status: "active", schedulerState: "leader" }], + ]); + const raindexStatuses = new Map([ + [ + "137:0x1234567890123456789012345678901234567890", + { + raindexId: { + chainId: 137, + raindexAddress: "0x1234567890123456789012345678901234567890", + }, + status: "active", + schedulerState: "leader", + error: "This error should not appear", + }, + ], + ]); + + render(LocalDbStatusModal, { + props: { + open: true, + networkStatuses, + raindexStatuses, + }, + }); + + expect( + screen.queryByText("This error should not appear"), + ).not.toBeInTheDocument(); + }); + + it("does not show phase message when schedulerState is notLeader even if status is syncing", () => { + const networkStatuses = new Map([ + [137, { chainId: 137, status: "syncing", schedulerState: "notLeader" }], + ]); + const raindexStatuses = new Map([ + [ + "137:0x1234567890123456789012345678901234567890", + { + raindexId: { + chainId: 137, + raindexAddress: "0x1234567890123456789012345678901234567890", + }, + status: "syncing", + schedulerState: "notLeader", + phaseMessage: "Fetching latest block", + }, + ], + ]); + + render(LocalDbStatusModal, { + props: { + open: true, + networkStatuses, + raindexStatuses, + }, + }); + + expect(screen.getByText("Observing")).toBeInTheDocument(); + expect(screen.queryByText("Fetching latest block")).not.toBeInTheDocument(); + }); }); diff --git a/packages/ui-components/src/__tests__/OrderAPY.test.ts b/packages/ui-components/src/__tests__/OrderAPY.test.ts index 0cce0e39c1..d717a877be 100644 --- a/packages/ui-components/src/__tests__/OrderAPY.test.ts +++ b/packages/ui-components/src/__tests__/OrderAPY.test.ts @@ -1,6 +1,6 @@ // import { render, screen, waitFor } from '@testing-library/svelte'; // import { test, vi } from 'vitest'; -import { test } from 'vitest'; +import { test } from "vitest"; // import { expect } from '$lib/test/matchers'; // import type { OrderPerformance, RaindexOrder } from '@rainlanguage/raindex'; // import { QueryClient } from '@tanstack/svelte-query'; @@ -32,23 +32,23 @@ import { test } from 'vitest'; // }; // TODO: Issue #1989 -test('renders table with correct data', async () => { - // const queryClient = new QueryClient(); - // const mockOrder: RaindexOrder = { - // id: '1', - // getPerformance: vi.fn().mockResolvedValue({ value: mockOrderApy }) - // } as unknown as RaindexOrder; - // render(OrderApy, { - // context: new Map([['$$_queryClient', queryClient]]), - // props: { order: mockOrder } - // }); - // await waitFor(async () => { - // // get apy row - // const rows = screen.getAllByTestId('apy-field'); - // // checking - // const display = - // (mockOrderApy.denominatedPerformance!.apyIsNeg ? '-' : '') + - // bigintStringToPercentage(mockOrderApy.denominatedPerformance!.apy, 18, 5); - // expect(rows[0]).toHaveTextContent(display); - // }); +test("renders table with correct data", async () => { + // const queryClient = new QueryClient(); + // const mockOrder: RaindexOrder = { + // id: '1', + // getPerformance: vi.fn().mockResolvedValue({ value: mockOrderApy }) + // } as unknown as RaindexOrder; + // render(OrderApy, { + // context: new Map([['$$_queryClient', queryClient]]), + // props: { order: mockOrder } + // }); + // await waitFor(async () => { + // // get apy row + // const rows = screen.getAllByTestId('apy-field'); + // // checking + // const display = + // (mockOrderApy.denominatedPerformance!.apyIsNeg ? '-' : '') + + // bigintStringToPercentage(mockOrderApy.denominatedPerformance!.apy, 18, 5); + // expect(rows[0]).toHaveTextContent(display); + // }); }); diff --git a/packages/ui-components/src/__tests__/OrderDetail.test.ts b/packages/ui-components/src/__tests__/OrderDetail.test.ts index 62c93419ba..df1d6f54ad 100644 --- a/packages/ui-components/src/__tests__/OrderDetail.test.ts +++ b/packages/ui-components/src/__tests__/OrderDetail.test.ts @@ -1,653 +1,695 @@ -import { render, screen, waitFor } from '@testing-library/svelte'; +import { render, screen, waitFor } from "@testing-library/svelte"; import { - RaindexClient, - RaindexOrder, - RaindexTransaction, - RaindexVault -} from '@rainlanguage/raindex'; -import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; -import { QueryClient } from '@tanstack/svelte-query'; -import OrderDetail from '../lib/components/detail/OrderDetail.svelte'; -import { readable, writable } from 'svelte/store'; -import { darkChartTheme } from '../lib/utils/lightweightChartsThemes'; -import userEvent from '@testing-library/user-event'; -import { useAccount } from '$lib/providers/wallet/useAccount'; -import type { ComponentProps } from 'svelte'; -import { invalidateTanstackQueries } from '$lib/queries/queryClient'; -import { useToasts } from '$lib/providers/toasts/useToasts'; -import { useRaindexClient } from '$lib/hooks/useRaindexClient'; -import { getExplorerLink } from '$lib/services/getExplorerLink'; - -vi.mock('$lib/hooks/useRaindexClient', () => ({ - useRaindexClient: vi.fn() + RaindexClient, + RaindexOrder, + RaindexTransaction, + RaindexVault, +} from "@rainlanguage/raindex"; +import { describe, it, expect, vi, beforeEach, type Mock } from "vitest"; +import { QueryClient } from "@tanstack/svelte-query"; +import OrderDetail from "../lib/components/detail/OrderDetail.svelte"; +import { readable, writable } from "svelte/store"; +import { darkChartTheme } from "../lib/utils/lightweightChartsThemes"; +import userEvent from "@testing-library/user-event"; +import { useAccount } from "$lib/providers/wallet/useAccount"; +import type { ComponentProps } from "svelte"; +import { invalidateTanstackQueries } from "$lib/queries/queryClient"; +import { useToasts } from "$lib/providers/toasts/useToasts"; +import { useRaindexClient } from "$lib/hooks/useRaindexClient"; +import { getExplorerLink } from "$lib/services/getExplorerLink"; + +vi.mock("$lib/hooks/useRaindexClient", () => ({ + useRaindexClient: vi.fn(), })); // Mock the account hook -vi.mock('$lib/providers/wallet/useAccount', () => ({ - useAccount: vi.fn() +vi.mock("$lib/providers/wallet/useAccount", () => ({ + useAccount: vi.fn(), })); // Mock the js_api functions -vi.mock('@rainlanguage/raindex', () => ({ - RaindexClient: vi.fn() +vi.mock("@rainlanguage/raindex", () => ({ + RaindexClient: vi.fn(), })); // Mock the query client functions -vi.mock('$lib/queries/queryClient', () => ({ - invalidateTanstackQueries: vi.fn() +vi.mock("$lib/queries/queryClient", () => ({ + invalidateTanstackQueries: vi.fn(), })); const mockErrToast = vi.fn(); -vi.mock('$lib/providers/toasts/useToasts', () => ({ - useToasts: vi.fn() +vi.mock("$lib/providers/toasts/useToasts", () => ({ + useToasts: vi.fn(), })); -vi.mock('$lib/components/charts/OrderTradesChart.svelte', async () => { - const mockLightweightCharts = (await import('../lib/__mocks__/MockComponent.svelte')).default; - return { default: mockLightweightCharts }; +vi.mock("$lib/components/charts/OrderTradesChart.svelte", async () => { + const mockLightweightCharts = ( + await import("../lib/__mocks__/MockComponent.svelte") + ).default; + return { default: mockLightweightCharts }; }); -vi.mock('$lib/components/CodeMirrorRainlang.svelte', async () => { - const mockCodeMirror = (await import('../lib/__mocks__/CodeMirrorRainlang.svelte')).default; - return { default: mockCodeMirror }; +vi.mock("$lib/components/CodeMirrorRainlang.svelte", async () => { + const mockCodeMirror = ( + await import("../lib/__mocks__/CodeMirrorRainlang.svelte") + ).default; + return { default: mockCodeMirror }; }); -vi.mock('$lib/services/getExplorerLink', () => ({ - getExplorerLink: vi.fn() +vi.mock("$lib/services/getExplorerLink", () => ({ + getExplorerLink: vi.fn(), })); -const raindexAddress = '0x123456789012345678901234567890123456abcd'; -const orderHash = '0x0234'; +const raindexAddress = "0x123456789012345678901234567890123456abcd"; +const orderHash = "0x0234"; const defaultProps: ComponentProps = { - chainId: 1, - raindexAddress, - orderHash, - codeMirrorTheme: readable('dark'), - lightweightChartsTheme: readable(darkChartTheme), - onRemove: vi.fn(), - onDeposit: vi.fn(), - onWithdraw: vi.fn(), - onWithdrawAll: vi.fn() + chainId: 1, + raindexAddress, + orderHash, + codeMirrorTheme: readable("dark"), + lightweightChartsTheme: readable(darkChartTheme), + onRemove: vi.fn(), + onDeposit: vi.fn(), + onWithdraw: vi.fn(), + onWithdrawAll: vi.fn(), }; const mockVaultsList = () => ({ - items: [], - getWithdrawableVaults: () => ({ value: [], error: null }) + items: [], + getWithdrawableVaults: () => ({ value: [], error: null }), }); const mockOrder: RaindexOrder = { - chainId: 1, - raindex: raindexAddress, - id: 'mockId', - orderBytes: '0x0000000000000000000000000000000000000000...', - orderHash: orderHash, - owner: '0x1234567890123456789012345678901234567890', - active: true, - meta: undefined, - rainlang: undefined, - timestampAdded: BigInt(1234567890), - inputsList: mockVaultsList(), - outputsList: mockVaultsList(), - inputsOutputsList: mockVaultsList(), - vaultsList: { - ...mockVaultsList(), - items: [ - { - chainId: 1, - vaultType: 'input', - id: '0x0000000000000000000000000000000000000002', - token: { - id: '0x0000000000000000000000000000000000000000', - address: '0x0000000000000000000000000000000000000000', - name: 'MockToken', - symbol: 'MCK', - decimals: '18' - }, - balance: BigInt(0), - vaultId: BigInt(2), - owner: '0x1234567890123456789012345678901234567890', - ordersAsOutput: [], - ordersAsInput: [], - raindex: raindexAddress - } as unknown as RaindexVault, - { - chainId: 1, - vaultType: 'output', - id: '0x0000000000000000000000000000000000000001', - token: { - id: '0x0000000000000000000000000000000000000000', - address: '0x0000000000000000000000000000000000000000', - name: 'MockToken2', - symbol: 'MCK2', - decimals: '18' - }, - balance: BigInt(0), - vaultId: BigInt(1), - owner: '0x1234567890123456789012345678901234567890', - ordersAsOutput: [], - ordersAsInput: [], - raindex: raindexAddress - } as unknown as RaindexVault - ] - }, - transaction: { - blockNumber: BigInt(12345678), - timestamp: BigInt(1234567890), - id: '0x0000000000000000000000000000000000000000', - from: '0x1234567890123456789012345678901234567890' - } as unknown as RaindexTransaction, - tradesCount: 0 + chainId: 1, + raindex: raindexAddress, + id: "mockId", + orderBytes: "0x0000000000000000000000000000000000000000...", + orderHash: orderHash, + owner: "0x1234567890123456789012345678901234567890", + active: true, + meta: undefined, + rainlang: undefined, + timestampAdded: BigInt(1234567890), + inputsList: mockVaultsList(), + outputsList: mockVaultsList(), + inputsOutputsList: mockVaultsList(), + vaultsList: { + ...mockVaultsList(), + items: [ + { + chainId: 1, + vaultType: "input", + id: "0x0000000000000000000000000000000000000002", + token: { + id: "0x0000000000000000000000000000000000000000", + address: "0x0000000000000000000000000000000000000000", + name: "MockToken", + symbol: "MCK", + decimals: "18", + }, + balance: BigInt(0), + vaultId: BigInt(2), + owner: "0x1234567890123456789012345678901234567890", + ordersAsOutput: [], + ordersAsInput: [], + raindex: raindexAddress, + } as unknown as RaindexVault, + { + chainId: 1, + vaultType: "output", + id: "0x0000000000000000000000000000000000000001", + token: { + id: "0x0000000000000000000000000000000000000000", + address: "0x0000000000000000000000000000000000000000", + name: "MockToken2", + symbol: "MCK2", + decimals: "18", + }, + balance: BigInt(0), + vaultId: BigInt(1), + owner: "0x1234567890123456789012345678901234567890", + ordersAsOutput: [], + ordersAsInput: [], + raindex: raindexAddress, + } as unknown as RaindexVault, + ], + }, + transaction: { + blockNumber: BigInt(12345678), + timestamp: BigInt(1234567890), + id: "0x0000000000000000000000000000000000000000", + from: "0x1234567890123456789012345678901234567890", + } as unknown as RaindexTransaction, + tradesCount: 0, } as unknown as RaindexOrder; const mockMatchesAccount = vi.fn(); -describe('OrderDetail', () => { - let queryClient: QueryClient; - let mockRaindexClient: RaindexClient; - const resolveOrder = (override: Partial = {}) => - (mockRaindexClient.getOrderByHash as Mock).mockResolvedValue({ - value: { ...mockOrder, ...override } - }); - - beforeEach(async () => { - vi.clearAllMocks(); - vi.resetAllMocks(); - queryClient = new QueryClient(); - - (useAccount as Mock).mockReturnValue({ - matchesAccount: mockMatchesAccount - }); - - mockRaindexClient = { - getOrderByHash: vi.fn().mockResolvedValue({ - value: mockOrder - }) - } as unknown as RaindexClient; - (useRaindexClient as Mock).mockReturnValue(mockRaindexClient); - - (useToasts as Mock).mockReturnValue({ - toasts: writable([]), - errToast: mockErrToast, - removeToast: vi.fn() - }); - - (getExplorerLink as Mock).mockReturnValue( - 'https://etherscan.io/address/0x1234567890123456789012345678901234567890' - ); - }); - - it('calls the order detail query with the correct order hash', async () => { - render(OrderDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - expect(mockRaindexClient.getOrderByHash).toHaveBeenCalledWith(1, raindexAddress, orderHash); - }); - - it('shows the correct empty message when the query returns no data', async () => { - (mockRaindexClient.getOrderByHash as Mock).mockResolvedValue({ value: null }); - - render(OrderDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - expect(screen.getByText('Order not found')).toBeInTheDocument(); - }); - }); - - it('shows the correct data when the query returns data', async () => { - render(OrderDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - expect(screen.getByText('Order')).toBeInTheDocument(); - expect(screen.getByText('Raindex')).toBeInTheDocument(); - expect(screen.getByText('Owner')).toBeInTheDocument(); - expect(screen.getByText('Created')).toBeInTheDocument(); - expect(screen.getByText(raindexAddress)).toBeInTheDocument(); - expect(screen.getByText('0x1234567890123456789012345678901234567890')).toBeInTheDocument(); - }); - }); - - it('shows remove button if owner wallet matches and order is active', async () => { - mockMatchesAccount.mockReturnValue(true); - render(OrderDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - const removeButton = screen.getByTestId('remove-button'); - expect(removeButton).toBeInTheDocument(); - expect(defaultProps.onRemove).not.toHaveBeenCalled(); - }); - - await userEvent.click(screen.getByTestId('remove-button')); - - await waitFor(() => { - expect(defaultProps.onRemove).toHaveBeenCalledWith(mockRaindexClient, mockOrder); - }); - }); - - it('does not show remove button if account does not match owner', async () => { - mockMatchesAccount.mockReturnValue(false); - - render(OrderDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - expect(screen.queryByTestId('remove-button')).not.toBeInTheDocument(); - }); - }); - - it('does not show remove button if order is not active', async () => { - // Modify the mock to return an inactive order - (mockRaindexClient.getOrderByHash as Mock).mockResolvedValue({ - value: { - ...mockOrder, - active: false - } - }); - - render(OrderDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - expect(screen.queryByTestId('remove-button')).not.toBeInTheDocument(); - }); - }); - - it('refresh button triggers query invalidation when clicked', async () => { - render(OrderDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(async () => { - const refreshButton = screen.getByTestId('top-refresh'); - await userEvent.click(refreshButton); - - expect(invalidateTanstackQueries).toHaveBeenCalledWith(queryClient, [orderHash]); - }); - }); - - it('failed query invalidation triggers a toast', async () => { - (invalidateTanstackQueries as Mock).mockRejectedValue(new Error('Failed to refresh')); - - render(OrderDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(async () => { - const refreshButton = screen.getByTestId('top-refresh'); - await userEvent.click(refreshButton); - }); - - await waitFor(() => { - expect(mockErrToast).toHaveBeenCalledWith('Failed to refresh'); - }); - }); - - it('calls onDeposit callback when deposit button is clicked', async () => { - mockMatchesAccount.mockReturnValue(true); - const user = userEvent.setup(); - const mockOnDeposit = vi.fn(); - - render(OrderDetail, { - props: { - ...defaultProps, - onDeposit: mockOnDeposit - }, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - expect(screen.getByText('Order')).toBeInTheDocument(); - - expect(screen.getByText('Raindex')).toBeInTheDocument(); - - expect(screen.getByText('Owner')).toBeInTheDocument(); - - expect(screen.getByText('Created')).toBeInTheDocument(); - }); - - const depositButton = screen.getAllByTestId('deposit-button'); - await user.click(depositButton[0]); - - expect(mockOnDeposit).toHaveBeenCalledWith(mockRaindexClient, mockOrder.vaultsList.items[1]); - }); - - it('calls onWithdraw callback when withdraw button is clicked', async () => { - mockMatchesAccount.mockReturnValue(true); - const user = userEvent.setup(); - const mockOnWithdraw = vi.fn(); - - render(OrderDetail, { - props: { - ...defaultProps, - onWithdraw: mockOnWithdraw - }, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - expect(screen.getByText('Order')).toBeInTheDocument(); - expect(screen.getByText('Raindex')).toBeInTheDocument(); - expect(screen.getByText('Owner')).toBeInTheDocument(); - expect(screen.getByText('Created')).toBeInTheDocument(); - }); - - const withdrawButton = screen.getAllByTestId('withdraw-button'); - await user.click(withdrawButton[0]); - - expect(mockOnWithdraw).toHaveBeenCalledWith(mockRaindexClient, mockOrder.vaultsList.items[1]); - }); - - it('does not show Take Order button for inactive orders', async () => { - (mockRaindexClient.getOrderByHash as Mock).mockResolvedValue({ - value: { - ...mockOrder, - active: false - } - }); - - render(OrderDetail, { - props: { - ...defaultProps, - onTakeOrder: vi.fn() - }, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - expect(screen.getByText('Order')).toBeInTheDocument(); - }); - - expect(screen.queryByTestId('take-order-button')).not.toBeInTheDocument(); - }); - - it('shows Take Order button for active orders', async () => { - render(OrderDetail, { - props: { - ...defaultProps, - onTakeOrder: vi.fn() - }, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - expect(screen.getByText('Order')).toBeInTheDocument(); - }); - - expect(screen.getByTestId('take-order-button')).toBeInTheDocument(); - }); - - it('calls onTakeOrder callback when Take Order button clicked', async () => { - const user = userEvent.setup(); - const mockOnTakeOrder = vi.fn(); - - render(OrderDetail, { - props: { - ...defaultProps, - onTakeOrder: mockOnTakeOrder - }, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - expect(screen.getByText('Order')).toBeInTheDocument(); - }); - - const takeOrderButton = screen.getByTestId('take-order-button'); - expect(takeOrderButton).toBeInTheDocument(); - - await user.click(takeOrderButton); - - expect(mockOnTakeOrder).toHaveBeenCalledWith(mockRaindexClient, mockOrder); - }); - - it('renders the Dotrain tab and content when dotrain source exists', async () => { - const user = userEvent.setup(); - resolveOrder({ dotrainSource: 'dotrain:source' }); - - render(OrderDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - const dotrainTab = await screen.findByText('Dotrain'); - await user.click(dotrainTab); - - await waitFor(() => { - expect(screen.getByTestId('codemirror-rainlang')).toHaveTextContent('dotrain:source'); - }); - }); - - it('does not render the Dotrain tab when dotrain source is missing', async () => { - resolveOrder({ dotrainSource: undefined }); - - render(OrderDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - expect(screen.queryByText('Dotrain')).not.toBeInTheDocument(); - }); - }); - - it('renders the builder state tab with formatted JSON when present', async () => { - const user = userEvent.setup(); - const builderState = JSON.stringify({ foo: 'bar' }); - resolveOrder({ orderBuilderState: builderState }); - - render(OrderDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - const builderTab = await screen.findByText('Builder State'); - await user.click(builderTab); - - await waitFor(() => { - expect(screen.getByTestId('builder-state-json')).toHaveTextContent('"foo": "bar"'); - }); - }); - - it('handles invalid builder state JSON gracefully', async () => { - const user = userEvent.setup(); - resolveOrder({ orderBuilderState: '{invalid' }); - - render(OrderDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - const builderTab = await screen.findByText('Builder State'); - await user.click(builderTab); - - await waitFor(() => { - expect(screen.getByTestId('builder-state-json')).toHaveTextContent('Invalid builder state'); - }); - }); - - it('renders on-chain Rainlang even without a Dotrain source', async () => { - const user = userEvent.setup(); - const rainlangText = '/* rainlang source */'; - resolveOrder({ rainlang: rainlangText, dotrainSource: undefined }); - - render(OrderDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - const rainlangTab = await screen.findByText('On-chain Rainlang'); - await user.click(rainlangTab); - - await waitFor(() => { - expect(screen.getByTestId('codemirror-rainlang')).toHaveTextContent(rainlangText); - }); - }); - - it('renders owner address as explorer link when explorer is available', async () => { - const explorerUrl = 'https://etherscan.io/address/0x1234567890123456789012345678901234567890'; - (getExplorerLink as Mock).mockReturnValue(explorerUrl); - - render(OrderDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - const ownerLink = screen.getByRole('link', { - name: /0x1234567890123456789012345678901234567890/i - }); - expect(ownerLink).toBeInTheDocument(); - expect(ownerLink).toHaveAttribute('href', explorerUrl); - expect(ownerLink).toHaveAttribute('target', '_blank'); - expect(ownerLink).toHaveAttribute('rel', 'noopener noreferrer'); - }); - }); - - it('falls back to Hash component when no explorer link is available', async () => { - (getExplorerLink as Mock).mockReturnValue(''); - - render(OrderDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - expect(screen.getByText('0x1234567890123456789012345678901234567890')).toBeInTheDocument(); - expect( - screen.queryByRole('link', { name: /0x1234567890123456789012345678901234567890/i }) - ).not.toBeInTheDocument(); - }); - }); - - describe('Oracle URL functionality', () => { - it('renders Oracle section when oracleUrl is present', async () => { - const oracleUrl = 'https://oracle.example.com/api'; - resolveOrder({ oracleUrl }); - - render(OrderDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - expect(screen.getByText('Oracle')).toBeInTheDocument(); - }); - }); - - it('does not render Oracle section when oracleUrl is not present', async () => { - resolveOrder({ oracleUrl: undefined }); - - render(OrderDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - expect(screen.queryByText('Oracle')).not.toBeInTheDocument(); - }); - }); - - it('renders Oracle URL as clickable link when URL is https', async () => { - const oracleUrl = 'https://oracle.example.com/api'; - resolveOrder({ oracleUrl }); - - render(OrderDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - const oracleLink = screen.getByRole('link', { name: oracleUrl }); - expect(oracleLink).toBeInTheDocument(); - expect(oracleLink).toHaveAttribute('href', oracleUrl); - expect(oracleLink).toHaveAttribute('target', '_blank'); - expect(oracleLink).toHaveAttribute('rel', 'noopener noreferrer'); - expect(oracleLink).toHaveClass('text-blue-500', 'hover:underline'); - }); - }); - - it('renders Oracle URL as clickable link when URL is http', async () => { - const oracleUrl = 'http://localhost:8080/oracle'; - resolveOrder({ oracleUrl }); - - render(OrderDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - const oracleLink = screen.getByRole('link', { name: oracleUrl }); - expect(oracleLink).toBeInTheDocument(); - expect(oracleLink).toHaveAttribute('href', oracleUrl); - expect(oracleLink).toHaveAttribute('target', '_blank'); - expect(oracleLink).toHaveAttribute('rel', 'noopener noreferrer'); - }); - }); - - it('renders Oracle URL as plain text when URL does not start with http/https', async () => { - const oracleUrl = 'ftp://oracle.example.com/api'; - resolveOrder({ oracleUrl }); - - render(OrderDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - expect(screen.getByText(oracleUrl)).toBeInTheDocument(); - expect(screen.queryByRole('link', { name: oracleUrl })).not.toBeInTheDocument(); - }); - }); - - it('renders Oracle URL as plain text with gray styling for non-http URLs', async () => { - const oracleUrl = 'javascript:alert(1)'; - resolveOrder({ oracleUrl }); - - render(OrderDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - const textElement = screen.getByText(oracleUrl); - expect(textElement).toBeInTheDocument(); - expect(textElement.tagName).toBe('SPAN'); - expect(textElement).toHaveClass('text-gray-500'); - // Should not be a link itself (but other links may exist on page) - expect(screen.queryByRole('link', { name: oracleUrl })).not.toBeInTheDocument(); - }); - }); - - it('displays Oracle section with info icon when URL is present', async () => { - const oracleUrl = 'https://oracle.example.com/api'; - resolveOrder({ oracleUrl }); - - render(OrderDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - // Check that Oracle section is present - expect(screen.getByText('Oracle')).toBeInTheDocument(); - // Check that the Oracle URL is displayed - expect(screen.getByText(oracleUrl)).toBeInTheDocument(); - }); - }); - }); +describe("OrderDetail", () => { + let queryClient: QueryClient; + let mockRaindexClient: RaindexClient; + const resolveOrder = (override: Partial = {}) => + (mockRaindexClient.getOrderByHash as Mock).mockResolvedValue({ + value: { ...mockOrder, ...override }, + }); + + beforeEach(async () => { + vi.clearAllMocks(); + vi.resetAllMocks(); + queryClient = new QueryClient(); + + (useAccount as Mock).mockReturnValue({ + matchesAccount: mockMatchesAccount, + }); + + mockRaindexClient = { + getOrderByHash: vi.fn().mockResolvedValue({ + value: mockOrder, + }), + } as unknown as RaindexClient; + (useRaindexClient as Mock).mockReturnValue(mockRaindexClient); + + (useToasts as Mock).mockReturnValue({ + toasts: writable([]), + errToast: mockErrToast, + removeToast: vi.fn(), + }); + + (getExplorerLink as Mock).mockReturnValue( + "https://etherscan.io/address/0x1234567890123456789012345678901234567890", + ); + }); + + it("calls the order detail query with the correct order hash", async () => { + render(OrderDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + expect(mockRaindexClient.getOrderByHash).toHaveBeenCalledWith( + 1, + raindexAddress, + orderHash, + ); + }); + + it("shows the correct empty message when the query returns no data", async () => { + (mockRaindexClient.getOrderByHash as Mock).mockResolvedValue({ + value: null, + }); + + render(OrderDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + expect(screen.getByText("Order not found")).toBeInTheDocument(); + }); + }); + + it("shows the correct data when the query returns data", async () => { + render(OrderDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + expect(screen.getByText("Order")).toBeInTheDocument(); + expect(screen.getByText("Raindex")).toBeInTheDocument(); + expect(screen.getByText("Owner")).toBeInTheDocument(); + expect(screen.getByText("Created")).toBeInTheDocument(); + expect(screen.getByText(raindexAddress)).toBeInTheDocument(); + expect( + screen.getByText("0x1234567890123456789012345678901234567890"), + ).toBeInTheDocument(); + }); + }); + + it("shows remove button if owner wallet matches and order is active", async () => { + mockMatchesAccount.mockReturnValue(true); + render(OrderDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + const removeButton = screen.getByTestId("remove-button"); + expect(removeButton).toBeInTheDocument(); + expect(defaultProps.onRemove).not.toHaveBeenCalled(); + }); + + await userEvent.click(screen.getByTestId("remove-button")); + + await waitFor(() => { + expect(defaultProps.onRemove).toHaveBeenCalledWith( + mockRaindexClient, + mockOrder, + ); + }); + }); + + it("does not show remove button if account does not match owner", async () => { + mockMatchesAccount.mockReturnValue(false); + + render(OrderDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + expect(screen.queryByTestId("remove-button")).not.toBeInTheDocument(); + }); + }); + + it("does not show remove button if order is not active", async () => { + // Modify the mock to return an inactive order + (mockRaindexClient.getOrderByHash as Mock).mockResolvedValue({ + value: { + ...mockOrder, + active: false, + }, + }); + + render(OrderDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + expect(screen.queryByTestId("remove-button")).not.toBeInTheDocument(); + }); + }); + + it("refresh button triggers query invalidation when clicked", async () => { + render(OrderDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(async () => { + const refreshButton = screen.getByTestId("top-refresh"); + await userEvent.click(refreshButton); + + expect(invalidateTanstackQueries).toHaveBeenCalledWith(queryClient, [ + orderHash, + ]); + }); + }); + + it("failed query invalidation triggers a toast", async () => { + (invalidateTanstackQueries as Mock).mockRejectedValue( + new Error("Failed to refresh"), + ); + + render(OrderDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(async () => { + const refreshButton = screen.getByTestId("top-refresh"); + await userEvent.click(refreshButton); + }); + + await waitFor(() => { + expect(mockErrToast).toHaveBeenCalledWith("Failed to refresh"); + }); + }); + + it("calls onDeposit callback when deposit button is clicked", async () => { + mockMatchesAccount.mockReturnValue(true); + const user = userEvent.setup(); + const mockOnDeposit = vi.fn(); + + render(OrderDetail, { + props: { + ...defaultProps, + onDeposit: mockOnDeposit, + }, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + expect(screen.getByText("Order")).toBeInTheDocument(); + + expect(screen.getByText("Raindex")).toBeInTheDocument(); + + expect(screen.getByText("Owner")).toBeInTheDocument(); + + expect(screen.getByText("Created")).toBeInTheDocument(); + }); + + const depositButton = screen.getAllByTestId("deposit-button"); + await user.click(depositButton[0]); + + expect(mockOnDeposit).toHaveBeenCalledWith( + mockRaindexClient, + mockOrder.vaultsList.items[1], + ); + }); + + it("calls onWithdraw callback when withdraw button is clicked", async () => { + mockMatchesAccount.mockReturnValue(true); + const user = userEvent.setup(); + const mockOnWithdraw = vi.fn(); + + render(OrderDetail, { + props: { + ...defaultProps, + onWithdraw: mockOnWithdraw, + }, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + expect(screen.getByText("Order")).toBeInTheDocument(); + expect(screen.getByText("Raindex")).toBeInTheDocument(); + expect(screen.getByText("Owner")).toBeInTheDocument(); + expect(screen.getByText("Created")).toBeInTheDocument(); + }); + + const withdrawButton = screen.getAllByTestId("withdraw-button"); + await user.click(withdrawButton[0]); + + expect(mockOnWithdraw).toHaveBeenCalledWith( + mockRaindexClient, + mockOrder.vaultsList.items[1], + ); + }); + + it("does not show Take Order button for inactive orders", async () => { + (mockRaindexClient.getOrderByHash as Mock).mockResolvedValue({ + value: { + ...mockOrder, + active: false, + }, + }); + + render(OrderDetail, { + props: { + ...defaultProps, + onTakeOrder: vi.fn(), + }, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + expect(screen.getByText("Order")).toBeInTheDocument(); + }); + + expect(screen.queryByTestId("take-order-button")).not.toBeInTheDocument(); + }); + + it("shows Take Order button for active orders", async () => { + render(OrderDetail, { + props: { + ...defaultProps, + onTakeOrder: vi.fn(), + }, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + expect(screen.getByText("Order")).toBeInTheDocument(); + }); + + expect(screen.getByTestId("take-order-button")).toBeInTheDocument(); + }); + + it("calls onTakeOrder callback when Take Order button clicked", async () => { + const user = userEvent.setup(); + const mockOnTakeOrder = vi.fn(); + + render(OrderDetail, { + props: { + ...defaultProps, + onTakeOrder: mockOnTakeOrder, + }, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + expect(screen.getByText("Order")).toBeInTheDocument(); + }); + + const takeOrderButton = screen.getByTestId("take-order-button"); + expect(takeOrderButton).toBeInTheDocument(); + + await user.click(takeOrderButton); + + expect(mockOnTakeOrder).toHaveBeenCalledWith(mockRaindexClient, mockOrder); + }); + + it("renders the Dotrain tab and content when dotrain source exists", async () => { + const user = userEvent.setup(); + resolveOrder({ dotrainSource: "dotrain:source" }); + + render(OrderDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + const dotrainTab = await screen.findByText("Dotrain"); + await user.click(dotrainTab); + + await waitFor(() => { + expect(screen.getByTestId("codemirror-rainlang")).toHaveTextContent( + "dotrain:source", + ); + }); + }); + + it("does not render the Dotrain tab when dotrain source is missing", async () => { + resolveOrder({ dotrainSource: undefined }); + + render(OrderDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + expect(screen.queryByText("Dotrain")).not.toBeInTheDocument(); + }); + }); + + it("renders the builder state tab with formatted JSON when present", async () => { + const user = userEvent.setup(); + const builderState = JSON.stringify({ foo: "bar" }); + resolveOrder({ orderBuilderState: builderState }); + + render(OrderDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + const builderTab = await screen.findByText("Builder State"); + await user.click(builderTab); + + await waitFor(() => { + expect(screen.getByTestId("builder-state-json")).toHaveTextContent( + '"foo": "bar"', + ); + }); + }); + + it("handles invalid builder state JSON gracefully", async () => { + const user = userEvent.setup(); + resolveOrder({ orderBuilderState: "{invalid" }); + + render(OrderDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + const builderTab = await screen.findByText("Builder State"); + await user.click(builderTab); + + await waitFor(() => { + expect(screen.getByTestId("builder-state-json")).toHaveTextContent( + "Invalid builder state", + ); + }); + }); + + it("renders on-chain Rainlang even without a Dotrain source", async () => { + const user = userEvent.setup(); + const rainlangText = "/* rainlang source */"; + resolveOrder({ rainlang: rainlangText, dotrainSource: undefined }); + + render(OrderDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + const rainlangTab = await screen.findByText("On-chain Rainlang"); + await user.click(rainlangTab); + + await waitFor(() => { + expect(screen.getByTestId("codemirror-rainlang")).toHaveTextContent( + rainlangText, + ); + }); + }); + + it("renders owner address as explorer link when explorer is available", async () => { + const explorerUrl = + "https://etherscan.io/address/0x1234567890123456789012345678901234567890"; + (getExplorerLink as Mock).mockReturnValue(explorerUrl); + + render(OrderDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + const ownerLink = screen.getByRole("link", { + name: /0x1234567890123456789012345678901234567890/i, + }); + expect(ownerLink).toBeInTheDocument(); + expect(ownerLink).toHaveAttribute("href", explorerUrl); + expect(ownerLink).toHaveAttribute("target", "_blank"); + expect(ownerLink).toHaveAttribute("rel", "noopener noreferrer"); + }); + }); + + it("falls back to Hash component when no explorer link is available", async () => { + (getExplorerLink as Mock).mockReturnValue(""); + + render(OrderDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + expect( + screen.getByText("0x1234567890123456789012345678901234567890"), + ).toBeInTheDocument(); + expect( + screen.queryByRole("link", { + name: /0x1234567890123456789012345678901234567890/i, + }), + ).not.toBeInTheDocument(); + }); + }); + + describe("Oracle URL functionality", () => { + it("renders Oracle section when oracleUrl is present", async () => { + const oracleUrl = "https://oracle.example.com/api"; + resolveOrder({ oracleUrl }); + + render(OrderDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + expect(screen.getByText("Oracle")).toBeInTheDocument(); + }); + }); + + it("does not render Oracle section when oracleUrl is not present", async () => { + resolveOrder({ oracleUrl: undefined }); + + render(OrderDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + expect(screen.queryByText("Oracle")).not.toBeInTheDocument(); + }); + }); + + it("renders Oracle URL as clickable link when URL is https", async () => { + const oracleUrl = "https://oracle.example.com/api"; + resolveOrder({ oracleUrl }); + + render(OrderDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + const oracleLink = screen.getByRole("link", { name: oracleUrl }); + expect(oracleLink).toBeInTheDocument(); + expect(oracleLink).toHaveAttribute("href", oracleUrl); + expect(oracleLink).toHaveAttribute("target", "_blank"); + expect(oracleLink).toHaveAttribute("rel", "noopener noreferrer"); + expect(oracleLink).toHaveClass("text-blue-500", "hover:underline"); + }); + }); + + it("renders Oracle URL as clickable link when URL is http", async () => { + const oracleUrl = "http://localhost:8080/oracle"; + resolveOrder({ oracleUrl }); + + render(OrderDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + const oracleLink = screen.getByRole("link", { name: oracleUrl }); + expect(oracleLink).toBeInTheDocument(); + expect(oracleLink).toHaveAttribute("href", oracleUrl); + expect(oracleLink).toHaveAttribute("target", "_blank"); + expect(oracleLink).toHaveAttribute("rel", "noopener noreferrer"); + }); + }); + + it("renders Oracle URL as plain text when URL does not start with http/https", async () => { + const oracleUrl = "ftp://oracle.example.com/api"; + resolveOrder({ oracleUrl }); + + render(OrderDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + expect(screen.getByText(oracleUrl)).toBeInTheDocument(); + expect( + screen.queryByRole("link", { name: oracleUrl }), + ).not.toBeInTheDocument(); + }); + }); + + it("renders Oracle URL as plain text with gray styling for non-http URLs", async () => { + const oracleUrl = "javascript:alert(1)"; + resolveOrder({ oracleUrl }); + + render(OrderDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + const textElement = screen.getByText(oracleUrl); + expect(textElement).toBeInTheDocument(); + expect(textElement.tagName).toBe("SPAN"); + expect(textElement).toHaveClass("text-gray-500"); + // Should not be a link itself (but other links may exist on page) + expect( + screen.queryByRole("link", { name: oracleUrl }), + ).not.toBeInTheDocument(); + }); + }); + + it("displays Oracle section with info icon when URL is present", async () => { + const oracleUrl = "https://oracle.example.com/api"; + resolveOrder({ oracleUrl }); + + render(OrderDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + // Check that Oracle section is present + expect(screen.getByText("Oracle")).toBeInTheDocument(); + // Check that the Oracle URL is displayed + expect(screen.getByText(oracleUrl)).toBeInTheDocument(); + }); + }); + }); }); diff --git a/packages/ui-components/src/__tests__/OrderOrVaultHash.test.ts b/packages/ui-components/src/__tests__/OrderOrVaultHash.test.ts index 94dddbefc7..5fd15924f6 100644 --- a/packages/ui-components/src/__tests__/OrderOrVaultHash.test.ts +++ b/packages/ui-components/src/__tests__/OrderOrVaultHash.test.ts @@ -1,113 +1,113 @@ -import { render } from '@testing-library/svelte'; -import { describe, it, expect, vi } from 'vitest'; -import OrderOrVaultHash from '../lib/components/OrderOrVaultHash.svelte'; -import type { RaindexOrder, RaindexVault } from '@rainlanguage/raindex'; +import { render } from "@testing-library/svelte"; +import { describe, it, expect, vi } from "vitest"; +import OrderOrVaultHash from "../lib/components/OrderOrVaultHash.svelte"; +import type { RaindexOrder, RaindexVault } from "@rainlanguage/raindex"; -vi.mock('$app/navigation', () => ({ - goto: vi.fn() +vi.mock("$app/navigation", () => ({ + goto: vi.fn(), })); -describe('OrderOrVaultHash', () => { - const mockOrder = { - id: '123', - orderHash: '0x123abc', - active: true - } as unknown as RaindexOrder; - - const mockInactiveOrder = { - ...mockOrder, - active: false - } as unknown as RaindexOrder; - - const mockVault = { - id: '0xvault456' - } as unknown as RaindexVault; - - describe('Order rendering', () => { - it('renders with active order', () => { - const { getByTestId } = render(OrderOrVaultHash, { - props: { - type: 'orders', - orderOrVault: mockOrder, - chainId: 1, - raindexAddress: '0x234567' - } - }); - - const button = getByTestId('vault-order-input'); - const anchor = getByTestId('order-or-vault-hash'); - - expect(button).toBeTruthy(); - expect(button.classList.toString()).toContain('text-white bg-green'); - expect(button.getAttribute('data-id')).toBe('0x123abc'); - - expect(anchor).toBeTruthy(); - expect(anchor.getAttribute('href')).toBe('/orders/1-0x234567-0x123abc'); - - expect(button.textContent).toBeDefined(); - }); - - it('renders with inactive order', () => { - const { getByTestId } = render(OrderOrVaultHash, { - props: { - type: 'orders', - orderOrVault: mockInactiveOrder, - chainId: 1, - raindexAddress: '0x234567' - } - }); - - const button = getByTestId('vault-order-input'); - expect(button.classList.toString()).toContain('text-white bg-yellow'); - }); - }); - - describe('Vault rendering', () => { - it('renders vault correctly', () => { - const { getByTestId } = render(OrderOrVaultHash, { - props: { - type: 'vaults', - orderOrVault: mockVault, - chainId: 1, - raindexAddress: '0x234567' - } - }); - - const button = getByTestId('vault-order-input'); - const anchor = getByTestId('order-or-vault-hash'); - - expect(button).toBeTruthy(); - expect(button.getAttribute('data-id')).toBe('0xvault456'); - - expect(anchor).toBeTruthy(); - expect(anchor.getAttribute('href')).toBe('/vaults/1-0x234567-0xvault456'); - }); - - it('renders active order with appropriate styling', () => { - const { getByTestId } = render(OrderOrVaultHash, { - props: { - type: 'orders', - orderOrVault: mockOrder as unknown as RaindexOrder, - chainId: 1, - raindexAddress: '0x234567' - } - }); - - const button = getByTestId('vault-order-input'); - expect(button.classList.toString()).toContain('text-white bg-green'); - }); - it('renders inactive order with appropriate styling', () => { - const { getByTestId } = render(OrderOrVaultHash, { - props: { - type: 'orders', - orderOrVault: mockInactiveOrder as unknown as RaindexOrder, - chainId: 1, - raindexAddress: '0x234567' - } - }); - - const button = getByTestId('vault-order-input'); - expect(button.classList.toString()).toContain('bg-yellow-400'); - }); - }); +describe("OrderOrVaultHash", () => { + const mockOrder = { + id: "123", + orderHash: "0x123abc", + active: true, + } as unknown as RaindexOrder; + + const mockInactiveOrder = { + ...mockOrder, + active: false, + } as unknown as RaindexOrder; + + const mockVault = { + id: "0xvault456", + } as unknown as RaindexVault; + + describe("Order rendering", () => { + it("renders with active order", () => { + const { getByTestId } = render(OrderOrVaultHash, { + props: { + type: "orders", + orderOrVault: mockOrder, + chainId: 1, + raindexAddress: "0x234567", + }, + }); + + const button = getByTestId("vault-order-input"); + const anchor = getByTestId("order-or-vault-hash"); + + expect(button).toBeTruthy(); + expect(button.classList.toString()).toContain("text-white bg-green"); + expect(button.getAttribute("data-id")).toBe("0x123abc"); + + expect(anchor).toBeTruthy(); + expect(anchor.getAttribute("href")).toBe("/orders/1-0x234567-0x123abc"); + + expect(button.textContent).toBeDefined(); + }); + + it("renders with inactive order", () => { + const { getByTestId } = render(OrderOrVaultHash, { + props: { + type: "orders", + orderOrVault: mockInactiveOrder, + chainId: 1, + raindexAddress: "0x234567", + }, + }); + + const button = getByTestId("vault-order-input"); + expect(button.classList.toString()).toContain("text-white bg-yellow"); + }); + }); + + describe("Vault rendering", () => { + it("renders vault correctly", () => { + const { getByTestId } = render(OrderOrVaultHash, { + props: { + type: "vaults", + orderOrVault: mockVault, + chainId: 1, + raindexAddress: "0x234567", + }, + }); + + const button = getByTestId("vault-order-input"); + const anchor = getByTestId("order-or-vault-hash"); + + expect(button).toBeTruthy(); + expect(button.getAttribute("data-id")).toBe("0xvault456"); + + expect(anchor).toBeTruthy(); + expect(anchor.getAttribute("href")).toBe("/vaults/1-0x234567-0xvault456"); + }); + + it("renders active order with appropriate styling", () => { + const { getByTestId } = render(OrderOrVaultHash, { + props: { + type: "orders", + orderOrVault: mockOrder as unknown as RaindexOrder, + chainId: 1, + raindexAddress: "0x234567", + }, + }); + + const button = getByTestId("vault-order-input"); + expect(button.classList.toString()).toContain("text-white bg-green"); + }); + it("renders inactive order with appropriate styling", () => { + const { getByTestId } = render(OrderOrVaultHash, { + props: { + type: "orders", + orderOrVault: mockInactiveOrder as unknown as RaindexOrder, + chainId: 1, + raindexAddress: "0x234567", + }, + }); + + const button = getByTestId("vault-order-input"); + expect(button.classList.toString()).toContain("bg-yellow-400"); + }); + }); }); diff --git a/packages/ui-components/src/__tests__/OrderPage.test.ts b/packages/ui-components/src/__tests__/OrderPage.test.ts index c20a79a5d7..af95c83d61 100644 --- a/packages/ui-components/src/__tests__/OrderPage.test.ts +++ b/packages/ui-components/src/__tests__/OrderPage.test.ts @@ -1,117 +1,123 @@ -import { render, screen, waitFor } from '@testing-library/svelte'; -import OrderPage from '../lib/components/deployment/OrderPage.svelte'; -import type { NameAndDescriptionCfg } from '@rainlanguage/raindex'; -import { vi, describe, it, expect, beforeEach } from 'vitest'; +import { render, screen, waitFor } from "@testing-library/svelte"; +import OrderPage from "../lib/components/deployment/OrderPage.svelte"; +import type { NameAndDescriptionCfg } from "@rainlanguage/raindex"; +import { vi, describe, it, expect, beforeEach } from "vitest"; // Mock fetch const mockFetch = vi.fn(); -vi.stubGlobal('fetch', mockFetch); +vi.stubGlobal("fetch", mockFetch); -vi.mock('../lib/components/deployment/DeploymentsSection.svelte', async () => { - const MockDeploymentsSection = (await import('../lib/__mocks__/MockComponent.svelte')).default; - return { default: MockDeploymentsSection }; +vi.mock("../lib/components/deployment/DeploymentsSection.svelte", async () => { + const MockDeploymentsSection = ( + await import("../lib/__mocks__/MockComponent.svelte") + ).default; + return { default: MockDeploymentsSection }; }); -describe('OrderPage', () => { - beforeEach(() => { - mockFetch.mockReset(); - }); - - it('renders order details when provided directly', async () => { - render(OrderPage, { - props: { - orderName: 'TestOrder', - orderDetail: { - name: 'Test Order', - description: 'Test Description', - short_description: 'Test Short Description' - } - } - }); - - await waitFor(() => { - expect(screen.getByText('Test Order')).toBeInTheDocument(); - expect(screen.getByText('Test Description')).toBeInTheDocument(); - }); - }); - - it('renders markdown when description is a markdown url', async () => { - mockFetch.mockResolvedValueOnce({ - ok: true, - text: () => Promise.resolve('mock markdown content') - }); - - render(OrderPage, { - props: { - orderName: 'TestOrder', - orderDetail: { - name: 'Test Order', - description: 'https://example.com/description.md', - short_description: 'Test Short Description' - } - } - }); - - await waitFor(() => { - expect(screen.getByText('Test Order')).toBeInTheDocument(); - expect(screen.getByTestId('markdown-content')).toBeInTheDocument(); - expect(mockFetch).toHaveBeenCalledWith('https://example.com/description.md'); - }); - }); - - it('handles markdown fetch failure', async () => { - mockFetch.mockRejectedValueOnce(new Error('Failed to fetch')); - - render(OrderPage, { - props: { - orderName: 'TestOrder', - orderDetail: { - name: 'Test Order', - description: 'https://example.com/description.md', - short_description: 'Test Short Description' - } - } - }); - - await waitFor(() => { - expect(screen.getByText('Failed to fetch markdown')).toBeInTheDocument(); - }); - }); - - it('falls back to plain text when markdown fetch is not ok', async () => { - mockFetch.mockResolvedValueOnce({ - ok: false, - statusText: 'Not Found' - }); - - render(OrderPage, { - props: { - orderName: 'TestOrder', - orderDetail: { - name: 'Test Order', - description: 'https://example.com/description.md', - short_description: 'Test Short Description' - } - } - }); - - await waitFor(() => { - expect(screen.getByText('Test Order')).toBeInTheDocument(); - expect(screen.getByTestId('plain-description')).toHaveTextContent( - 'https://example.com/description.md' - ); - }); - }); - - it('shows fallback when order detail is missing', () => { - render(OrderPage, { - // Casting to satisfy the required prop in tests - props: { - orderName: 'TestOrder', - orderDetail: undefined as unknown as NameAndDescriptionCfg - } - }); - - expect(screen.getByText('Failed to load order details.')).toBeInTheDocument(); - }); +describe("OrderPage", () => { + beforeEach(() => { + mockFetch.mockReset(); + }); + + it("renders order details when provided directly", async () => { + render(OrderPage, { + props: { + orderName: "TestOrder", + orderDetail: { + name: "Test Order", + description: "Test Description", + short_description: "Test Short Description", + }, + }, + }); + + await waitFor(() => { + expect(screen.getByText("Test Order")).toBeInTheDocument(); + expect(screen.getByText("Test Description")).toBeInTheDocument(); + }); + }); + + it("renders markdown when description is a markdown url", async () => { + mockFetch.mockResolvedValueOnce({ + ok: true, + text: () => Promise.resolve("mock markdown content"), + }); + + render(OrderPage, { + props: { + orderName: "TestOrder", + orderDetail: { + name: "Test Order", + description: "https://example.com/description.md", + short_description: "Test Short Description", + }, + }, + }); + + await waitFor(() => { + expect(screen.getByText("Test Order")).toBeInTheDocument(); + expect(screen.getByTestId("markdown-content")).toBeInTheDocument(); + expect(mockFetch).toHaveBeenCalledWith( + "https://example.com/description.md", + ); + }); + }); + + it("handles markdown fetch failure", async () => { + mockFetch.mockRejectedValueOnce(new Error("Failed to fetch")); + + render(OrderPage, { + props: { + orderName: "TestOrder", + orderDetail: { + name: "Test Order", + description: "https://example.com/description.md", + short_description: "Test Short Description", + }, + }, + }); + + await waitFor(() => { + expect(screen.getByText("Failed to fetch markdown")).toBeInTheDocument(); + }); + }); + + it("falls back to plain text when markdown fetch is not ok", async () => { + mockFetch.mockResolvedValueOnce({ + ok: false, + statusText: "Not Found", + }); + + render(OrderPage, { + props: { + orderName: "TestOrder", + orderDetail: { + name: "Test Order", + description: "https://example.com/description.md", + short_description: "Test Short Description", + }, + }, + }); + + await waitFor(() => { + expect(screen.getByText("Test Order")).toBeInTheDocument(); + expect(screen.getByTestId("plain-description")).toHaveTextContent( + "https://example.com/description.md", + ); + }); + }); + + it("shows fallback when order detail is missing", () => { + render(OrderPage, { + // Casting to satisfy the required prop in tests + props: { + orderName: "TestOrder", + orderDetail: undefined as unknown as NameAndDescriptionCfg, + }, + }); + + expect( + screen.getByText("Failed to load order details."), + ).toBeInTheDocument(); + }); }); diff --git a/packages/ui-components/src/__tests__/OrderVaultsVolTable.test.ts b/packages/ui-components/src/__tests__/OrderVaultsVolTable.test.ts index def3963f69..0f81cbb6bc 100644 --- a/packages/ui-components/src/__tests__/OrderVaultsVolTable.test.ts +++ b/packages/ui-components/src/__tests__/OrderVaultsVolTable.test.ts @@ -1,81 +1,81 @@ -import { render, screen, waitFor } from '@testing-library/svelte'; -import { test, vi } from 'vitest'; -import { expect } from '$lib/test/matchers'; -import type { RaindexOrder, RaindexVaultVolume } from '@rainlanguage/raindex'; -import OrderVaultsVolTable from '../lib/components/tables/OrderVaultsVolTable.svelte'; -import { QueryClient } from '@tanstack/svelte-query'; +import { render, screen, waitFor } from "@testing-library/svelte"; +import { test, vi } from "vitest"; +import { expect } from "$lib/test/matchers"; +import type { RaindexOrder, RaindexVaultVolume } from "@rainlanguage/raindex"; +import OrderVaultsVolTable from "../lib/components/tables/OrderVaultsVolTable.svelte"; +import { QueryClient } from "@tanstack/svelte-query"; const mockVaultsVol = [ - { - id: BigInt('1'), - token: { - id: 'output_token', - address: '0xoutput_token', - name: 'output_token', - symbol: 'output_token', - decimals: BigInt('0') - }, - details: { - formattedTotalIn: '1', - formattedTotalOut: '2', - formattedTotalVol: '3', - formattedNetVol: '-1' - } - }, - { - id: BigInt('2'), - token: { - id: 'output_token', - address: '0xoutput_token', - name: 'output_token', - symbol: 'output_token', - decimals: BigInt('0') - }, - details: { - formattedTotalIn: '2', - formattedTotalOut: '5', - formattedTotalVol: '7', - formattedNetVol: '-3' - } - } + { + id: BigInt("1"), + token: { + id: "output_token", + address: "0xoutput_token", + name: "output_token", + symbol: "output_token", + decimals: BigInt("0"), + }, + details: { + formattedTotalIn: "1", + formattedTotalOut: "2", + formattedTotalVol: "3", + formattedNetVol: "-1", + }, + }, + { + id: BigInt("2"), + token: { + id: "output_token", + address: "0xoutput_token", + name: "output_token", + symbol: "output_token", + decimals: BigInt("0"), + }, + details: { + formattedTotalIn: "2", + formattedTotalOut: "5", + formattedTotalVol: "7", + formattedNetVol: "-3", + }, + }, ] as unknown as RaindexVaultVolume[]; -test('renders table with correct data', async () => { - const queryClient = new QueryClient(); - const mockOrder: RaindexOrder = { - id: '1', - getVaultsVolume: vi.fn().mockResolvedValue({ value: mockVaultsVol }) - } as unknown as RaindexOrder; - render(OrderVaultsVolTable, { - context: new Map([['$$_queryClient', queryClient]]), - props: { order: mockOrder } - }); - await waitFor(async () => { - const rows = screen.getAllByTestId('total-in'); - for (let i = 0; i < mockVaultsVol.length; i++) { - const display = mockVaultsVol[i].details.formattedTotalIn; - expect(rows[i]).toHaveTextContent(display); - } - }); - await waitFor(async () => { - const rows = screen.getAllByTestId('total-out'); - for (let i = 0; i < mockVaultsVol.length; i++) { - const display = mockVaultsVol[i].details.formattedTotalOut; - expect(rows[i]).toHaveTextContent(display); - } - }); - await waitFor(async () => { - const rows = screen.getAllByTestId('net-vol'); - for (let i = 0; i < mockVaultsVol.length; i++) { - const display = mockVaultsVol[i].details.formattedNetVol; - expect(rows[i]).toHaveTextContent(display); - } - }); - await waitFor(async () => { - const rows = screen.getAllByTestId('total-vol'); - for (let i = 0; i < mockVaultsVol.length; i++) { - const display = mockVaultsVol[i].details.formattedTotalVol; - expect(rows[i]).toHaveTextContent(display); - } - }); +test("renders table with correct data", async () => { + const queryClient = new QueryClient(); + const mockOrder: RaindexOrder = { + id: "1", + getVaultsVolume: vi.fn().mockResolvedValue({ value: mockVaultsVol }), + } as unknown as RaindexOrder; + render(OrderVaultsVolTable, { + context: new Map([["$$_queryClient", queryClient]]), + props: { order: mockOrder }, + }); + await waitFor(async () => { + const rows = screen.getAllByTestId("total-in"); + for (let i = 0; i < mockVaultsVol.length; i++) { + const display = mockVaultsVol[i].details.formattedTotalIn; + expect(rows[i]).toHaveTextContent(display); + } + }); + await waitFor(async () => { + const rows = screen.getAllByTestId("total-out"); + for (let i = 0; i < mockVaultsVol.length; i++) { + const display = mockVaultsVol[i].details.formattedTotalOut; + expect(rows[i]).toHaveTextContent(display); + } + }); + await waitFor(async () => { + const rows = screen.getAllByTestId("net-vol"); + for (let i = 0; i < mockVaultsVol.length; i++) { + const display = mockVaultsVol[i].details.formattedNetVol; + expect(rows[i]).toHaveTextContent(display); + } + }); + await waitFor(async () => { + const rows = screen.getAllByTestId("total-vol"); + for (let i = 0; i < mockVaultsVol.length; i++) { + const display = mockVaultsVol[i].details.formattedTotalVol; + expect(rows[i]).toHaveTextContent(display); + } + }); }); diff --git a/packages/ui-components/src/__tests__/OrdersListTable.test.ts b/packages/ui-components/src/__tests__/OrdersListTable.test.ts index 4c1df2023f..b901ece24f 100644 --- a/packages/ui-components/src/__tests__/OrdersListTable.test.ts +++ b/packages/ui-components/src/__tests__/OrdersListTable.test.ts @@ -1,642 +1,660 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { render, screen, waitFor } from '@testing-library/svelte'; -import { describe, it, expect, vi, type Mock } from 'vitest'; -import userEvent from '@testing-library/user-event'; -import OrdersListTable from '../lib/components/tables/OrdersListTable.svelte'; -import { RaindexOrder } from '@rainlanguage/raindex'; -import type { ComponentProps } from 'svelte'; -import { readable } from 'svelte/store'; -import { useAccount } from '$lib/providers/wallet/useAccount'; - -vi.mock('../lib/components/ListViewRaindexFilters.svelte', async () => { - const MockComponent = (await import('../lib/__mocks__/MockComponent.svelte')).default; - return { - default: MockComponent - }; +import { render, screen, waitFor } from "@testing-library/svelte"; +import { describe, it, expect, vi, type Mock } from "vitest"; +import userEvent from "@testing-library/user-event"; +import OrdersListTable from "../lib/components/tables/OrdersListTable.svelte"; +import { RaindexOrder } from "@rainlanguage/raindex"; +import type { ComponentProps } from "svelte"; +import { readable } from "svelte/store"; +import { useAccount } from "$lib/providers/wallet/useAccount"; + +vi.mock("../lib/components/ListViewRaindexFilters.svelte", async () => { + const MockComponent = (await import("../lib/__mocks__/MockComponent.svelte")) + .default; + return { + default: MockComponent, + }; }); -vi.mock('$lib/providers/wallet/useAccount', () => ({ - useAccount: vi.fn() +vi.mock("$lib/providers/wallet/useAccount", () => ({ + useAccount: vi.fn(), })); -vi.mock('$lib/hooks/useRaindexClient', () => ({ - useRaindexClient: vi.fn() +vi.mock("$lib/hooks/useRaindexClient", () => ({ + useRaindexClient: vi.fn(), })); -import { useRaindexClient } from '$lib/hooks/useRaindexClient'; +import { useRaindexClient } from "$lib/hooks/useRaindexClient"; -const mockAccountStore = readable('0xabcdef1234567890abcdef1234567890abcdef12'); +const mockAccountStore = readable("0xabcdef1234567890abcdef1234567890abcdef12"); const mockMatchesAccount = vi.fn(); const mockVaultsList = () => ({ - items: [], - getWithdrawableVaults: () => ({ value: [], error: null }) + items: [], + getWithdrawableVaults: () => ({ value: [], error: null }), }); const mockOrder = { - chainId: 1, - id: '0x1234567890abcdef1234567890abcdef12345678', - orderBytes: '', - orderHash: '0x4444444444444444444444444444444444444444', - owner: '0xabcdef1234567890abcdef1234567890abcdef12', - inputs: [ - { - token: { - symbol: 'ETH' - }, - formattedBalance: '1.5' - } - ], - outputs: [ - { - token: { - symbol: 'DAI' - }, - formattedBalance: '2500.0' - } - ], - vaults: [], - inputsList: { - ...mockVaultsList(), - items: [ - { - token: { - symbol: 'ETH' - }, - formattedBalance: '1.5' - } - ] - }, - outputsList: { - ...mockVaultsList(), - items: [ - { - token: { - symbol: 'DAI' - }, - formattedBalance: '2500.0' - } - ] - }, - inputsOutputsList: mockVaultsList(), - vaultsList: mockVaultsList(), - raindex: '0x2222222222222222222222222222222222222222', - active: true, - timestampAdded: BigInt(1678901234), - meta: '', - rainlang: '', - tradesCount: 2 + chainId: 1, + id: "0x1234567890abcdef1234567890abcdef12345678", + orderBytes: "", + orderHash: "0x4444444444444444444444444444444444444444", + owner: "0xabcdef1234567890abcdef1234567890abcdef12", + inputs: [ + { + token: { + symbol: "ETH", + }, + formattedBalance: "1.5", + }, + ], + outputs: [ + { + token: { + symbol: "DAI", + }, + formattedBalance: "2500.0", + }, + ], + vaults: [], + inputsList: { + ...mockVaultsList(), + items: [ + { + token: { + symbol: "ETH", + }, + formattedBalance: "1.5", + }, + ], + }, + outputsList: { + ...mockVaultsList(), + items: [ + { + token: { + symbol: "DAI", + }, + formattedBalance: "2500.0", + }, + ], + }, + inputsOutputsList: mockVaultsList(), + vaultsList: mockVaultsList(), + raindex: "0x2222222222222222222222222222222222222222", + active: true, + timestampAdded: BigInt(1678901234), + meta: "", + rainlang: "", + tradesCount: 2, } as unknown as RaindexOrder; -vi.mock('@tanstack/svelte-query'); +vi.mock("@tanstack/svelte-query"); // Hoisted mock stores const { - mockHideZeroBalanceVaultsStore, - mockHideInactiveOrdersVaultsStore, - mockOrderHashStore, - mockShowInactiveOrdersStore, - mockSelectedChainIdsStore, - mockActiveTokensStore, - mockActiveRaindexAddressesStore, - mockOwnerFilterStore -} = await vi.hoisted(() => import('../lib/__mocks__/stores')); + mockHideZeroBalanceVaultsStore, + mockHideInactiveOrdersVaultsStore, + mockOrderHashStore, + mockShowInactiveOrdersStore, + mockSelectedChainIdsStore, + mockActiveTokensStore, + mockActiveRaindexAddressesStore, + mockOwnerFilterStore, +} = await vi.hoisted(() => import("../lib/__mocks__/stores")); type OrdersListTableProps = ComponentProps; const defaultProps: OrdersListTableProps = { - showInactiveOrders: mockShowInactiveOrdersStore, - orderHash: mockOrderHashStore, - hideZeroBalanceVaults: mockHideZeroBalanceVaultsStore, - hideInactiveOrdersVaults: mockHideInactiveOrdersVaultsStore, - selectedChainIds: mockSelectedChainIdsStore, - activeTokens: mockActiveTokensStore, - activeRaindexAddresses: mockActiveRaindexAddressesStore, - ownerFilter: mockOwnerFilterStore + showInactiveOrders: mockShowInactiveOrdersStore, + orderHash: mockOrderHashStore, + hideZeroBalanceVaults: mockHideZeroBalanceVaultsStore, + hideInactiveOrdersVaults: mockHideInactiveOrdersVaultsStore, + selectedChainIds: mockSelectedChainIdsStore, + activeTokens: mockActiveTokensStore, + activeRaindexAddresses: mockActiveRaindexAddressesStore, + ownerFilter: mockOwnerFilterStore, } as unknown as OrdersListTableProps; const mockGetOrders = vi.fn(); const mockGetTokens = vi.fn(); const mockGetAllRaindexes = vi.fn(); -describe('OrdersListTable', () => { - beforeEach(() => { - vi.clearAllMocks(); - (useAccount as Mock).mockReturnValue({ - account: mockAccountStore, - matchesAccount: mockMatchesAccount - }); - (useRaindexClient as Mock).mockReturnValue({ - getOrders: mockGetOrders, - getTokens: mockGetTokens, - getAllRaindexes: mockGetAllRaindexes.mockReturnValue({ - value: new Map([ - [ - 'raindex1', - { - key: 'raindex1', - address: '0x1111111111111111111111111111111111111111', - network: { chainId: 1 } - } - ] - ]), - error: undefined - }) - }); - mockGetOrders.mockResolvedValue({ value: { orders: [], totalCount: 0 }, error: undefined }); - mockGetTokens.mockResolvedValue({ value: [], error: undefined }); - }); - - it('displays order information correctly', async () => { - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [{ orders: [mockOrder], totalCount: 1 }] }, - status: 'success', - isFetching: false, - isFetched: true - }); - return { unsubscribe: () => {} }; - } - })) as Mock; - render(OrdersListTable, defaultProps as OrdersListTableProps); - - const orderInfoCell = screen.getByTestId('orderListRowOrderInfo'); - expect(orderInfoCell).toHaveTextContent('Ethereum'); - expect(orderInfoCell).toHaveTextContent('Active'); - expect(orderInfoCell).toHaveTextContent('Added:'); - - const addressesCell = screen.getByTestId('orderListRowAddresses'); - expect(addressesCell).toBeInTheDocument(); - expect(addressesCell).toHaveTextContent('Order:'); - expect(addressesCell).toHaveTextContent('Owner:'); - expect(addressesCell).toHaveTextContent('Raindex:'); - - // Check that vault cards are rendered with correct content - const vaultCards = screen.getAllByTestId('vault-card'); - expect(vaultCards).toHaveLength(2); // One input, one output - expect(screen.getByText('ETH')).toBeInTheDocument(); - expect(screen.getByText('1.5')).toBeInTheDocument(); - expect(screen.getByText('DAI')).toBeInTheDocument(); - expect(screen.getByText('2500.0')).toBeInTheDocument(); - - expect(screen.getByTestId('orderListRowTrades')).toHaveTextContent('2'); - }); - - it('displays token information in compact layout', async () => { - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [{ orders: [mockOrder], totalCount: 1 }] }, - status: 'success', - isFetching: false, - isFetched: true - }); - return { unsubscribe: () => {} }; - } - })) as Mock; - render(OrdersListTable, defaultProps as OrdersListTableProps); - - // Verify token symbols and balances are displayed in vault cards - expect(screen.getByText('ETH')).toBeInTheDocument(); - expect(screen.getByText('1.5')).toBeInTheDocument(); - expect(screen.getByText('DAI')).toBeInTheDocument(); - expect(screen.getByText('2500.0')).toBeInTheDocument(); - - // Verify "Strategy Balance:" label is not present (since we're using vault cards now) - expect(screen.queryByText('Strategy Balance:')).not.toBeInTheDocument(); - }); - - it('displays multiple tokens correctly in grid layout with shared IO', async () => { - const orderWithMultipleTokens = { - ...mockOrder, - inputs: [ - { - token: { symbol: 'ETH' }, - formattedBalance: '1.5' - }, - { - token: { symbol: 'USDC' }, - formattedBalance: '100.0' - } - ], - outputs: [ - { - token: { symbol: 'DAI' }, - formattedBalance: '2500.0' - }, - { - token: { symbol: 'USDC' }, - formattedBalance: '100.0' - } - ], - inputsList: { - ...mockVaultsList(), - items: [ - { - id: '0xeth', - token: { symbol: 'ETH' }, - formattedBalance: '1.5' - } - ] - }, - outputsList: { - ...mockVaultsList(), - items: [ - { - id: '0xdai', - token: { symbol: 'DAI' }, - formattedBalance: '2500.0' - } - ] - }, - inputsOutputsList: { - ...mockVaultsList(), - items: [ - { - id: '0xusdc', - token: { symbol: 'USDC' }, - formattedBalance: '100.0' - } - ] - } - }; - - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [{ orders: [orderWithMultipleTokens], totalCount: 1 }] }, - status: 'success', - isFetching: false, - isFetched: true - }); - return { unsubscribe: () => {} }; - } - })) as Mock; - render(OrdersListTable, defaultProps as OrdersListTableProps); - - // Verify all tokens are displayed in vault cards - const vaultCards = screen.getAllByTestId('vault-card'); - expect(vaultCards).toHaveLength(4); // 2 inputs + 2 outputs (1 is shared between IO) - - // Verify all input tokens are displayed - expect(screen.getByText('ETH')).toBeInTheDocument(); - expect(screen.getByText('1.5')).toBeInTheDocument(); - - // Verify all output tokens are displayed - expect(screen.getByText('DAI')).toBeInTheDocument(); - expect(screen.getByText('2500.0')).toBeInTheDocument(); - - // Verify shared token is displayed for input and output - expect(screen.getAllByText('USDC')).toHaveLength(2); - expect(screen.getAllByText('100.0')).toHaveLength(2); - }); - - it('displays multiple tokens correctly in grid layout', async () => { - const orderWithMultipleTokens = { - ...mockOrder, - inputs: [ - { - token: { symbol: 'ETH' }, - formattedBalance: '1.5' - }, - { - token: { symbol: 'USDC' }, - formattedBalance: '100.0' - } - ], - outputs: [ - { - token: { symbol: 'DAI' }, - formattedBalance: '2500.0' - }, - { - token: { symbol: 'WBTC' }, - formattedBalance: '0.05' - } - ], - inputsList: { - ...mockVaultsList(), - items: [ - { - token: { symbol: 'ETH' }, - formattedBalance: '1.5' - }, - { - token: { symbol: 'USDC' }, - formattedBalance: '100.0' - } - ] - }, - outputsList: { - ...mockVaultsList(), - items: [ - { - token: { symbol: 'DAI' }, - formattedBalance: '2500.0' - }, - { - token: { symbol: 'WBTC' }, - formattedBalance: '0.05' - } - ] - } - }; - - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [{ orders: [orderWithMultipleTokens], totalCount: 1 }] }, - status: 'success', - isFetching: false, - isFetched: true - }); - return { unsubscribe: () => {} }; - } - })) as Mock; - render(OrdersListTable, defaultProps as OrdersListTableProps); - - // Verify all tokens are displayed in vault cards - const vaultCards = screen.getAllByTestId('vault-card'); - expect(vaultCards).toHaveLength(4); // 2 inputs + 2 outputs - - // Verify all input tokens are displayed - expect(screen.getByText('ETH')).toBeInTheDocument(); - expect(screen.getByText('1.5')).toBeInTheDocument(); - expect(screen.getByText('USDC')).toBeInTheDocument(); - expect(screen.getByText('100.0')).toBeInTheDocument(); - - // Verify all output tokens are displayed - expect(screen.getByText('DAI')).toBeInTheDocument(); - expect(screen.getByText('2500.0')).toBeInTheDocument(); - expect(screen.getByText('WBTC')).toBeInTheDocument(); - expect(screen.getByText('0.05')).toBeInTheDocument(); - }); - - it('shows inactive badge for inactive orders', async () => { - const inactiveOrder = { - ...mockOrder, - active: false - }; - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [{ orders: [inactiveOrder], totalCount: 1 }] }, - status: 'success', - isFetching: false, - isFetched: true - }); - return { unsubscribe: () => {} }; - } - })) as Mock; - render(OrdersListTable, defaultProps as OrdersListTableProps); - - const orderInfoCell = screen.getByTestId('orderListRowOrderInfo'); - expect(orderInfoCell).toHaveTextContent('Inactive'); - }); - - it('displays empty state when no orders are found', async () => { - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [{ orders: [], totalCount: 0 }] }, - status: 'success', - isFetching: false, - isFetched: true - }); - return { unsubscribe: () => {} }; - } - })) as Mock; - - render(OrdersListTable, defaultProps as OrdersListTableProps); - expect(screen.getByText('No Orders Found')).toBeInTheDocument(); - }); - - it('navigates to order details on row click', async () => { - vi.mock('$app/navigation', () => ({ - goto: vi.fn() - })); - - const gotoMock = await import('$app/navigation'); - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [{ orders: [mockOrder], totalCount: 1 }] }, - status: 'success', - isFetching: false, - isFetched: true - }); - return { unsubscribe: () => {} }; - } - })) as Mock; - - render(OrdersListTable, defaultProps as OrdersListTableProps); - - // Simulate row click - const event = new CustomEvent('clickRow', { - detail: { - item: mockOrder - } - }); - - // Find the AppTable component and dispatch the event - const appTable = document.querySelector('div[role="table"]'); - if (appTable) { - appTable.dispatchEvent(event); - expect(gotoMock.goto).toHaveBeenCalledWith( - `/orders/${mockOrder.chainId}-${mockOrder.raindex}-${mockOrder.orderHash}` - ); - } - }); - - it('handles large number of trades display', async () => { - const orderWithManyTrades = { - ...mockOrder, - tradesCount: 100 - }; - - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [{ orders: [orderWithManyTrades], totalCount: 1 }] }, - status: 'success', - isFetching: false, - isFetched: true - }); - return { unsubscribe: () => {} }; - } - })) as Mock; - - render(OrdersListTable, defaultProps as OrdersListTableProps); - expect(screen.getByTestId('orderListRowTrades')).toHaveTextContent('>99'); - }); - - it('shows Take button for active orders', async () => { - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [{ orders: [mockOrder], totalCount: 1 }] }, - status: 'success', - isFetching: false, - isFetched: true - }); - return { unsubscribe: () => {} }; - } - })) as Mock; - - render(OrdersListTable, { - ...defaultProps, - handleTakeOrderModal: vi.fn() - } as OrdersListTableProps); - - expect(screen.getByTestId(`order-take-${mockOrder.id}`)).toBeInTheDocument(); - expect(screen.getByTestId(`order-take-${mockOrder.id}`)).toHaveTextContent('Take'); - }); - - it('does not show Take button for inactive orders', async () => { - const inactiveOrder = { - ...mockOrder, - active: false - }; - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [{ orders: [inactiveOrder], totalCount: 1 }] }, - status: 'success', - isFetching: false, - isFetched: true - }); - return { unsubscribe: () => {} }; - } - })) as Mock; - - render(OrdersListTable, { - ...defaultProps, - handleTakeOrderModal: vi.fn() - } as OrdersListTableProps); - - expect(screen.queryByTestId(`order-take-${inactiveOrder.id}`)).not.toBeInTheDocument(); - }); - - it('calls handleTakeOrderModal when Take button clicked', async () => { - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - const mockRefetch = vi.fn(); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [{ orders: [mockOrder], totalCount: 1 }] }, - status: 'success', - isFetching: false, - isFetched: true, - refetch: mockRefetch - }); - return { unsubscribe: () => {} }; - } - })) as Mock; - - const handleTakeOrderModal = vi.fn(); - - render(OrdersListTable, { - ...defaultProps, - handleTakeOrderModal - } as OrdersListTableProps); - - const takeButton = screen.getByTestId(`order-take-${mockOrder.id}`); - await userEvent.click(takeButton); - - expect(handleTakeOrderModal).toHaveBeenCalledWith(mockOrder, mockRefetch, new Map()); - }); - - it('passes raindexAddresses filter to getOrders when raindexes are selected', async () => { - const raindexAddress = '0x1111111111111111111111111111111111111111'; - - mockActiveRaindexAddressesStore.mockSetSubscribeValue([raindexAddress]); - - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - mockQuery.createInfiniteQuery = vi.fn((options: any) => { - if (options.queryFn) { - options.queryFn({ pageParam: 0 }); - } - return { - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [{ orders: [], totalCount: 0 }] }, - status: 'success', - isFetching: false, - isFetched: true - }); - return { unsubscribe: () => {} }; - } - }; - }) as Mock; - - render(OrdersListTable, defaultProps as OrdersListTableProps); - - await waitFor(() => { - expect(mockGetOrders).toHaveBeenCalledWith( - expect.anything(), - expect.objectContaining({ - raindexAddresses: [raindexAddress] - }), - expect.anything() - ); - }); - }); - - it('does not pass raindexAddresses filter when no raindexes are selected', async () => { - mockActiveRaindexAddressesStore.mockSetSubscribeValue([]); - - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - mockQuery.createInfiniteQuery = vi.fn((options: any) => { - if (options.queryFn) { - options.queryFn({ pageParam: 0 }); - } - return { - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [{ orders: [], totalCount: 0 }] }, - status: 'success', - isFetching: false, - isFetched: true - }); - return { unsubscribe: () => {} }; - } - }; - }) as Mock; - - render(OrdersListTable, defaultProps as OrdersListTableProps); - - await waitFor(() => { - expect(mockGetOrders).toHaveBeenCalledWith( - expect.anything(), - expect.objectContaining({ - raindexAddresses: undefined - }), - expect.anything() - ); - }); - }); +describe("OrdersListTable", () => { + beforeEach(() => { + vi.clearAllMocks(); + (useAccount as Mock).mockReturnValue({ + account: mockAccountStore, + matchesAccount: mockMatchesAccount, + }); + (useRaindexClient as Mock).mockReturnValue({ + getOrders: mockGetOrders, + getTokens: mockGetTokens, + getAllRaindexes: mockGetAllRaindexes.mockReturnValue({ + value: new Map([ + [ + "raindex1", + { + key: "raindex1", + address: "0x1111111111111111111111111111111111111111", + network: { chainId: 1 }, + }, + ], + ]), + error: undefined, + }), + }); + mockGetOrders.mockResolvedValue({ + value: { orders: [], totalCount: 0 }, + error: undefined, + }); + mockGetTokens.mockResolvedValue({ value: [], error: undefined }); + }); + + it("displays order information correctly", async () => { + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ + subscribe: (fn: (value: any) => void) => { + fn({ + data: { pages: [{ orders: [mockOrder], totalCount: 1 }] }, + status: "success", + isFetching: false, + isFetched: true, + }); + return { unsubscribe: () => {} }; + }, + })) as Mock; + render(OrdersListTable, defaultProps as OrdersListTableProps); + + const orderInfoCell = screen.getByTestId("orderListRowOrderInfo"); + expect(orderInfoCell).toHaveTextContent("Ethereum"); + expect(orderInfoCell).toHaveTextContent("Active"); + expect(orderInfoCell).toHaveTextContent("Added:"); + + const addressesCell = screen.getByTestId("orderListRowAddresses"); + expect(addressesCell).toBeInTheDocument(); + expect(addressesCell).toHaveTextContent("Order:"); + expect(addressesCell).toHaveTextContent("Owner:"); + expect(addressesCell).toHaveTextContent("Raindex:"); + + // Check that vault cards are rendered with correct content + const vaultCards = screen.getAllByTestId("vault-card"); + expect(vaultCards).toHaveLength(2); // One input, one output + expect(screen.getByText("ETH")).toBeInTheDocument(); + expect(screen.getByText("1.5")).toBeInTheDocument(); + expect(screen.getByText("DAI")).toBeInTheDocument(); + expect(screen.getByText("2500.0")).toBeInTheDocument(); + + expect(screen.getByTestId("orderListRowTrades")).toHaveTextContent("2"); + }); + + it("displays token information in compact layout", async () => { + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ + subscribe: (fn: (value: any) => void) => { + fn({ + data: { pages: [{ orders: [mockOrder], totalCount: 1 }] }, + status: "success", + isFetching: false, + isFetched: true, + }); + return { unsubscribe: () => {} }; + }, + })) as Mock; + render(OrdersListTable, defaultProps as OrdersListTableProps); + + // Verify token symbols and balances are displayed in vault cards + expect(screen.getByText("ETH")).toBeInTheDocument(); + expect(screen.getByText("1.5")).toBeInTheDocument(); + expect(screen.getByText("DAI")).toBeInTheDocument(); + expect(screen.getByText("2500.0")).toBeInTheDocument(); + + // Verify "Strategy Balance:" label is not present (since we're using vault cards now) + expect(screen.queryByText("Strategy Balance:")).not.toBeInTheDocument(); + }); + + it("displays multiple tokens correctly in grid layout with shared IO", async () => { + const orderWithMultipleTokens = { + ...mockOrder, + inputs: [ + { + token: { symbol: "ETH" }, + formattedBalance: "1.5", + }, + { + token: { symbol: "USDC" }, + formattedBalance: "100.0", + }, + ], + outputs: [ + { + token: { symbol: "DAI" }, + formattedBalance: "2500.0", + }, + { + token: { symbol: "USDC" }, + formattedBalance: "100.0", + }, + ], + inputsList: { + ...mockVaultsList(), + items: [ + { + id: "0xeth", + token: { symbol: "ETH" }, + formattedBalance: "1.5", + }, + ], + }, + outputsList: { + ...mockVaultsList(), + items: [ + { + id: "0xdai", + token: { symbol: "DAI" }, + formattedBalance: "2500.0", + }, + ], + }, + inputsOutputsList: { + ...mockVaultsList(), + items: [ + { + id: "0xusdc", + token: { symbol: "USDC" }, + formattedBalance: "100.0", + }, + ], + }, + }; + + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ + subscribe: (fn: (value: any) => void) => { + fn({ + data: { + pages: [{ orders: [orderWithMultipleTokens], totalCount: 1 }], + }, + status: "success", + isFetching: false, + isFetched: true, + }); + return { unsubscribe: () => {} }; + }, + })) as Mock; + render(OrdersListTable, defaultProps as OrdersListTableProps); + + // Verify all tokens are displayed in vault cards + const vaultCards = screen.getAllByTestId("vault-card"); + expect(vaultCards).toHaveLength(4); // 2 inputs + 2 outputs (1 is shared between IO) + + // Verify all input tokens are displayed + expect(screen.getByText("ETH")).toBeInTheDocument(); + expect(screen.getByText("1.5")).toBeInTheDocument(); + + // Verify all output tokens are displayed + expect(screen.getByText("DAI")).toBeInTheDocument(); + expect(screen.getByText("2500.0")).toBeInTheDocument(); + + // Verify shared token is displayed for input and output + expect(screen.getAllByText("USDC")).toHaveLength(2); + expect(screen.getAllByText("100.0")).toHaveLength(2); + }); + + it("displays multiple tokens correctly in grid layout", async () => { + const orderWithMultipleTokens = { + ...mockOrder, + inputs: [ + { + token: { symbol: "ETH" }, + formattedBalance: "1.5", + }, + { + token: { symbol: "USDC" }, + formattedBalance: "100.0", + }, + ], + outputs: [ + { + token: { symbol: "DAI" }, + formattedBalance: "2500.0", + }, + { + token: { symbol: "WBTC" }, + formattedBalance: "0.05", + }, + ], + inputsList: { + ...mockVaultsList(), + items: [ + { + token: { symbol: "ETH" }, + formattedBalance: "1.5", + }, + { + token: { symbol: "USDC" }, + formattedBalance: "100.0", + }, + ], + }, + outputsList: { + ...mockVaultsList(), + items: [ + { + token: { symbol: "DAI" }, + formattedBalance: "2500.0", + }, + { + token: { symbol: "WBTC" }, + formattedBalance: "0.05", + }, + ], + }, + }; + + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ + subscribe: (fn: (value: any) => void) => { + fn({ + data: { + pages: [{ orders: [orderWithMultipleTokens], totalCount: 1 }], + }, + status: "success", + isFetching: false, + isFetched: true, + }); + return { unsubscribe: () => {} }; + }, + })) as Mock; + render(OrdersListTable, defaultProps as OrdersListTableProps); + + // Verify all tokens are displayed in vault cards + const vaultCards = screen.getAllByTestId("vault-card"); + expect(vaultCards).toHaveLength(4); // 2 inputs + 2 outputs + + // Verify all input tokens are displayed + expect(screen.getByText("ETH")).toBeInTheDocument(); + expect(screen.getByText("1.5")).toBeInTheDocument(); + expect(screen.getByText("USDC")).toBeInTheDocument(); + expect(screen.getByText("100.0")).toBeInTheDocument(); + + // Verify all output tokens are displayed + expect(screen.getByText("DAI")).toBeInTheDocument(); + expect(screen.getByText("2500.0")).toBeInTheDocument(); + expect(screen.getByText("WBTC")).toBeInTheDocument(); + expect(screen.getByText("0.05")).toBeInTheDocument(); + }); + + it("shows inactive badge for inactive orders", async () => { + const inactiveOrder = { + ...mockOrder, + active: false, + }; + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ + subscribe: (fn: (value: any) => void) => { + fn({ + data: { pages: [{ orders: [inactiveOrder], totalCount: 1 }] }, + status: "success", + isFetching: false, + isFetched: true, + }); + return { unsubscribe: () => {} }; + }, + })) as Mock; + render(OrdersListTable, defaultProps as OrdersListTableProps); + + const orderInfoCell = screen.getByTestId("orderListRowOrderInfo"); + expect(orderInfoCell).toHaveTextContent("Inactive"); + }); + + it("displays empty state when no orders are found", async () => { + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ + subscribe: (fn: (value: any) => void) => { + fn({ + data: { pages: [{ orders: [], totalCount: 0 }] }, + status: "success", + isFetching: false, + isFetched: true, + }); + return { unsubscribe: () => {} }; + }, + })) as Mock; + + render(OrdersListTable, defaultProps as OrdersListTableProps); + expect(screen.getByText("No Orders Found")).toBeInTheDocument(); + }); + + it("navigates to order details on row click", async () => { + vi.mock("$app/navigation", () => ({ + goto: vi.fn(), + })); + + const gotoMock = await import("$app/navigation"); + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ + subscribe: (fn: (value: any) => void) => { + fn({ + data: { pages: [{ orders: [mockOrder], totalCount: 1 }] }, + status: "success", + isFetching: false, + isFetched: true, + }); + return { unsubscribe: () => {} }; + }, + })) as Mock; + + render(OrdersListTable, defaultProps as OrdersListTableProps); + + // Simulate row click + const event = new CustomEvent("clickRow", { + detail: { + item: mockOrder, + }, + }); + + // Find the AppTable component and dispatch the event + const appTable = document.querySelector('div[role="table"]'); + if (appTable) { + appTable.dispatchEvent(event); + expect(gotoMock.goto).toHaveBeenCalledWith( + `/orders/${mockOrder.chainId}-${mockOrder.raindex}-${mockOrder.orderHash}`, + ); + } + }); + + it("handles large number of trades display", async () => { + const orderWithManyTrades = { + ...mockOrder, + tradesCount: 100, + }; + + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ + subscribe: (fn: (value: any) => void) => { + fn({ + data: { pages: [{ orders: [orderWithManyTrades], totalCount: 1 }] }, + status: "success", + isFetching: false, + isFetched: true, + }); + return { unsubscribe: () => {} }; + }, + })) as Mock; + + render(OrdersListTable, defaultProps as OrdersListTableProps); + expect(screen.getByTestId("orderListRowTrades")).toHaveTextContent(">99"); + }); + + it("shows Take button for active orders", async () => { + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ + subscribe: (fn: (value: any) => void) => { + fn({ + data: { pages: [{ orders: [mockOrder], totalCount: 1 }] }, + status: "success", + isFetching: false, + isFetched: true, + }); + return { unsubscribe: () => {} }; + }, + })) as Mock; + + render(OrdersListTable, { + ...defaultProps, + handleTakeOrderModal: vi.fn(), + } as OrdersListTableProps); + + expect( + screen.getByTestId(`order-take-${mockOrder.id}`), + ).toBeInTheDocument(); + expect(screen.getByTestId(`order-take-${mockOrder.id}`)).toHaveTextContent( + "Take", + ); + }); + + it("does not show Take button for inactive orders", async () => { + const inactiveOrder = { + ...mockOrder, + active: false, + }; + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ + subscribe: (fn: (value: any) => void) => { + fn({ + data: { pages: [{ orders: [inactiveOrder], totalCount: 1 }] }, + status: "success", + isFetching: false, + isFetched: true, + }); + return { unsubscribe: () => {} }; + }, + })) as Mock; + + render(OrdersListTable, { + ...defaultProps, + handleTakeOrderModal: vi.fn(), + } as OrdersListTableProps); + + expect( + screen.queryByTestId(`order-take-${inactiveOrder.id}`), + ).not.toBeInTheDocument(); + }); + + it("calls handleTakeOrderModal when Take button clicked", async () => { + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + const mockRefetch = vi.fn(); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ + subscribe: (fn: (value: any) => void) => { + fn({ + data: { pages: [{ orders: [mockOrder], totalCount: 1 }] }, + status: "success", + isFetching: false, + isFetched: true, + refetch: mockRefetch, + }); + return { unsubscribe: () => {} }; + }, + })) as Mock; + + const handleTakeOrderModal = vi.fn(); + + render(OrdersListTable, { + ...defaultProps, + handleTakeOrderModal, + } as OrdersListTableProps); + + const takeButton = screen.getByTestId(`order-take-${mockOrder.id}`); + await userEvent.click(takeButton); + + expect(handleTakeOrderModal).toHaveBeenCalledWith( + mockOrder, + mockRefetch, + new Map(), + ); + }); + + it("passes raindexAddresses filter to getOrders when raindexes are selected", async () => { + const raindexAddress = "0x1111111111111111111111111111111111111111"; + + mockActiveRaindexAddressesStore.mockSetSubscribeValue([raindexAddress]); + + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + mockQuery.createInfiniteQuery = vi.fn((options: any) => { + if (options.queryFn) { + options.queryFn({ pageParam: 0 }); + } + return { + subscribe: (fn: (value: any) => void) => { + fn({ + data: { pages: [{ orders: [], totalCount: 0 }] }, + status: "success", + isFetching: false, + isFetched: true, + }); + return { unsubscribe: () => {} }; + }, + }; + }) as Mock; + + render(OrdersListTable, defaultProps as OrdersListTableProps); + + await waitFor(() => { + expect(mockGetOrders).toHaveBeenCalledWith( + expect.anything(), + expect.objectContaining({ + raindexAddresses: [raindexAddress], + }), + expect.anything(), + ); + }); + }); + + it("does not pass raindexAddresses filter when no raindexes are selected", async () => { + mockActiveRaindexAddressesStore.mockSetSubscribeValue([]); + + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + mockQuery.createInfiniteQuery = vi.fn((options: any) => { + if (options.queryFn) { + options.queryFn({ pageParam: 0 }); + } + return { + subscribe: (fn: (value: any) => void) => { + fn({ + data: { pages: [{ orders: [], totalCount: 0 }] }, + status: "success", + isFetching: false, + isFetched: true, + }); + return { unsubscribe: () => {} }; + }, + }; + }) as Mock; + + render(OrdersListTable, defaultProps as OrdersListTableProps); + + await waitFor(() => { + expect(mockGetOrders).toHaveBeenCalledWith( + expect.anything(), + expect.objectContaining({ + raindexAddresses: undefined, + }), + expect.anything(), + ); + }); + }); }); diff --git a/packages/ui-components/src/__tests__/PageHeader.test.ts b/packages/ui-components/src/__tests__/PageHeader.test.ts index 13a7a333aa..87d555a6ba 100644 --- a/packages/ui-components/src/__tests__/PageHeader.test.ts +++ b/packages/ui-components/src/__tests__/PageHeader.test.ts @@ -1,64 +1,72 @@ -import { render, screen, within } from '@testing-library/svelte'; -import { describe, it, expect, vi } from 'vitest'; -import PageHeader from '../lib/components/PageHeader.svelte'; +import { render, screen, within } from "@testing-library/svelte"; +import { describe, it, expect, vi } from "vitest"; +import PageHeader from "../lib/components/PageHeader.svelte"; -vi.mock('../lib/utils/breadcrumbs', () => ({ - generateBreadcrumbs: vi.fn() +vi.mock("../lib/utils/breadcrumbs", () => ({ + generateBreadcrumbs: vi.fn(), })); -import { generateBreadcrumbs } from '../lib/utils/breadcrumbs'; - -describe('PageHeader.svelte', () => { - const mockTitle = 'Test Page'; - const mockPathname = '/test/path'; - const mockCrumbs = [ - { label: 'Test', href: '/test' }, - { label: 'Path', href: '/test/path' } - ]; - - beforeEach(() => { - vi.clearAllMocks(); - vi.mocked(generateBreadcrumbs).mockReturnValue(mockCrumbs); - }); - - it('renders the title correctly', () => { - render(PageHeader, { props: { title: mockTitle, pathname: mockPathname } }); - - expect(screen.getByTestId('breadcrumb-page-title')).toHaveTextContent(mockTitle); - }); - - it('calls generateBreadcrumbs with the correct pathname', () => { - render(PageHeader, { props: { title: mockTitle, pathname: mockPathname } }); - - expect(generateBreadcrumbs).toHaveBeenCalledTimes(1); - expect(generateBreadcrumbs).toHaveBeenCalledWith(mockPathname); - }); - - it('renders the generated breadcrumbs', () => { - render(PageHeader, { props: { title: mockTitle, pathname: mockPathname } }); - - const nav = screen.getByRole('navigation', { name: 'Default breadcrumb example' }); - - const links = within(nav).getAllByRole('link'); - expect(links.length).toBe(1 + mockCrumbs.length); - - expect(links[0]).toHaveAttribute('href', '/'); - - mockCrumbs.forEach((crumb, index) => { - expect(links[index + 1]).toHaveTextContent(crumb.label); - expect(links[index + 1]).toHaveAttribute('href', crumb.href); - }); - }); - - it('handles empty breadcrumbs array', () => { - vi.mocked(generateBreadcrumbs).mockReturnValue([]); - render(PageHeader, { props: { title: mockTitle, pathname: mockPathname } }); - - expect(screen.getByTestId('breadcrumb-page-title')).toHaveTextContent(mockTitle); - - const nav = screen.getByRole('navigation', { name: 'Default breadcrumb example' }); - const links = within(nav).getAllByRole('link'); - expect(links.length).toBe(1); - expect(links[0]).toHaveAttribute('href', '/'); - }); +import { generateBreadcrumbs } from "../lib/utils/breadcrumbs"; + +describe("PageHeader.svelte", () => { + const mockTitle = "Test Page"; + const mockPathname = "/test/path"; + const mockCrumbs = [ + { label: "Test", href: "/test" }, + { label: "Path", href: "/test/path" }, + ]; + + beforeEach(() => { + vi.clearAllMocks(); + vi.mocked(generateBreadcrumbs).mockReturnValue(mockCrumbs); + }); + + it("renders the title correctly", () => { + render(PageHeader, { props: { title: mockTitle, pathname: mockPathname } }); + + expect(screen.getByTestId("breadcrumb-page-title")).toHaveTextContent( + mockTitle, + ); + }); + + it("calls generateBreadcrumbs with the correct pathname", () => { + render(PageHeader, { props: { title: mockTitle, pathname: mockPathname } }); + + expect(generateBreadcrumbs).toHaveBeenCalledTimes(1); + expect(generateBreadcrumbs).toHaveBeenCalledWith(mockPathname); + }); + + it("renders the generated breadcrumbs", () => { + render(PageHeader, { props: { title: mockTitle, pathname: mockPathname } }); + + const nav = screen.getByRole("navigation", { + name: "Default breadcrumb example", + }); + + const links = within(nav).getAllByRole("link"); + expect(links.length).toBe(1 + mockCrumbs.length); + + expect(links[0]).toHaveAttribute("href", "/"); + + mockCrumbs.forEach((crumb, index) => { + expect(links[index + 1]).toHaveTextContent(crumb.label); + expect(links[index + 1]).toHaveAttribute("href", crumb.href); + }); + }); + + it("handles empty breadcrumbs array", () => { + vi.mocked(generateBreadcrumbs).mockReturnValue([]); + render(PageHeader, { props: { title: mockTitle, pathname: mockPathname } }); + + expect(screen.getByTestId("breadcrumb-page-title")).toHaveTextContent( + mockTitle, + ); + + const nav = screen.getByRole("navigation", { + name: "Default breadcrumb example", + }); + const links = within(nav).getAllByRole("link"); + expect(links.length).toBe(1); + expect(links[0]).toHaveAttribute("href", "/"); + }); }); diff --git a/packages/ui-components/src/__tests__/RegistryManager.test.ts b/packages/ui-components/src/__tests__/RegistryManager.test.ts index 8a46732200..830cb4437b 100644 --- a/packages/ui-components/src/__tests__/RegistryManager.test.ts +++ b/packages/ui-components/src/__tests__/RegistryManager.test.ts @@ -1,178 +1,203 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import { RegistryManager } from '../lib/providers/registry/RegistryManager'; +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { RegistryManager } from "../lib/providers/registry/RegistryManager"; -const DEFAULT_REGISTRY_URL = 'https://default.registry.url/registry.json'; -const CUSTOM_REGISTRY_URL = 'https://custom.registry.url/registry.json'; -const STORAGE_KEY = 'registry'; +const DEFAULT_REGISTRY_URL = "https://default.registry.url/registry.json"; +const CUSTOM_REGISTRY_URL = "https://custom.registry.url/registry.json"; +const STORAGE_KEY = "registry"; const mockLocalStorage = (() => { - let store: Record = {}; - return { - getItem: vi.fn((key: string) => store[key] || null), - setItem: vi.fn((key: string, value: string) => { - store[key] = value; - }), - removeItem: vi.fn((key: string) => { - delete store[key]; - }), - clear: () => { - store = {}; - }, - getStore: () => store - }; + let store: Record = {}; + return { + getItem: vi.fn((key: string) => store[key] || null), + setItem: vi.fn((key: string, value: string) => { + store[key] = value; + }), + removeItem: vi.fn((key: string) => { + delete store[key]; + }), + clear: () => { + store = {}; + }, + getStore: () => store, + }; })(); const mockLocation = (searchParams: URLSearchParams) => ({ - href: `http://localhost/?${searchParams.toString()}`, - searchParams + href: `http://localhost/?${searchParams.toString()}`, + searchParams, }); const mockHistory = { - pushState: vi.fn() + pushState: vi.fn(), }; -vi.stubGlobal('localStorage', mockLocalStorage); -vi.stubGlobal('history', mockHistory); +vi.stubGlobal("localStorage", mockLocalStorage); +vi.stubGlobal("history", mockHistory); const setMockLocation = (params: Record) => { - const searchParams = new URLSearchParams(params); - Object.defineProperty(window, 'location', { - value: mockLocation(searchParams), - writable: true - }); + const searchParams = new URLSearchParams(params); + Object.defineProperty(window, "location", { + value: mockLocation(searchParams), + writable: true, + }); }; -describe('RegistryManager', () => { - beforeEach(() => { - mockLocalStorage.clear(); - vi.clearAllMocks(); - setMockLocation({}); - }); - - it('should initialize with default registry if no URL param or localStorage', () => { - const manager = new RegistryManager(DEFAULT_REGISTRY_URL); - expect(manager.getCurrentRegistry()).toBe(DEFAULT_REGISTRY_URL); - expect(mockLocalStorage.getItem).toHaveBeenCalledWith(STORAGE_KEY); - expect(mockLocalStorage.setItem).not.toHaveBeenCalled(); - }); - - it('should initialize with URL parameter if present', () => { - setMockLocation({ [STORAGE_KEY]: CUSTOM_REGISTRY_URL }); - const manager = new RegistryManager(DEFAULT_REGISTRY_URL); - expect(manager.getCurrentRegistry()).toBe(CUSTOM_REGISTRY_URL); - expect(mockLocalStorage.setItem).toHaveBeenCalledWith(STORAGE_KEY, CUSTOM_REGISTRY_URL); - }); - - it('should initialize with localStorage value if present (and no URL param)', () => { - mockLocalStorage.setItem(STORAGE_KEY, CUSTOM_REGISTRY_URL); - const manager = new RegistryManager(DEFAULT_REGISTRY_URL); - expect(manager.getCurrentRegistry()).toBe(CUSTOM_REGISTRY_URL); - expect(mockLocalStorage.getItem).toHaveBeenCalledWith(STORAGE_KEY); - expect(mockLocalStorage.setItem).toHaveBeenCalledTimes(1); - }); - - it('should prioritize URL parameter over localStorage on initialization', () => { - const urlRegistry = 'https://from.url/registry.json'; - setMockLocation({ [STORAGE_KEY]: urlRegistry }); - mockLocalStorage.setItem(STORAGE_KEY, CUSTOM_REGISTRY_URL); - - const manager = new RegistryManager(DEFAULT_REGISTRY_URL); - expect(manager.getCurrentRegistry()).toBe(urlRegistry); - expect(mockLocalStorage.setItem).toHaveBeenCalledWith(STORAGE_KEY, urlRegistry); - }); - - it('getCurrentRegistry() should return the current registry', () => { - const manager = new RegistryManager(DEFAULT_REGISTRY_URL); - expect(manager.getCurrentRegistry()).toBe(DEFAULT_REGISTRY_URL); - - setMockLocation({ [STORAGE_KEY]: CUSTOM_REGISTRY_URL }); - const manager2 = new RegistryManager(DEFAULT_REGISTRY_URL); - expect(manager2.getCurrentRegistry()).toBe(CUSTOM_REGISTRY_URL); - }); - - it('setRegistry() should update current registry, localStorage, and URL', () => { - const manager = new RegistryManager(DEFAULT_REGISTRY_URL); - manager.setRegistry(CUSTOM_REGISTRY_URL); - - expect(manager.getCurrentRegistry()).toBe(CUSTOM_REGISTRY_URL); - expect(mockLocalStorage.setItem).toHaveBeenCalledWith(STORAGE_KEY, CUSTOM_REGISTRY_URL); - expect(mockHistory.pushState).toHaveBeenCalledTimes(1); - const expectedUrl = new URL(window.location.href); - expectedUrl.searchParams.set(STORAGE_KEY, CUSTOM_REGISTRY_URL); - expect(mockHistory.pushState).toHaveBeenCalledWith({}, '', expectedUrl.toString()); - }); - - it('resetToDefault() should reset registry, clear localStorage, and update URL', () => { - mockLocalStorage.setItem(STORAGE_KEY, CUSTOM_REGISTRY_URL); - setMockLocation({ [STORAGE_KEY]: CUSTOM_REGISTRY_URL }); - const manager = new RegistryManager(DEFAULT_REGISTRY_URL); - expect(manager.getCurrentRegistry()).toBe(CUSTOM_REGISTRY_URL); - - manager.resetToDefault(); - - expect(manager.getCurrentRegistry()).toBe(DEFAULT_REGISTRY_URL); - expect(mockLocalStorage.removeItem).toHaveBeenCalledWith(STORAGE_KEY); - expect(mockHistory.pushState).toHaveBeenCalledTimes(1); - const expectedUrl = new URL(window.location.href); - expectedUrl.searchParams.delete(STORAGE_KEY); - expect(mockHistory.pushState).toHaveBeenCalledWith({}, '', expectedUrl.toString()); - }); - - it('updateUrlWithRegistry() should update URL search parameter', () => { - const manager = new RegistryManager(DEFAULT_REGISTRY_URL); - manager.updateUrlWithRegistry(CUSTOM_REGISTRY_URL); - - expect(mockHistory.pushState).toHaveBeenCalledTimes(1); - const expectedUrl = new URL(window.location.href); - expectedUrl.searchParams.set(STORAGE_KEY, CUSTOM_REGISTRY_URL); - expect(mockHistory.pushState).toHaveBeenCalledWith({}, '', expectedUrl.toString()); - }); - - it('updateUrlWithRegistry() should remove URL search parameter when value is null', () => { - setMockLocation({ [STORAGE_KEY]: CUSTOM_REGISTRY_URL }); - const manager = new RegistryManager(DEFAULT_REGISTRY_URL); - manager.updateUrlWithRegistry(null); - - expect(mockHistory.pushState).toHaveBeenCalledTimes(1); - const expectedUrl = new URL(window.location.href); - expectedUrl.searchParams.delete(STORAGE_KEY); - expect(mockHistory.pushState).toHaveBeenCalledWith({}, '', expectedUrl.toString()); - }); - - it('isCustomRegistry() should return false when using default registry', () => { - const manager = new RegistryManager(DEFAULT_REGISTRY_URL); - expect(manager.isCustomRegistry()).toBe(false); - }); - - it('isCustomRegistry() should return true when using a custom registry', () => { - mockLocalStorage.setItem(STORAGE_KEY, CUSTOM_REGISTRY_URL); - const manager = new RegistryManager(DEFAULT_REGISTRY_URL); - expect(manager.isCustomRegistry()).toBe(true); - }); - - it('isCustomRegistry() should return false after resetting to default', () => { - mockLocalStorage.setItem(STORAGE_KEY, CUSTOM_REGISTRY_URL); - const manager = new RegistryManager(DEFAULT_REGISTRY_URL); - expect(manager.isCustomRegistry()).toBe(true); - manager.resetToDefault(); - expect(manager.isCustomRegistry()).toBe(false); - }); - - it('should handle localStorage errors gracefully (at least not crash)', () => { - vi.spyOn(mockLocalStorage, 'getItem').mockImplementation(() => { - throw new Error('localStorage unavailable'); - }); - vi.spyOn(mockLocalStorage, 'setItem').mockImplementation(() => { - throw new Error('localStorage unavailable'); - }); - vi.spyOn(mockLocalStorage, 'removeItem').mockImplementation(() => { - throw new Error('localStorage unavailable'); - }); - - expect(() => new RegistryManager(DEFAULT_REGISTRY_URL)).toThrow( - /Failed to access localStorage|Failed to save to localStorage/ - ); - - vi.restoreAllMocks(); - }); +describe("RegistryManager", () => { + beforeEach(() => { + mockLocalStorage.clear(); + vi.clearAllMocks(); + setMockLocation({}); + }); + + it("should initialize with default registry if no URL param or localStorage", () => { + const manager = new RegistryManager(DEFAULT_REGISTRY_URL); + expect(manager.getCurrentRegistry()).toBe(DEFAULT_REGISTRY_URL); + expect(mockLocalStorage.getItem).toHaveBeenCalledWith(STORAGE_KEY); + expect(mockLocalStorage.setItem).not.toHaveBeenCalled(); + }); + + it("should initialize with URL parameter if present", () => { + setMockLocation({ [STORAGE_KEY]: CUSTOM_REGISTRY_URL }); + const manager = new RegistryManager(DEFAULT_REGISTRY_URL); + expect(manager.getCurrentRegistry()).toBe(CUSTOM_REGISTRY_URL); + expect(mockLocalStorage.setItem).toHaveBeenCalledWith( + STORAGE_KEY, + CUSTOM_REGISTRY_URL, + ); + }); + + it("should initialize with localStorage value if present (and no URL param)", () => { + mockLocalStorage.setItem(STORAGE_KEY, CUSTOM_REGISTRY_URL); + const manager = new RegistryManager(DEFAULT_REGISTRY_URL); + expect(manager.getCurrentRegistry()).toBe(CUSTOM_REGISTRY_URL); + expect(mockLocalStorage.getItem).toHaveBeenCalledWith(STORAGE_KEY); + expect(mockLocalStorage.setItem).toHaveBeenCalledTimes(1); + }); + + it("should prioritize URL parameter over localStorage on initialization", () => { + const urlRegistry = "https://from.url/registry.json"; + setMockLocation({ [STORAGE_KEY]: urlRegistry }); + mockLocalStorage.setItem(STORAGE_KEY, CUSTOM_REGISTRY_URL); + + const manager = new RegistryManager(DEFAULT_REGISTRY_URL); + expect(manager.getCurrentRegistry()).toBe(urlRegistry); + expect(mockLocalStorage.setItem).toHaveBeenCalledWith( + STORAGE_KEY, + urlRegistry, + ); + }); + + it("getCurrentRegistry() should return the current registry", () => { + const manager = new RegistryManager(DEFAULT_REGISTRY_URL); + expect(manager.getCurrentRegistry()).toBe(DEFAULT_REGISTRY_URL); + + setMockLocation({ [STORAGE_KEY]: CUSTOM_REGISTRY_URL }); + const manager2 = new RegistryManager(DEFAULT_REGISTRY_URL); + expect(manager2.getCurrentRegistry()).toBe(CUSTOM_REGISTRY_URL); + }); + + it("setRegistry() should update current registry, localStorage, and URL", () => { + const manager = new RegistryManager(DEFAULT_REGISTRY_URL); + manager.setRegistry(CUSTOM_REGISTRY_URL); + + expect(manager.getCurrentRegistry()).toBe(CUSTOM_REGISTRY_URL); + expect(mockLocalStorage.setItem).toHaveBeenCalledWith( + STORAGE_KEY, + CUSTOM_REGISTRY_URL, + ); + expect(mockHistory.pushState).toHaveBeenCalledTimes(1); + const expectedUrl = new URL(window.location.href); + expectedUrl.searchParams.set(STORAGE_KEY, CUSTOM_REGISTRY_URL); + expect(mockHistory.pushState).toHaveBeenCalledWith( + {}, + "", + expectedUrl.toString(), + ); + }); + + it("resetToDefault() should reset registry, clear localStorage, and update URL", () => { + mockLocalStorage.setItem(STORAGE_KEY, CUSTOM_REGISTRY_URL); + setMockLocation({ [STORAGE_KEY]: CUSTOM_REGISTRY_URL }); + const manager = new RegistryManager(DEFAULT_REGISTRY_URL); + expect(manager.getCurrentRegistry()).toBe(CUSTOM_REGISTRY_URL); + + manager.resetToDefault(); + + expect(manager.getCurrentRegistry()).toBe(DEFAULT_REGISTRY_URL); + expect(mockLocalStorage.removeItem).toHaveBeenCalledWith(STORAGE_KEY); + expect(mockHistory.pushState).toHaveBeenCalledTimes(1); + const expectedUrl = new URL(window.location.href); + expectedUrl.searchParams.delete(STORAGE_KEY); + expect(mockHistory.pushState).toHaveBeenCalledWith( + {}, + "", + expectedUrl.toString(), + ); + }); + + it("updateUrlWithRegistry() should update URL search parameter", () => { + const manager = new RegistryManager(DEFAULT_REGISTRY_URL); + manager.updateUrlWithRegistry(CUSTOM_REGISTRY_URL); + + expect(mockHistory.pushState).toHaveBeenCalledTimes(1); + const expectedUrl = new URL(window.location.href); + expectedUrl.searchParams.set(STORAGE_KEY, CUSTOM_REGISTRY_URL); + expect(mockHistory.pushState).toHaveBeenCalledWith( + {}, + "", + expectedUrl.toString(), + ); + }); + + it("updateUrlWithRegistry() should remove URL search parameter when value is null", () => { + setMockLocation({ [STORAGE_KEY]: CUSTOM_REGISTRY_URL }); + const manager = new RegistryManager(DEFAULT_REGISTRY_URL); + manager.updateUrlWithRegistry(null); + + expect(mockHistory.pushState).toHaveBeenCalledTimes(1); + const expectedUrl = new URL(window.location.href); + expectedUrl.searchParams.delete(STORAGE_KEY); + expect(mockHistory.pushState).toHaveBeenCalledWith( + {}, + "", + expectedUrl.toString(), + ); + }); + + it("isCustomRegistry() should return false when using default registry", () => { + const manager = new RegistryManager(DEFAULT_REGISTRY_URL); + expect(manager.isCustomRegistry()).toBe(false); + }); + + it("isCustomRegistry() should return true when using a custom registry", () => { + mockLocalStorage.setItem(STORAGE_KEY, CUSTOM_REGISTRY_URL); + const manager = new RegistryManager(DEFAULT_REGISTRY_URL); + expect(manager.isCustomRegistry()).toBe(true); + }); + + it("isCustomRegistry() should return false after resetting to default", () => { + mockLocalStorage.setItem(STORAGE_KEY, CUSTOM_REGISTRY_URL); + const manager = new RegistryManager(DEFAULT_REGISTRY_URL); + expect(manager.isCustomRegistry()).toBe(true); + manager.resetToDefault(); + expect(manager.isCustomRegistry()).toBe(false); + }); + + it("should handle localStorage errors gracefully (at least not crash)", () => { + vi.spyOn(mockLocalStorage, "getItem").mockImplementation(() => { + throw new Error("localStorage unavailable"); + }); + vi.spyOn(mockLocalStorage, "setItem").mockImplementation(() => { + throw new Error("localStorage unavailable"); + }); + vi.spyOn(mockLocalStorage, "removeItem").mockImplementation(() => { + throw new Error("localStorage unavailable"); + }); + + expect(() => new RegistryManager(DEFAULT_REGISTRY_URL)).toThrow( + /Failed to access localStorage|Failed to save to localStorage/, + ); + + vi.restoreAllMocks(); + }); }); diff --git a/packages/ui-components/src/__tests__/SelectToken.test.ts b/packages/ui-components/src/__tests__/SelectToken.test.ts index acc2b036bc..30dab41368 100644 --- a/packages/ui-components/src/__tests__/SelectToken.test.ts +++ b/packages/ui-components/src/__tests__/SelectToken.test.ts @@ -1,460 +1,482 @@ -import { render, screen, waitFor } from '@testing-library/svelte'; -import userEvent from '@testing-library/user-event'; -import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; -import SelectToken from '../lib/components/deployment/SelectToken.svelte'; -import type { ComponentProps } from 'svelte'; -import { Float, type AccountBalance, type RaindexOrderBuilder } from '@rainlanguage/raindex'; -import { useRaindexOrderBuilder } from '$lib/hooks/useRaindexOrderBuilder'; -import type { TokenBalance } from '$lib/types/tokenBalance'; +import { render, screen, waitFor } from "@testing-library/svelte"; +import userEvent from "@testing-library/user-event"; +import { describe, it, expect, vi, beforeEach, type Mock } from "vitest"; +import SelectToken from "../lib/components/deployment/SelectToken.svelte"; +import type { ComponentProps } from "svelte"; +import { + Float, + type AccountBalance, + type RaindexOrderBuilder, +} from "@rainlanguage/raindex"; +import { useRaindexOrderBuilder } from "$lib/hooks/useRaindexOrderBuilder"; +import type { TokenBalance } from "$lib/types/tokenBalance"; type SelectTokenComponentProps = ComponentProps; const mockBuilder: RaindexOrderBuilder = { - setSelectToken: vi.fn(), - isSelectTokenSet: vi.fn(), - unsetSelectToken: vi.fn(), - getTokenInfo: vi.fn().mockResolvedValue({ - value: { - name: 'Ethereum', - symbol: 'ETH', - decimals: 18, - address: '0x456' - } - }), - getAllTokens: vi.fn().mockResolvedValue({ - value: [ - { - key: 'token1', - address: '0x1234567890123456789012345678901234567890', - name: 'Test Token 1', - symbol: 'TEST1', - decimals: 18 - }, - { - key: 'token2', - address: '0x0987654321098765432109876543210987654321', - name: 'Another Token', - symbol: 'ANOTHER', - decimals: 6 - } - ] - }) + setSelectToken: vi.fn(), + isSelectTokenSet: vi.fn(), + unsetSelectToken: vi.fn(), + getTokenInfo: vi.fn().mockResolvedValue({ + value: { + name: "Ethereum", + symbol: "ETH", + decimals: 18, + address: "0x456", + }, + }), + getAllTokens: vi.fn().mockResolvedValue({ + value: [ + { + key: "token1", + address: "0x1234567890123456789012345678901234567890", + name: "Test Token 1", + symbol: "TEST1", + decimals: 18, + }, + { + key: "token2", + address: "0x0987654321098765432109876543210987654321", + name: "Another Token", + symbol: "ANOTHER", + decimals: 6, + }, + ], + }), } as unknown as RaindexOrderBuilder; -vi.mock('@rainlanguage/raindex', async (importOriginal) => { - return { - ...(await importOriginal()) - }; +vi.mock("@rainlanguage/raindex", async (importOriginal) => { + return { + ...(await importOriginal()), + }; }); -vi.mock('../lib/hooks/useRaindexOrderBuilder', () => ({ - useRaindexOrderBuilder: vi.fn() +vi.mock("../lib/hooks/useRaindexOrderBuilder", () => ({ + useRaindexOrderBuilder: vi.fn(), })); -describe('SelectToken', () => { - let mockStateUpdateCallback: Mock; - - const mockProps: SelectTokenComponentProps = { - token: { - key: 'input', - name: 'test input', - description: 'test description' - }, - onSelectTokenSelect: vi.fn(), - tokenBalances: new Map() - }; - - beforeEach(() => { - mockStateUpdateCallback = vi.fn(); - mockBuilder.setSelectToken = vi.fn().mockImplementation(() => { - mockStateUpdateCallback(); - return Promise.resolve(); - }); - (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilder); - vi.clearAllMocks(); - }); - - it('renders token label correctly', () => { - const { getByText } = render(SelectToken, mockProps); - expect(getByText('test input')).toBeInTheDocument(); - }); - - it('renders dropdown button when tokens are available', () => { - const { getByText } = render(SelectToken, mockProps); - expect(getByText('Select a token...')).toBeInTheDocument(); - }); - - it('calls setSelectToken and updates token info when input changes', async () => { - const user = userEvent.setup(); - const mockBuilderWithNoToken = { - ...mockBuilder, - getTokenInfo: vi.fn().mockResolvedValue({ value: null }) - } as unknown as RaindexOrderBuilder; - - (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilderWithNoToken); - - const { getByTestId, getByRole } = render(SelectToken, { - ...mockProps - }); - - const customButton = getByTestId('custom-mode-button'); - await user.click(customButton); - - const input = getByRole('textbox'); - - await userEvent.clear(input); - await user.paste('0x456'); - - await waitFor(() => { - expect(mockBuilderWithNoToken.setSelectToken).toHaveBeenCalledWith('input', '0x456'); - }); - expect(mockStateUpdateCallback).toHaveBeenCalledTimes(1); - }); - - it('shows error message for invalid address, and removes the selectToken', async () => { - const user = userEvent.setup(); - const mockBuilderWithError = { - ...mockBuilder, - setSelectToken: vi.fn().mockRejectedValue(new Error('Invalid address')) - } as unknown as RaindexOrderBuilder; - - (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilderWithError); - - const screen = render(SelectToken, { - ...mockProps - }); - - const customButton = screen.getByTestId('custom-mode-button'); - await user.click(customButton); - - const input = screen.getByRole('textbox'); - await userEvent.clear(input); - await user.paste('invalid'); - await waitFor(() => { - expect(screen.getByTestId('error')).toBeInTheDocument(); - }); - }); - - it('replaces the token and triggers state update twice if the token is already set', async () => { - const mockBuilderWithTokenSet = { - ...mockBuilder, - isSelectTokenSet: vi.fn().mockResolvedValue(true) - } as unknown as RaindexOrderBuilder; - - (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilderWithTokenSet); - - const user = userEvent.setup(); - - const { getByRole, getByTestId } = render(SelectToken, { - ...mockProps - }); +describe("SelectToken", () => { + let mockStateUpdateCallback: Mock; + + const mockProps: SelectTokenComponentProps = { + token: { + key: "input", + name: "test input", + description: "test description", + }, + onSelectTokenSelect: vi.fn(), + tokenBalances: new Map(), + }; + + beforeEach(() => { + mockStateUpdateCallback = vi.fn(); + mockBuilder.setSelectToken = vi.fn().mockImplementation(() => { + mockStateUpdateCallback(); + return Promise.resolve(); + }); + (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilder); + vi.clearAllMocks(); + }); + + it("renders token label correctly", () => { + const { getByText } = render(SelectToken, mockProps); + expect(getByText("test input")).toBeInTheDocument(); + }); + + it("renders dropdown button when tokens are available", () => { + const { getByText } = render(SelectToken, mockProps); + expect(getByText("Select a token...")).toBeInTheDocument(); + }); + + it("calls setSelectToken and updates token info when input changes", async () => { + const user = userEvent.setup(); + const mockBuilderWithNoToken = { + ...mockBuilder, + getTokenInfo: vi.fn().mockResolvedValue({ value: null }), + } as unknown as RaindexOrderBuilder; + + (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilderWithNoToken); + + const { getByTestId, getByRole } = render(SelectToken, { + ...mockProps, + }); + + const customButton = getByTestId("custom-mode-button"); + await user.click(customButton); + + const input = getByRole("textbox"); + + await userEvent.clear(input); + await user.paste("0x456"); + + await waitFor(() => { + expect(mockBuilderWithNoToken.setSelectToken).toHaveBeenCalledWith( + "input", + "0x456", + ); + }); + expect(mockStateUpdateCallback).toHaveBeenCalledTimes(1); + }); + + it("shows error message for invalid address, and removes the selectToken", async () => { + const user = userEvent.setup(); + const mockBuilderWithError = { + ...mockBuilder, + setSelectToken: vi.fn().mockRejectedValue(new Error("Invalid address")), + } as unknown as RaindexOrderBuilder; + + (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilderWithError); + + const screen = render(SelectToken, { + ...mockProps, + }); + + const customButton = screen.getByTestId("custom-mode-button"); + await user.click(customButton); + + const input = screen.getByRole("textbox"); + await userEvent.clear(input); + await user.paste("invalid"); + await waitFor(() => { + expect(screen.getByTestId("error")).toBeInTheDocument(); + }); + }); + + it("replaces the token and triggers state update twice if the token is already set", async () => { + const mockBuilderWithTokenSet = { + ...mockBuilder, + isSelectTokenSet: vi.fn().mockResolvedValue(true), + } as unknown as RaindexOrderBuilder; + + (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilderWithTokenSet); + + const user = userEvent.setup(); + + const { getByRole, getByTestId } = render(SelectToken, { + ...mockProps, + }); + + const customButton = getByTestId("custom-mode-button"); + await user.click(customButton); + + const input = getByRole("textbox"); + await userEvent.clear(input); + await user.paste("invalid"); + await waitFor(() => { + expect(mockBuilderWithTokenSet.setSelectToken).toHaveBeenCalled(); + expect(mockStateUpdateCallback).toHaveBeenCalledTimes(1); + }); + }); + + it("calls onSelectTokenSelect after input changes", async () => { + const user = userEvent.setup(); + const { getByRole, getByTestId } = render(SelectToken, mockProps); + + const customButton = getByTestId("custom-mode-button"); + await user.click(customButton); - const customButton = getByTestId('custom-mode-button'); - await user.click(customButton); - - const input = getByRole('textbox'); - await userEvent.clear(input); - await user.paste('invalid'); - await waitFor(() => { - expect(mockBuilderWithTokenSet.setSelectToken).toHaveBeenCalled(); - expect(mockStateUpdateCallback).toHaveBeenCalledTimes(1); - }); - }); + const input = getByRole("textbox"); - it('calls onSelectTokenSelect after input changes', async () => { - const user = userEvent.setup(); - const { getByRole, getByTestId } = render(SelectToken, mockProps); + await userEvent.clear(input); + await user.paste("0x456"); + + await waitFor(() => { + expect(mockProps.onSelectTokenSelect).toHaveBeenCalled(); + }); + }); + + describe("Dropdown Mode", () => { + beforeEach(() => { + (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilder); + }); - const customButton = getByTestId('custom-mode-button'); - await user.click(customButton); + it("shows dropdown and custom mode buttons when tokens are available", () => { + render(SelectToken, mockProps); - const input = getByRole('textbox'); + expect(screen.getByTestId("dropdown-mode-button")).toBeInTheDocument(); + expect(screen.getByTestId("custom-mode-button")).toBeInTheDocument(); + }); - await userEvent.clear(input); - await user.paste('0x456'); + it("shows dropdown mode as active by default", () => { + render(SelectToken, mockProps); - await waitFor(() => { - expect(mockProps.onSelectTokenSelect).toHaveBeenCalled(); - }); - }); + const dropdownButton = screen.getByTestId("dropdown-mode-button"); + const customButton = screen.getByTestId("custom-mode-button"); - describe('Dropdown Mode', () => { - beforeEach(() => { - (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilder); - }); + expect(dropdownButton).toHaveClass("border-blue-300"); + expect(customButton).not.toHaveClass("border-blue-300"); + }); + + it("switches to custom mode when custom button is clicked", async () => { + const user = userEvent.setup(); + render(SelectToken, mockProps); + + const customButton = screen.getByTestId("custom-mode-button"); + await user.click(customButton); - it('shows dropdown and custom mode buttons when tokens are available', () => { - render(SelectToken, mockProps); + expect(customButton).toHaveClass("border-blue-300"); + expect(screen.getByTestId("dropdown-mode-button")).not.toHaveClass( + "border-blue-300", + ); + }); + + it("shows TokenSelectionModal component in dropdown mode", () => { + render(SelectToken, mockProps); + + expect(screen.getByText("Select a token...")).toBeInTheDocument(); + }); - expect(screen.getByTestId('dropdown-mode-button')).toBeInTheDocument(); - expect(screen.getByTestId('custom-mode-button')).toBeInTheDocument(); - }); + it("shows custom input in custom mode", async () => { + const user = userEvent.setup(); + render(SelectToken, mockProps); - it('shows dropdown mode as active by default', () => { - render(SelectToken, mockProps); - - const dropdownButton = screen.getByTestId('dropdown-mode-button'); - const customButton = screen.getByTestId('custom-mode-button'); - - expect(dropdownButton).toHaveClass('border-blue-300'); - expect(customButton).not.toHaveClass('border-blue-300'); - }); - - it('switches to custom mode when custom button is clicked', async () => { - const user = userEvent.setup(); - render(SelectToken, mockProps); - - const customButton = screen.getByTestId('custom-mode-button'); - await user.click(customButton); - - expect(customButton).toHaveClass('border-blue-300'); - expect(screen.getByTestId('dropdown-mode-button')).not.toHaveClass('border-blue-300'); - }); - - it('shows TokenSelectionModal component in dropdown mode', () => { - render(SelectToken, mockProps); - - expect(screen.getByText('Select a token...')).toBeInTheDocument(); - }); - - it('shows custom input in custom mode', async () => { - const user = userEvent.setup(); - render(SelectToken, mockProps); - - const customButton = screen.getByTestId('custom-mode-button'); - await user.click(customButton); - - expect(screen.getByPlaceholderText('Enter token address (0x...)')).toBeInTheDocument(); - }); - - it('clears state when switching from dropdown to custom mode', async () => { - const user = userEvent.setup(); - const mockBuilderNoToken = { - ...mockBuilder, - getTokenInfo: vi.fn().mockResolvedValue({ value: null }) - } as unknown as RaindexOrderBuilder; - - (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilderNoToken); - - render(SelectToken, { - ...mockProps - }); - - const dropdownButton = screen.getByText('Select a token...'); - await user.click(dropdownButton); - - const firstToken = screen.getByText('Test Token 1'); - await user.click(firstToken); - - const customButton = screen.getByTestId('custom-mode-button'); - await user.click(customButton); - - const customInput = screen.getByPlaceholderText('Enter token address (0x...)'); - expect(customInput).toHaveValue(''); - - expect(mockBuilderNoToken.unsetSelectToken).toHaveBeenCalledWith('input'); - }); - - it('clears state when switching from custom to dropdown mode', async () => { - const user = userEvent.setup(); - render(SelectToken, mockProps); - - const customButton = screen.getByTestId('custom-mode-button'); - await user.click(customButton); - - const customInput = screen.getByPlaceholderText('Enter token address (0x...)'); - await user.type(customInput, '0x1234567890123456789012345678901234567890'); - - const dropdownButton = screen.getByTestId('dropdown-mode-button'); - await user.click(dropdownButton); - - expect(mockBuilder.unsetSelectToken).toHaveBeenCalledWith('input'); - }); - - it('handles token selection from dropdown', async () => { - const user = userEvent.setup(); - const mockBuilderNoToken = { - ...mockBuilder, - getTokenInfo: vi.fn().mockResolvedValue({ value: null }) - } as unknown as RaindexOrderBuilder; - - (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilderNoToken); - - render(SelectToken, { - ...mockProps - }); - - const dropdownButton = screen.getByText('Select a token...'); - await user.click(dropdownButton); - - const secondToken = screen.getByText('Another Token'); - await user.click(secondToken); - - expect(mockBuilderNoToken.setSelectToken).toHaveBeenCalledWith( - 'input', - '0x0987654321098765432109876543210987654321' - ); - }); - - it('displays selected token info when token is selected', async () => { - mockBuilder.getTokenInfo = vi.fn().mockResolvedValue({ - value: { - name: 'Test Token 1', - symbol: 'TEST1', - address: '0x1234567890123456789012345678901234567890', - decimals: 18 - } - }); - - render(SelectToken, mockProps); - - await waitFor(() => { - expect(screen.getByText('Test Token 1')).toBeInTheDocument(); - }); - - expect(screen.getByTestId(`select-token-success-${mockProps.token.key}`)).toBeInTheDocument(); - }); - }); - - describe('Balance Display', () => { - it('displays balance when token is selected and balance is provided', async () => { - mockBuilder.getTokenInfo = vi.fn().mockResolvedValue({ - value: { - name: 'Test Token', - symbol: 'TEST', - address: '0x1234567890123456789012345678901234567890', - decimals: 18, - key: 'input' - } - }); - - const tokenBalances = new Map(); - tokenBalances.set('input', { - value: { - balance: Float.parse('1').value, - formattedBalance: '1' - } as AccountBalance, - loading: false, - error: '' - }); - - render(SelectToken, { - ...mockProps, - tokenBalances - }); - - await waitFor(() => { - expect(screen.getByText('Test Token')).toBeInTheDocument(); - }); - - await waitFor(() => { - expect(screen.getByText('Balance: 1')).toBeInTheDocument(); - }); - }); - - it('shows loading spinner when balance is loading', async () => { - mockBuilder.getTokenInfo = vi.fn().mockResolvedValue({ - value: { - name: 'Test Token', - symbol: 'TEST', - address: '0x1234567890123456789012345678901234567890', - decimals: 18, - key: 'input' - } - }); - - const tokenBalances = new Map(); - tokenBalances.set('input', { - value: { - balance: Float.parse('0').value, - formattedBalance: '0' - } as AccountBalance, - loading: true, - error: '' - }); - - render(SelectToken, { - ...mockProps, - tokenBalances - }); - - await waitFor(() => { - expect(screen.getByText('Test Token')).toBeInTheDocument(); - }); - - // Check for spinner (we can't easily test the spinner component directly, so we test for its presence) - const tokenStatus = screen.getByTestId(`select-token-success-${mockProps.token.key}`); - expect(tokenStatus).toBeInTheDocument(); - }); - - it('shows error message when balance fetch fails', async () => { - mockBuilder.getTokenInfo = vi.fn().mockResolvedValue({ - value: { - name: 'Test Token', - symbol: 'TEST', - address: '0x1234567890123456789012345678901234567890', - decimals: 18, - key: 'input' - } - }); - - const tokenBalances = new Map(); - tokenBalances.set('input', { - value: { - balance: Float.parse('0').value, - formattedBalance: '0' - } as AccountBalance, - loading: false, - error: 'Network error' - }); - - render(SelectToken, { - ...mockProps, - tokenBalances - }); - - await waitFor(() => { - expect(screen.getByText('Test Token')).toBeInTheDocument(); - }); - - await waitFor(() => { - expect(screen.getByText('Network error')).toBeInTheDocument(); - }); - }); - - it('formats balance correctly with token decimals', async () => { - mockBuilder.getTokenInfo = vi.fn().mockResolvedValue({ - value: { - name: 'USDC', - symbol: 'USDC', - address: '0x1234567890123456789012345678901234567890', - decimals: 6, - key: 'input' - } - }); - - const tokenBalances = new Map(); - tokenBalances.set('input', { - value: { - balance: Float.parse('1.5').value, - formattedBalance: '1.5' - } as AccountBalance, - loading: false, - error: '' - }); - - render(SelectToken, { - ...mockProps, - tokenBalances - }); - - await waitFor(() => { - expect(screen.getByText('USDC')).toBeInTheDocument(); - }); - - await waitFor(() => { - expect(screen.getByText('Balance: 1.5')).toBeInTheDocument(); - }); - }); - }); + const customButton = screen.getByTestId("custom-mode-button"); + await user.click(customButton); + + expect( + screen.getByPlaceholderText("Enter token address (0x...)"), + ).toBeInTheDocument(); + }); + + it("clears state when switching from dropdown to custom mode", async () => { + const user = userEvent.setup(); + const mockBuilderNoToken = { + ...mockBuilder, + getTokenInfo: vi.fn().mockResolvedValue({ value: null }), + } as unknown as RaindexOrderBuilder; + + (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilderNoToken); + + render(SelectToken, { + ...mockProps, + }); + + const dropdownButton = screen.getByText("Select a token..."); + await user.click(dropdownButton); + + const firstToken = screen.getByText("Test Token 1"); + await user.click(firstToken); + + const customButton = screen.getByTestId("custom-mode-button"); + await user.click(customButton); + + const customInput = screen.getByPlaceholderText( + "Enter token address (0x...)", + ); + expect(customInput).toHaveValue(""); + + expect(mockBuilderNoToken.unsetSelectToken).toHaveBeenCalledWith("input"); + }); + + it("clears state when switching from custom to dropdown mode", async () => { + const user = userEvent.setup(); + render(SelectToken, mockProps); + + const customButton = screen.getByTestId("custom-mode-button"); + await user.click(customButton); + + const customInput = screen.getByPlaceholderText( + "Enter token address (0x...)", + ); + await user.type( + customInput, + "0x1234567890123456789012345678901234567890", + ); + + const dropdownButton = screen.getByTestId("dropdown-mode-button"); + await user.click(dropdownButton); + + expect(mockBuilder.unsetSelectToken).toHaveBeenCalledWith("input"); + }); + + it("handles token selection from dropdown", async () => { + const user = userEvent.setup(); + const mockBuilderNoToken = { + ...mockBuilder, + getTokenInfo: vi.fn().mockResolvedValue({ value: null }), + } as unknown as RaindexOrderBuilder; + + (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilderNoToken); + + render(SelectToken, { + ...mockProps, + }); + + const dropdownButton = screen.getByText("Select a token..."); + await user.click(dropdownButton); + + const secondToken = screen.getByText("Another Token"); + await user.click(secondToken); + + expect(mockBuilderNoToken.setSelectToken).toHaveBeenCalledWith( + "input", + "0x0987654321098765432109876543210987654321", + ); + }); + + it("displays selected token info when token is selected", async () => { + mockBuilder.getTokenInfo = vi.fn().mockResolvedValue({ + value: { + name: "Test Token 1", + symbol: "TEST1", + address: "0x1234567890123456789012345678901234567890", + decimals: 18, + }, + }); + + render(SelectToken, mockProps); + + await waitFor(() => { + expect(screen.getByText("Test Token 1")).toBeInTheDocument(); + }); + + expect( + screen.getByTestId(`select-token-success-${mockProps.token.key}`), + ).toBeInTheDocument(); + }); + }); + + describe("Balance Display", () => { + it("displays balance when token is selected and balance is provided", async () => { + mockBuilder.getTokenInfo = vi.fn().mockResolvedValue({ + value: { + name: "Test Token", + symbol: "TEST", + address: "0x1234567890123456789012345678901234567890", + decimals: 18, + key: "input", + }, + }); + + const tokenBalances = new Map(); + tokenBalances.set("input", { + value: { + balance: Float.parse("1").value, + formattedBalance: "1", + } as AccountBalance, + loading: false, + error: "", + }); + + render(SelectToken, { + ...mockProps, + tokenBalances, + }); + + await waitFor(() => { + expect(screen.getByText("Test Token")).toBeInTheDocument(); + }); + + await waitFor(() => { + expect(screen.getByText("Balance: 1")).toBeInTheDocument(); + }); + }); + + it("shows loading spinner when balance is loading", async () => { + mockBuilder.getTokenInfo = vi.fn().mockResolvedValue({ + value: { + name: "Test Token", + symbol: "TEST", + address: "0x1234567890123456789012345678901234567890", + decimals: 18, + key: "input", + }, + }); + + const tokenBalances = new Map(); + tokenBalances.set("input", { + value: { + balance: Float.parse("0").value, + formattedBalance: "0", + } as AccountBalance, + loading: true, + error: "", + }); + + render(SelectToken, { + ...mockProps, + tokenBalances, + }); + + await waitFor(() => { + expect(screen.getByText("Test Token")).toBeInTheDocument(); + }); + + // Check for spinner (we can't easily test the spinner component directly, so we test for its presence) + const tokenStatus = screen.getByTestId( + `select-token-success-${mockProps.token.key}`, + ); + expect(tokenStatus).toBeInTheDocument(); + }); + + it("shows error message when balance fetch fails", async () => { + mockBuilder.getTokenInfo = vi.fn().mockResolvedValue({ + value: { + name: "Test Token", + symbol: "TEST", + address: "0x1234567890123456789012345678901234567890", + decimals: 18, + key: "input", + }, + }); + + const tokenBalances = new Map(); + tokenBalances.set("input", { + value: { + balance: Float.parse("0").value, + formattedBalance: "0", + } as AccountBalance, + loading: false, + error: "Network error", + }); + + render(SelectToken, { + ...mockProps, + tokenBalances, + }); + + await waitFor(() => { + expect(screen.getByText("Test Token")).toBeInTheDocument(); + }); + + await waitFor(() => { + expect(screen.getByText("Network error")).toBeInTheDocument(); + }); + }); + + it("formats balance correctly with token decimals", async () => { + mockBuilder.getTokenInfo = vi.fn().mockResolvedValue({ + value: { + name: "USDC", + symbol: "USDC", + address: "0x1234567890123456789012345678901234567890", + decimals: 6, + key: "input", + }, + }); + + const tokenBalances = new Map(); + tokenBalances.set("input", { + value: { + balance: Float.parse("1.5").value, + formattedBalance: "1.5", + } as AccountBalance, + loading: false, + error: "", + }); + + render(SelectToken, { + ...mockProps, + tokenBalances, + }); + + await waitFor(() => { + expect(screen.getByText("USDC")).toBeInTheDocument(); + }); + + await waitFor(() => { + expect(screen.getByText("Balance: 1.5")).toBeInTheDocument(); + }); + }); + }); }); diff --git a/packages/ui-components/src/__tests__/ShareChoicesButton.test.ts b/packages/ui-components/src/__tests__/ShareChoicesButton.test.ts index a8ca9d7fe5..1eb360e4e1 100644 --- a/packages/ui-components/src/__tests__/ShareChoicesButton.test.ts +++ b/packages/ui-components/src/__tests__/ShareChoicesButton.test.ts @@ -1,52 +1,58 @@ -import { render, fireEvent, screen } from '@testing-library/svelte'; -import { describe, it, expect, vi } from 'vitest'; -import ShareChoicesButton from '../lib/components/deployment/ShareChoicesButton.svelte'; - -describe('ShareChoicesButton', () => { - const mockHandleShareChoices = vi.fn(); - - it('calls handleShareChoices when clicked', async () => { - render(ShareChoicesButton, { - props: { - handleShareChoices: mockHandleShareChoices - } - }); - - await fireEvent.click(screen.getByTestId('review-choices-button')); - expect(mockHandleShareChoices).toHaveBeenCalledTimes(1); - }); - - it('shows and hides copied message when clicked', async () => { - render(ShareChoicesButton, { - props: { - handleShareChoices: mockHandleShareChoices - } - }); - - // Message should not be visible initially - expect(screen.queryByText('Shareable URL copied to clipboard')).not.toBeInTheDocument(); - - // Click the button - await fireEvent.click(screen.getByTestId('review-choices-button')); - - // Message should be visible - expect(screen.getByText('Shareable URL copied to clipboard')).toBeInTheDocument(); - - // Wait for 5 seconds - await new Promise((resolve) => setTimeout(resolve, 5000)); - - // Message should be gone - expect(screen.queryByText('Shareable URL copied to clipboard')).not.toBeInTheDocument(); - }); - - it('renders the share button correctly', () => { - render(ShareChoicesButton, { - props: { - handleShareChoices: mockHandleShareChoices - } - }); - - expect(screen.getByText('Share these choices')).toBeInTheDocument(); - expect(screen.getByTestId('review-choices-button')).toBeInTheDocument(); - }); +import { render, fireEvent, screen } from "@testing-library/svelte"; +import { describe, it, expect, vi } from "vitest"; +import ShareChoicesButton from "../lib/components/deployment/ShareChoicesButton.svelte"; + +describe("ShareChoicesButton", () => { + const mockHandleShareChoices = vi.fn(); + + it("calls handleShareChoices when clicked", async () => { + render(ShareChoicesButton, { + props: { + handleShareChoices: mockHandleShareChoices, + }, + }); + + await fireEvent.click(screen.getByTestId("review-choices-button")); + expect(mockHandleShareChoices).toHaveBeenCalledTimes(1); + }); + + it("shows and hides copied message when clicked", async () => { + render(ShareChoicesButton, { + props: { + handleShareChoices: mockHandleShareChoices, + }, + }); + + // Message should not be visible initially + expect( + screen.queryByText("Shareable URL copied to clipboard"), + ).not.toBeInTheDocument(); + + // Click the button + await fireEvent.click(screen.getByTestId("review-choices-button")); + + // Message should be visible + expect( + screen.getByText("Shareable URL copied to clipboard"), + ).toBeInTheDocument(); + + // Wait for 5 seconds + await new Promise((resolve) => setTimeout(resolve, 5000)); + + // Message should be gone + expect( + screen.queryByText("Shareable URL copied to clipboard"), + ).not.toBeInTheDocument(); + }); + + it("renders the share button correctly", () => { + render(ShareChoicesButton, { + props: { + handleShareChoices: mockHandleShareChoices, + }, + }); + + expect(screen.getByText("Share these choices")).toBeInTheDocument(); + expect(screen.getByTestId("review-choices-button")).toBeInTheDocument(); + }); }); diff --git a/packages/ui-components/src/__tests__/TableTimeFilters.test.ts b/packages/ui-components/src/__tests__/TableTimeFilters.test.ts index 09b1a9d10e..59c8f666e9 100644 --- a/packages/ui-components/src/__tests__/TableTimeFilters.test.ts +++ b/packages/ui-components/src/__tests__/TableTimeFilters.test.ts @@ -1,59 +1,59 @@ -import { render, fireEvent, screen } from '@testing-library/svelte'; -import { get, writable } from 'svelte/store'; -import { test, expect } from 'vitest'; -import TableTimeFiltersTest from './TableTimeFilters.test.svelte'; +import { render, fireEvent, screen } from "@testing-library/svelte"; +import { get, writable } from "svelte/store"; +import { test, expect } from "vitest"; +import TableTimeFiltersTest from "./TableTimeFilters.test.svelte"; const TIME_DELTA_24_HOURS = 60 * 60 * 24; const TIME_DELTA_48_HOURS = TIME_DELTA_24_HOURS * 2; -test('initial start/end time difference is set to all time', async () => { - const startTimeStore = writable(); - const endTimeStore = writable(); +test("initial start/end time difference is set to all time", async () => { + const startTimeStore = writable(); + const endTimeStore = writable(); - render(TableTimeFiltersTest, { startTimeStore, endTimeStore }); + render(TableTimeFiltersTest, { startTimeStore, endTimeStore }); - const twentyFourHoursButton = screen.getByText('24 Hours'); - expect(twentyFourHoursButton).toBeEnabled(); - expect(get(endTimeStore)).toBe(undefined); - expect(get(startTimeStore)).toBe(undefined); + const twentyFourHoursButton = screen.getByText("24 Hours"); + expect(twentyFourHoursButton).toBeEnabled(); + expect(get(endTimeStore)).toBe(undefined); + expect(get(startTimeStore)).toBe(undefined); }); -test('clicking All Time button updates timeDelta', async () => { - const startTimeStore = writable(0); - const endTimeStore = writable(0); +test("clicking All Time button updates timeDelta", async () => { + const startTimeStore = writable(0); + const endTimeStore = writable(0); - render(TableTimeFiltersTest, { startTimeStore, endTimeStore }); + render(TableTimeFiltersTest, { startTimeStore, endTimeStore }); - const allTimeButton = screen.getByText('All Time'); - await fireEvent.click(allTimeButton); + const allTimeButton = screen.getByText("All Time"); + await fireEvent.click(allTimeButton); - expect(allTimeButton).toBeDisabled(); - expect(get(startTimeStore)).toBe(undefined); - expect(get(endTimeStore)).toBe(undefined); + expect(allTimeButton).toBeDisabled(); + expect(get(startTimeStore)).toBe(undefined); + expect(get(endTimeStore)).toBe(undefined); }); -test('clicking 48 Hours button updates start/end timestamp', async () => { - const startTimeStore = writable(0); - const endTimeStore = writable(0); +test("clicking 48 Hours button updates start/end timestamp", async () => { + const startTimeStore = writable(0); + const endTimeStore = writable(0); - render(TableTimeFiltersTest, { startTimeStore, endTimeStore }); + render(TableTimeFiltersTest, { startTimeStore, endTimeStore }); - const fortyEightHoursButton = screen.getByText('48 Hours'); - await fireEvent.click(fortyEightHoursButton); + const fortyEightHoursButton = screen.getByText("48 Hours"); + await fireEvent.click(fortyEightHoursButton); - expect(fortyEightHoursButton).toBeDisabled(); - expect(get(endTimeStore) - get(startTimeStore)).toBe(TIME_DELTA_48_HOURS); + expect(fortyEightHoursButton).toBeDisabled(); + expect(get(endTimeStore) - get(startTimeStore)).toBe(TIME_DELTA_48_HOURS); }); -test('clicking 24 Hours button updates start/end timestamp', async () => { - const startTimeStore = writable(0); - const endTimeStore = writable(0); +test("clicking 24 Hours button updates start/end timestamp", async () => { + const startTimeStore = writable(0); + const endTimeStore = writable(0); - render(TableTimeFiltersTest, { startTimeStore, endTimeStore }); + render(TableTimeFiltersTest, { startTimeStore, endTimeStore }); - const twentyFourHoursButton = screen.getByText('24 Hours'); - await fireEvent.click(twentyFourHoursButton); + const twentyFourHoursButton = screen.getByText("24 Hours"); + await fireEvent.click(twentyFourHoursButton); - expect(twentyFourHoursButton).toBeDisabled(); - expect(get(endTimeStore) - get(startTimeStore)).toBe(TIME_DELTA_24_HOURS); + expect(twentyFourHoursButton).toBeDisabled(); + expect(get(endTimeStore) - get(startTimeStore)).toBe(TIME_DELTA_24_HOURS); }); diff --git a/packages/ui-components/src/__tests__/TanstackAppTable.test.ts b/packages/ui-components/src/__tests__/TanstackAppTable.test.ts index 3d798b5112..b8964489d2 100644 --- a/packages/ui-components/src/__tests__/TanstackAppTable.test.ts +++ b/packages/ui-components/src/__tests__/TanstackAppTable.test.ts @@ -1,223 +1,255 @@ -import { render, screen, waitFor } from '@testing-library/svelte'; -import { test, expect } from 'vitest'; -import TanstackAppTableTest from './TanstackAppTable.test.svelte'; -import userEvent from '@testing-library/user-event'; -import { writable, get } from 'svelte/store'; -import type { CreateInfiniteQueryResult, InfiniteData } from '@tanstack/svelte-query'; - -vi.mock('@tanstack/svelte-query', () => ({ - useQueryClient: () => ({}) +import { render, screen, waitFor } from "@testing-library/svelte"; +import { test, expect } from "vitest"; +import TanstackAppTableTest from "./TanstackAppTable.test.svelte"; +import userEvent from "@testing-library/user-event"; +import { writable, get } from "svelte/store"; +import type { + CreateInfiniteQueryResult, + InfiniteData, +} from "@tanstack/svelte-query"; + +vi.mock("@tanstack/svelte-query", () => ({ + useQueryClient: () => ({}), })); const mockInvalidateTanstackQueries = vi.fn(); -vi.mock('$lib/queries/queryClient', () => ({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - invalidateTanstackQueries: (queryClient: any, queryKey: string[]) => - mockInvalidateTanstackQueries(queryClient, queryKey) +vi.mock("$lib/queries/queryClient", () => ({ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + invalidateTanstackQueries: (queryClient: any, queryKey: string[]) => + mockInvalidateTanstackQueries(queryClient, queryKey), })); // Helper function to create base pages -const createPages = (pageData: unknown[] = ['page0']) => - writable({ - pages: [pageData], - pageParams: [0] - }); +const createPages = (pageData: unknown[] = ["page0"]) => + writable({ + pages: [pageData], + pageParams: [0], + }); // Helper function to create base mock query -const createMockQuery = (pages: ReturnType, overrides = {}) => { - return writable({ - data: get(pages), - isLoading: false, - isFetching: false, - isFetchingNextPage: false, - hasNextPage: true, - status: 'success' as const, - fetchStatus: 'idle' as const, - fetchNextPage: vi.fn(), - ...overrides - }); +const createMockQuery = ( + pages: ReturnType, + overrides = {}, +) => { + return writable({ + data: get(pages), + isLoading: false, + isFetching: false, + isFetchingNextPage: false, + hasNextPage: true, + status: "success" as const, + fetchStatus: "idle" as const, + fetchNextPage: vi.fn(), + ...overrides, + }); }; type VirtualizationConfig = { - enabled?: boolean; - estimatedRowHeight?: number; - overscan?: number; + enabled?: boolean; + estimatedRowHeight?: number; + overscan?: number; }; type TableRenderOptions = { - virtualization?: VirtualizationConfig; + virtualization?: VirtualizationConfig; }; const renderTable = ( - query: ReturnType, - options: TableRenderOptions = {} + query: ReturnType, + options: TableRenderOptions = {}, ) => { - return render(TanstackAppTableTest, { - query: query as unknown as CreateInfiniteQueryResult, Error>, - emptyMessage: 'No rows', - title: 'Test Table', - head: 'Test head', - queryKey: 'test', - ...options - }); + return render(TanstackAppTableTest, { + query: query as unknown as CreateInfiniteQueryResult< + InfiniteData, + Error + >, + emptyMessage: "No rows", + title: "Test Table", + head: "Test head", + queryKey: "test", + ...options, + }); }; -test('shows head and title', async () => { - const pages = createPages(); - const mockQuery = createMockQuery(pages); - renderTable(mockQuery); +test("shows head and title", async () => { + const pages = createPages(); + const mockQuery = createMockQuery(pages); + renderTable(mockQuery); - await waitFor(() => expect(screen.getByTestId('head')).toHaveTextContent('Test head')); - expect(screen.getByTestId('title')).toHaveTextContent('Test Table'); + await waitFor(() => + expect(screen.getByTestId("head")).toHaveTextContent("Test head"), + ); + expect(screen.getByTestId("title")).toHaveTextContent("Test Table"); }); -test('renders rows', async () => { - const pages = createPages(); - const mockQuery = createMockQuery(pages); - renderTable(mockQuery); +test("renders rows", async () => { + const pages = createPages(); + const mockQuery = createMockQuery(pages); + renderTable(mockQuery); - await waitFor(() => expect(screen.getByTestId('bodyRow')).toHaveTextContent('page0')); + await waitFor(() => + expect(screen.getByTestId("bodyRow")).toHaveTextContent("page0"), + ); }); -test('shows empty message', async () => { - const pages = createPages([]); - const mockQuery = createMockQuery(pages); - renderTable(mockQuery); +test("shows empty message", async () => { + const pages = createPages([]); + const mockQuery = createMockQuery(pages); + renderTable(mockQuery); - await waitFor(() => expect(screen.getByTestId('emptyMessage')).toHaveTextContent('No rows')); + await waitFor(() => + expect(screen.getByTestId("emptyMessage")).toHaveTextContent("No rows"), + ); }); -test('renders rows when first page is empty but later pages have data', async () => { - const pages = writable({ - pages: [[], ['page1']], - pageParams: [0, 1] - }); - const mockQuery = createMockQuery(pages); - renderTable(mockQuery); - - await waitFor(() => expect(screen.getByTestId('bodyRow')).toHaveTextContent('page1')); - expect(screen.queryByTestId('emptyMessage')).not.toBeInTheDocument(); +test("renders rows when first page is empty but later pages have data", async () => { + const pages = writable({ + pages: [[], ["page1"]], + pageParams: [0, 1], + }); + const mockQuery = createMockQuery(pages); + renderTable(mockQuery); + + await waitFor(() => + expect(screen.getByTestId("bodyRow")).toHaveTextContent("page1"), + ); + expect(screen.queryByTestId("emptyMessage")).not.toBeInTheDocument(); }); -test('loads more rows', async () => { - const pages = createPages(); - const mockQuery = createMockQuery(pages, { - fetchNextPage: async () => { - mockQuery.update((q) => ({ ...q, isFetchingNextPage: true })); - await new Promise((resolve) => setTimeout(resolve, 0)); - pages.update((data) => ({ - pages: [...data.pages, [`page${data.pages.length}`]], - pageParams: [...data.pageParams, data.pageParams.length] - })); - mockQuery.update((q) => ({ - ...q, - data: get(pages), - isFetchingNextPage: false - })); - } - }); - renderTable(mockQuery); - - await waitFor(() => expect(screen.getByTestId('bodyRow')).toHaveTextContent('page0')); - - const loadMoreButton = screen.getByTestId('loadMoreButton'); - await userEvent.click(loadMoreButton); - - await waitFor(() => { - expect(screen.getAllByTestId('bodyRow')).toHaveLength(2); - }); - - let rows = screen.getAllByTestId('bodyRow'); - expect(rows[0]).toHaveTextContent('page0'); - expect(rows[1]).toHaveTextContent('page1'); - - await userEvent.click(loadMoreButton); - - await waitFor(() => { - expect(screen.getAllByTestId('bodyRow')).toHaveLength(3); - }); - - rows = screen.getAllByTestId('bodyRow'); - expect(rows[0]).toHaveTextContent('page0'); - expect(rows[1]).toHaveTextContent('page1'); - expect(rows[2]).toHaveTextContent('page2'); +test("loads more rows", async () => { + const pages = createPages(); + const mockQuery = createMockQuery(pages, { + fetchNextPage: async () => { + mockQuery.update((q) => ({ ...q, isFetchingNextPage: true })); + await new Promise((resolve) => setTimeout(resolve, 0)); + pages.update((data) => ({ + pages: [...data.pages, [`page${data.pages.length}`]], + pageParams: [...data.pageParams, data.pageParams.length], + })); + mockQuery.update((q) => ({ + ...q, + data: get(pages), + isFetchingNextPage: false, + })); + }, + }); + renderTable(mockQuery); + + await waitFor(() => + expect(screen.getByTestId("bodyRow")).toHaveTextContent("page0"), + ); + + const loadMoreButton = screen.getByTestId("loadMoreButton"); + await userEvent.click(loadMoreButton); + + await waitFor(() => { + expect(screen.getAllByTestId("bodyRow")).toHaveLength(2); + }); + + let rows = screen.getAllByTestId("bodyRow"); + expect(rows[0]).toHaveTextContent("page0"); + expect(rows[1]).toHaveTextContent("page1"); + + await userEvent.click(loadMoreButton); + + await waitFor(() => { + expect(screen.getAllByTestId("bodyRow")).toHaveLength(3); + }); + + rows = screen.getAllByTestId("bodyRow"); + expect(rows[0]).toHaveTextContent("page0"); + expect(rows[1]).toHaveTextContent("page1"); + expect(rows[2]).toHaveTextContent("page2"); }); -test('load more button message changes when loading', async () => { - const pages = createPages(); - const mockQuery = createMockQuery(pages, { - fetchNextPage: async () => { - mockQuery.update((q) => ({ ...q, isFetchingNextPage: true })); - await new Promise((resolve) => setTimeout(resolve, 100)); - mockQuery.update((q) => ({ ...q, isFetchingNextPage: false })); - } - }); - renderTable(mockQuery); - - expect(await screen.findByTestId('loadMoreButton')).toHaveTextContent('Load More'); - - const loadMoreButton = screen.getByTestId('loadMoreButton'); - await userEvent.click(loadMoreButton); - - expect(await screen.findByTestId('loadMoreButton')).toHaveTextContent('Loading more...'); - - await waitFor(() => { - expect(screen.getByTestId('loadMoreButton')).toHaveTextContent('Load More'); - }); +test("load more button message changes when loading", async () => { + const pages = createPages(); + const mockQuery = createMockQuery(pages, { + fetchNextPage: async () => { + mockQuery.update((q) => ({ ...q, isFetchingNextPage: true })); + await new Promise((resolve) => setTimeout(resolve, 100)); + mockQuery.update((q) => ({ ...q, isFetchingNextPage: false })); + }, + }); + renderTable(mockQuery); + + expect(await screen.findByTestId("loadMoreButton")).toHaveTextContent( + "Load More", + ); + + const loadMoreButton = screen.getByTestId("loadMoreButton"); + await userEvent.click(loadMoreButton); + + expect(await screen.findByTestId("loadMoreButton")).toHaveTextContent( + "Loading more...", + ); + + await waitFor(() => { + expect(screen.getByTestId("loadMoreButton")).toHaveTextContent("Load More"); + }); }); -test('shows refresh icon', async () => { - const pages = createPages(); - const mockQuery = createMockQuery(pages); - renderTable(mockQuery); +test("shows refresh icon", async () => { + const pages = createPages(); + const mockQuery = createMockQuery(pages); + renderTable(mockQuery); - await waitFor(() => expect(screen.getByTestId('refreshButton')).toBeInTheDocument()); + await waitFor(() => + expect(screen.getByTestId("refreshButton")).toBeInTheDocument(), + ); }); -test('invalidates queries when refresh button is clicked', async () => { - const mockRefetch = vi.fn(); - const mockQuery = createMockQuery(createPages(), { - status: 'success', - fetchStatus: 'idle', - isLoading: false, - isFetching: false, - refetch: mockRefetch - }); - renderTable(mockQuery); - - const refreshButton = screen.getByTestId('refreshButton'); - await userEvent.click(refreshButton); - - expect(mockInvalidateTanstackQueries).toHaveBeenCalledWith(expect.anything(), ['test']); +test("invalidates queries when refresh button is clicked", async () => { + const mockRefetch = vi.fn(); + const mockQuery = createMockQuery(createPages(), { + status: "success", + fetchStatus: "idle", + isLoading: false, + isFetching: false, + refetch: mockRefetch, + }); + renderTable(mockQuery); + + const refreshButton = screen.getByTestId("refreshButton"); + await userEvent.click(refreshButton); + + expect(mockInvalidateTanstackQueries).toHaveBeenCalledWith( + expect.anything(), + ["test"], + ); }); -test('virtualizes rows based on viewport height', async () => { - const rows = Array.from({ length: 20 }, (_, i) => `row-${i}`); - const pages = createPages(rows); - const mockQuery = createMockQuery(pages); - const innerHeightSpy = vi.spyOn(window, 'innerHeight', 'get').mockReturnValue(60); - - renderTable(mockQuery, { virtualization: { overscan: 0, estimatedRowHeight: 20 } }); - - await waitFor(() => { - const renderedRows = screen.getAllByTestId('bodyRow'); - expect(renderedRows.length).toBeLessThan(rows.length); - expect(renderedRows.length).toBeGreaterThan(0); - }); - - expect(screen.getAllByTestId('bodyRow')[0]).toHaveTextContent('row-0'); - innerHeightSpy.mockRestore(); +test("virtualizes rows based on viewport height", async () => { + const rows = Array.from({ length: 20 }, (_, i) => `row-${i}`); + const pages = createPages(rows); + const mockQuery = createMockQuery(pages); + const innerHeightSpy = vi + .spyOn(window, "innerHeight", "get") + .mockReturnValue(60); + + renderTable(mockQuery, { + virtualization: { overscan: 0, estimatedRowHeight: 20 }, + }); + + await waitFor(() => { + const renderedRows = screen.getAllByTestId("bodyRow"); + expect(renderedRows.length).toBeLessThan(rows.length); + expect(renderedRows.length).toBeGreaterThan(0); + }); + + expect(screen.getAllByTestId("bodyRow")[0]).toHaveTextContent("row-0"); + innerHeightSpy.mockRestore(); }); -test('renders all rows when virtualization is disabled', async () => { - const rows = Array.from({ length: 10 }, (_, i) => `row-${i}`); - const pages = createPages(rows); - const mockQuery = createMockQuery(pages); +test("renders all rows when virtualization is disabled", async () => { + const rows = Array.from({ length: 10 }, (_, i) => `row-${i}`); + const pages = createPages(rows); + const mockQuery = createMockQuery(pages); - renderTable(mockQuery, { virtualization: { enabled: false } }); + renderTable(mockQuery, { virtualization: { enabled: false } }); - await waitFor(() => { - expect(screen.getAllByTestId('bodyRow')).toHaveLength(rows.length); - }); + await waitFor(() => { + expect(screen.getAllByTestId("bodyRow")).toHaveLength(rows.length); + }); }); diff --git a/packages/ui-components/src/__tests__/TanstackLightweightChartLine.test.ts b/packages/ui-components/src/__tests__/TanstackLightweightChartLine.test.ts index 75a4104b0c..cd5a4b4abf 100644 --- a/packages/ui-components/src/__tests__/TanstackLightweightChartLine.test.ts +++ b/packages/ui-components/src/__tests__/TanstackLightweightChartLine.test.ts @@ -1,79 +1,81 @@ -import { render, waitFor } from '@testing-library/svelte'; -import { test, expect, vi } from 'vitest'; -import TanstackLightweightChartLine from '../lib/components/charts/TanstackLightweightChartLine.svelte'; -import { props } from '../lib/__mocks__/MockComponent'; -import { createResolvableQuery } from '../lib/__mocks__/queries'; -import type { UTCTimestamp } from 'lightweight-charts'; -import { get, readable } from 'svelte/store'; +import { render, waitFor } from "@testing-library/svelte"; +import { test, expect, vi } from "vitest"; +import TanstackLightweightChartLine from "../lib/components/charts/TanstackLightweightChartLine.svelte"; +import { props } from "../lib/__mocks__/MockComponent"; +import { createResolvableQuery } from "../lib/__mocks__/queries"; +import type { UTCTimestamp } from "lightweight-charts"; +import { get, readable } from "svelte/store"; -vi.mock('../lib/components/charts/LightweightChart.svelte', async () => { - const MockLightweightChart = (await import('../lib/__mocks__/MockComponent.svelte')).default; - return { default: MockLightweightChart }; +vi.mock("../lib/components/charts/LightweightChart.svelte", async () => { + const MockLightweightChart = ( + await import("../lib/__mocks__/MockComponent.svelte") + ).default; + return { default: MockLightweightChart }; }); type MockData = { - value: number; - time: number; + value: number; + time: number; }; -test('renders the loading state correctly', async () => { - const mockData: MockData[] = [ - { value: 10, time: 1629899200 }, - { value: 20, time: 1629899300 } - ]; +test("renders the loading state correctly", async () => { + const mockData: MockData[] = [ + { value: 10, time: 1629899200 }, + { value: 20, time: 1629899300 }, + ]; - const { query, resolve } = createResolvableQuery(() => mockData); + const { query, resolve } = createResolvableQuery(() => mockData); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { component: _component } = render(TanstackLightweightChartLine, { - props: { - query, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - timeTransform: (d: any) => d.time as UTCTimestamp, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - valueTransform: (d: any) => d.value, - lightweightChartsTheme: readable({ test: 'test' }) - } - }); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { component: _component } = render(TanstackLightweightChartLine, { + props: { + query, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + timeTransform: (d: any) => d.time as UTCTimestamp, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + valueTransform: (d: any) => d.value, + lightweightChartsTheme: readable({ test: "test" }), + }, + }); - await waitFor(() => { - const _props = get(props) as (typeof _component)['$$props']; - expect(_props.loading).toBe(true); - }); + await waitFor(() => { + const _props = get(props) as (typeof _component)["$$props"]; + expect(_props.loading).toBe(true); + }); - await resolve(); + await resolve(); - await waitFor(() => { - const _props = get(props) as (typeof _component)['$$props']; - expect(_props.loading).toBe(false); - expect(_props.data).toEqual(mockData); - }); + await waitFor(() => { + const _props = get(props) as (typeof _component)["$$props"]; + expect(_props.loading).toBe(false); + expect(_props.data).toEqual(mockData); + }); }); -test('that a line series is added to the chart', async () => { - const mockData: MockData[] = [{ value: 20, time: 1629899300 }]; +test("that a line series is added to the chart", async () => { + const mockData: MockData[] = [{ value: 20, time: 1629899300 }]; - const { query, resolve } = createResolvableQuery(() => mockData); + const { query, resolve } = createResolvableQuery(() => mockData); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { component: _component } = render(TanstackLightweightChartLine, { - props: { - query, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - timeTransform: (d: any) => d.time as UTCTimestamp, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - valueTransform: (d: any) => d.value, - lightweightChartsTheme: readable({ test: 'test' }) - } - }); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { component: _component } = render(TanstackLightweightChartLine, { + props: { + query, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + timeTransform: (d: any) => d.time as UTCTimestamp, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + valueTransform: (d: any) => d.value, + lightweightChartsTheme: readable({ test: "test" }), + }, + }); - await resolve(); + await resolve(); - await waitFor(() => { - const _props = get(props) as (typeof _component)['$$props']; - // Assert that the createSeries function matches the expected implementation - expect(_props.createSeries.toString()).toEqual( - 'chart => chart.addLineSeries({ lineWidth: 1 })' - ); - }); + await waitFor(() => { + const _props = get(props) as (typeof _component)["$$props"]; + // Assert that the createSeries function matches the expected implementation + expect(_props.createSeries.toString()).toEqual( + "chart => chart.addLineSeries({ lineWidth: 1 })", + ); + }); }); diff --git a/packages/ui-components/src/__tests__/TanstackOrderQuote.test.ts b/packages/ui-components/src/__tests__/TanstackOrderQuote.test.ts index 897c2d214f..b697029e3c 100644 --- a/packages/ui-components/src/__tests__/TanstackOrderQuote.test.ts +++ b/packages/ui-components/src/__tests__/TanstackOrderQuote.test.ts @@ -1,363 +1,377 @@ -import { fireEvent, render, screen, waitFor } from '@testing-library/svelte'; -import { describe, it, vi, type Mock } from 'vitest'; -import { QueryClient } from '@tanstack/svelte-query'; -import TanstackOrderQuote from '../lib/components/detail/TanstackOrderQuote.svelte'; -import { expect } from '../lib/test/matchers'; -import type { RaindexOrder } from '@rainlanguage/raindex'; -import { useToasts } from '$lib/providers/toasts/useToasts'; -import { writable } from 'svelte/store'; -import { invalidateTanstackQueries } from '$lib/queries/queryClient'; - -vi.mock('@rainlanguage/raindex', () => ({ - getOrderQuote: vi.fn() +import { fireEvent, render, screen, waitFor } from "@testing-library/svelte"; +import { describe, it, vi, type Mock } from "vitest"; +import { QueryClient } from "@tanstack/svelte-query"; +import TanstackOrderQuote from "../lib/components/detail/TanstackOrderQuote.svelte"; +import { expect } from "../lib/test/matchers"; +import type { RaindexOrder } from "@rainlanguage/raindex"; +import { useToasts } from "$lib/providers/toasts/useToasts"; +import { writable } from "svelte/store"; +import { invalidateTanstackQueries } from "$lib/queries/queryClient"; + +vi.mock("@rainlanguage/raindex", () => ({ + getOrderQuote: vi.fn(), })); -vi.mock('$lib/providers/toasts/useToasts', () => ({ - useToasts: vi.fn() +vi.mock("$lib/providers/toasts/useToasts", () => ({ + useToasts: vi.fn(), })); -vi.mock('$lib/queries/queryClient', async (importOriginal) => ({ - ...((await importOriginal()) as object), - invalidateTanstackQueries: vi.fn() +vi.mock("$lib/queries/queryClient", async (importOriginal) => ({ + ...((await importOriginal()) as object), + invalidateTanstackQueries: vi.fn(), })); const mockErrToast = vi.fn(); const mockAddToast = vi.fn(); let clipboardWriteText: ReturnType; -describe('TanstackOrderQuote component', () => { - const mockOrder: RaindexOrder = { - id: '1', - getQuotes: vi.fn() - } as unknown as RaindexOrder; - - beforeEach(() => { - vi.clearAllMocks(); - vi.resetAllMocks(); - mockErrToast.mockReset(); - mockAddToast.mockReset(); - clipboardWriteText = vi.fn().mockResolvedValue(undefined); - Object.defineProperty(window.navigator, 'clipboard', { - value: { writeText: clipboardWriteText }, - configurable: true - }); - (useToasts as Mock).mockReturnValue({ - toasts: writable([]), - errToast: mockErrToast, - addToast: mockAddToast, - removeToast: vi.fn() - }); - }); - it('displays order quote data when query is successful', async () => { - (mockOrder.getQuotes as Mock).mockResolvedValueOnce({ - value: [ - { - success: true, - block_number: '0x123', - pair: { pairName: 'ETH/USDT', inputIndex: 0, outputIndex: 1 }, - data: { - formattedMaxOutput: '1.550122181502135692', - formattedRatio: '6.563567234157974775' - }, - error: undefined - } - ] - }); - - const queryClient = new QueryClient(); - - render(TanstackOrderQuote, { - props: { - order: mockOrder, - handleQuoteDebugModal: vi.fn() - }, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - const orderQuoteComponent = screen.getByTestId('bodyRow'); - - expect(orderQuoteComponent).toHaveTextContent('ETH/USDT'); - expect(orderQuoteComponent).toHaveTextContent('1.550122181502135692'); - expect(orderQuoteComponent).toHaveTextContent('6.563567234157974775'); - }); - }); - - it('refreshes the quote when the refresh icon is clicked', async () => { - (mockOrder.getQuotes as Mock).mockResolvedValueOnce({ - value: [ - { - success: true, - block_number: '0x123', - pair: { pairName: 'ETH/USDT', inputIndex: 0, outputIndex: 1 }, - data: { formattedMaxOutput: '1.550122181502135692' }, - error: undefined - }, - { - success: true, - block_number: '0x123', - pair: { pairName: 'BTC/USDT', inputIndex: 0, outputIndex: 1 }, - data: { formattedMaxOutput: '6.123350635480882605' }, - error: undefined - } - ] - }); - // Setup mock for the second data load (after refresh) - (mockOrder.getQuotes as Mock).mockResolvedValueOnce({ - value: [ - { - success: true, - block_number: '0x123', - pair: { pairName: 'ETH/USDT', inputIndex: 0, outputIndex: 1 }, - data: { - formattedMaxOutput: '5.945438972656012126', - formattedRatio: '6.305004957644166012' - }, - error: undefined - }, - { - success: true, - block_number: '0x123', - pair: { pairName: 'BTC/USDT', inputIndex: 0, outputIndex: 1 }, - data: { - formattedMaxOutput: '6.066479884955967059', - formattedRatio: '6.485589855485802559' - }, - error: undefined - } - ] - }); - - // Mock the invalidateTanstackQueries function to ensure it works correctly - (invalidateTanstackQueries as Mock).mockImplementation((queryClient, queryKey) => { - // This will trigger a refetch which will use the second mock - queryClient.invalidateQueries({ queryKey }); - return Promise.resolve(); - }); - - const queryClient = new QueryClient(); - - render(TanstackOrderQuote, { - props: { - order: mockOrder, - handleQuoteDebugModal: vi.fn() - }, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - const orderQuoteRows = screen.getAllByTestId('bodyRow'); - - // Check ETH/USDT row - expect(orderQuoteRows[0]).toHaveTextContent('1.550122181502135692'); - - // Check BTC/USDT row - expect(orderQuoteRows[1]).toHaveTextContent('6.123350635480882605'); - }); - - const refreshButton = screen.getByTestId('refresh-button'); - fireEvent.click(refreshButton); - - await waitFor(() => { - const orderQuoteRows = screen.getAllByTestId('bodyRow'); - - // Check ETH/USD row - expect(orderQuoteRows[0]).toHaveTextContent('ETH/USD'); - expect(orderQuoteRows[0]).toHaveTextContent('5.945438972656012126'); - expect(orderQuoteRows[0]).toHaveTextContent('6.305004957644166012'); - - // Check BTC/USDT row - expect(orderQuoteRows[1]).toHaveTextContent('BTC/USDT'); - expect(orderQuoteRows[1]).toHaveTextContent('6.066479884955967059'); - expect(orderQuoteRows[1]).toHaveTextContent('6.485589855485802559'); - }); - }); - - it('displays error message when query fails', async () => { - (mockOrder.getQuotes as Mock).mockResolvedValueOnce({ - value: [ - { - success: false, - block_number: '0x123', - pair: { pairName: 'ETH/USDT', inputIndex: 0, outputIndex: 1 }, - data: undefined, - error: 'Network error' - } - ] - }); - - const queryClient = new QueryClient(); - - render(TanstackOrderQuote, { - props: { - order: mockOrder, - handleQuoteDebugModal: vi.fn() - }, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - const errorNodes = screen.queryAllByText(/Network error/); - expect(errorNodes.length).toBeGreaterThan(0); - }); - }); - - it('displays zero for price when io ratio is zero', async () => { - (mockOrder.getQuotes as Mock).mockResolvedValueOnce({ - value: [ - { - success: true, - block_number: '0x123', - pair: { pairName: 'ETH/USDT', inputIndex: 0, outputIndex: 1 }, - data: { - formattedMaxOutput: '1.550122181502135692', - formattedRatio: '0', - formattedInverseRatio: '0' - }, - error: undefined - } - ] - }); - - const queryClient = new QueryClient(); - - render(TanstackOrderQuote, { - props: { - order: mockOrder, - handleQuoteDebugModal: vi.fn() - }, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - const orderQuoteComponent = screen.getByTestId('bodyRow'); - - expect(orderQuoteComponent).toHaveTextContent('ETH/USDT'); - expect(orderQuoteComponent).toHaveTextContent('1.550122181502135692'); // maxOutput - expect(orderQuoteComponent).toHaveTextContent('0'); // ratio - expect(orderQuoteComponent).toHaveTextContent('(0)'); // inverse price - }); - }); - - it('triggers a toast when the quote fails to refresh', async () => { - (invalidateTanstackQueries as Mock).mockRejectedValueOnce(new Error('Failed to refresh')); - (mockOrder.getQuotes as Mock).mockResolvedValueOnce({ - value: [ - { - success: true, - block_number: '0x123', - pair: { pairName: 'ETH/USDT', inputIndex: 0, outputIndex: 1 }, - data: { maxOutput: '0x158323e942e36d8c', ratio: '0x5b16799fcb6114f7' }, - error: undefined - }, - { - success: true, - block_number: '0x123', - pair: { pairName: 'BTC/USDT', inputIndex: 0, outputIndex: 1 }, - data: { maxOutput: '0x54fa82f5c7001dad', ratio: '0x53e0089714d06709' }, - error: undefined - } - ] - }); - const queryClient = new QueryClient(); - - render(TanstackOrderQuote, { - props: { - order: mockOrder, - handleQuoteDebugModal: vi.fn() - }, - context: new Map([['$$_queryClient', queryClient]]) - }); - - const refreshButton = screen.getByTestId('refresh-button'); - fireEvent.click(refreshButton); - - await waitFor(() => { - expect(mockErrToast).toHaveBeenCalledWith('Failed to refresh'); - }); - }); - - it('copies the quote error to the clipboard and notifies the user', async () => { - (mockOrder.getQuotes as Mock).mockResolvedValueOnce({ - value: [ - { - success: false, - block_number: '0x123', - pair: { pairName: 'ETH/USDT', inputIndex: 0, outputIndex: 1 }, - data: undefined, - error: 'Failed to calculate quote' - } - ] - }); - - const queryClient = new QueryClient(); - - render(TanstackOrderQuote, { - props: { - order: mockOrder, - handleQuoteDebugModal: vi.fn() - }, - context: new Map([['$$_queryClient', queryClient]]) - }); - - const copyButton = await screen.findByRole('button', { name: 'Copy quote error' }); - await fireEvent.click(copyButton); - - await waitFor(() => { - expect(clipboardWriteText).toHaveBeenCalledWith('Failed to calculate quote'); - expect(mockAddToast).toHaveBeenCalledWith({ - message: 'Copied quote error', - type: 'success', - color: 'green' - }); - expect(mockErrToast).not.toHaveBeenCalled(); - }); - }); - - it('displays truncated amounts with tooltips', async () => { - (mockOrder.getQuotes as Mock).mockResolvedValueOnce({ - value: [ - { - success: true, - blockNumber: '0x123', - pair: { pairName: 'ETH/USDT', inputIndex: 0, outputIndex: 1 }, - data: { - formattedMaxOutput: '1.550122181502135692', - formattedRatio: '6.563567234157974775', - formattedInverseRatio: '0.152345678901234567', - formattedMaxInput: '10.175432109876543210' - }, - error: undefined - } - ] - }); - - const queryClient = new QueryClient(); - - render(TanstackOrderQuote, { - props: { - order: mockOrder, - handleQuoteDebugModal: vi.fn() - }, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - const maxOutputSpan = document.getElementById('max-output-0'); - expect(maxOutputSpan).not.toBeNull(); - expect(maxOutputSpan?.classList.contains('truncate')).toBe(true); - expect(maxOutputSpan).toHaveTextContent('1.550122181502135692'); - - const ratioSpan = document.getElementById('ratio-0'); - expect(ratioSpan).not.toBeNull(); - expect(ratioSpan?.classList.contains('truncate')).toBe(true); - expect(ratioSpan).toHaveTextContent('6.563567234157974775'); - expect(ratioSpan).toHaveTextContent('0.152345678901234567'); - - const maxInputSpan = document.getElementById('max-input-0'); - expect(maxInputSpan).not.toBeNull(); - expect(maxInputSpan?.classList.contains('truncate')).toBe(true); - expect(maxInputSpan).toHaveTextContent('10.175432109876543210'); - }); - }); +describe("TanstackOrderQuote component", () => { + const mockOrder: RaindexOrder = { + id: "1", + getQuotes: vi.fn(), + } as unknown as RaindexOrder; + + beforeEach(() => { + vi.clearAllMocks(); + vi.resetAllMocks(); + mockErrToast.mockReset(); + mockAddToast.mockReset(); + clipboardWriteText = vi.fn().mockResolvedValue(undefined); + Object.defineProperty(window.navigator, "clipboard", { + value: { writeText: clipboardWriteText }, + configurable: true, + }); + (useToasts as Mock).mockReturnValue({ + toasts: writable([]), + errToast: mockErrToast, + addToast: mockAddToast, + removeToast: vi.fn(), + }); + }); + it("displays order quote data when query is successful", async () => { + (mockOrder.getQuotes as Mock).mockResolvedValueOnce({ + value: [ + { + success: true, + block_number: "0x123", + pair: { pairName: "ETH/USDT", inputIndex: 0, outputIndex: 1 }, + data: { + formattedMaxOutput: "1.550122181502135692", + formattedRatio: "6.563567234157974775", + }, + error: undefined, + }, + ], + }); + + const queryClient = new QueryClient(); + + render(TanstackOrderQuote, { + props: { + order: mockOrder, + handleQuoteDebugModal: vi.fn(), + }, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + const orderQuoteComponent = screen.getByTestId("bodyRow"); + + expect(orderQuoteComponent).toHaveTextContent("ETH/USDT"); + expect(orderQuoteComponent).toHaveTextContent("1.550122181502135692"); + expect(orderQuoteComponent).toHaveTextContent("6.563567234157974775"); + }); + }); + + it("refreshes the quote when the refresh icon is clicked", async () => { + (mockOrder.getQuotes as Mock).mockResolvedValueOnce({ + value: [ + { + success: true, + block_number: "0x123", + pair: { pairName: "ETH/USDT", inputIndex: 0, outputIndex: 1 }, + data: { formattedMaxOutput: "1.550122181502135692" }, + error: undefined, + }, + { + success: true, + block_number: "0x123", + pair: { pairName: "BTC/USDT", inputIndex: 0, outputIndex: 1 }, + data: { formattedMaxOutput: "6.123350635480882605" }, + error: undefined, + }, + ], + }); + // Setup mock for the second data load (after refresh) + (mockOrder.getQuotes as Mock).mockResolvedValueOnce({ + value: [ + { + success: true, + block_number: "0x123", + pair: { pairName: "ETH/USDT", inputIndex: 0, outputIndex: 1 }, + data: { + formattedMaxOutput: "5.945438972656012126", + formattedRatio: "6.305004957644166012", + }, + error: undefined, + }, + { + success: true, + block_number: "0x123", + pair: { pairName: "BTC/USDT", inputIndex: 0, outputIndex: 1 }, + data: { + formattedMaxOutput: "6.066479884955967059", + formattedRatio: "6.485589855485802559", + }, + error: undefined, + }, + ], + }); + + // Mock the invalidateTanstackQueries function to ensure it works correctly + (invalidateTanstackQueries as Mock).mockImplementation( + (queryClient, queryKey) => { + // This will trigger a refetch which will use the second mock + queryClient.invalidateQueries({ queryKey }); + return Promise.resolve(); + }, + ); + + const queryClient = new QueryClient(); + + render(TanstackOrderQuote, { + props: { + order: mockOrder, + handleQuoteDebugModal: vi.fn(), + }, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + const orderQuoteRows = screen.getAllByTestId("bodyRow"); + + // Check ETH/USDT row + expect(orderQuoteRows[0]).toHaveTextContent("1.550122181502135692"); + + // Check BTC/USDT row + expect(orderQuoteRows[1]).toHaveTextContent("6.123350635480882605"); + }); + + const refreshButton = screen.getByTestId("refresh-button"); + fireEvent.click(refreshButton); + + await waitFor(() => { + const orderQuoteRows = screen.getAllByTestId("bodyRow"); + + // Check ETH/USD row + expect(orderQuoteRows[0]).toHaveTextContent("ETH/USD"); + expect(orderQuoteRows[0]).toHaveTextContent("5.945438972656012126"); + expect(orderQuoteRows[0]).toHaveTextContent("6.305004957644166012"); + + // Check BTC/USDT row + expect(orderQuoteRows[1]).toHaveTextContent("BTC/USDT"); + expect(orderQuoteRows[1]).toHaveTextContent("6.066479884955967059"); + expect(orderQuoteRows[1]).toHaveTextContent("6.485589855485802559"); + }); + }); + + it("displays error message when query fails", async () => { + (mockOrder.getQuotes as Mock).mockResolvedValueOnce({ + value: [ + { + success: false, + block_number: "0x123", + pair: { pairName: "ETH/USDT", inputIndex: 0, outputIndex: 1 }, + data: undefined, + error: "Network error", + }, + ], + }); + + const queryClient = new QueryClient(); + + render(TanstackOrderQuote, { + props: { + order: mockOrder, + handleQuoteDebugModal: vi.fn(), + }, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + const errorNodes = screen.queryAllByText(/Network error/); + expect(errorNodes.length).toBeGreaterThan(0); + }); + }); + + it("displays zero for price when io ratio is zero", async () => { + (mockOrder.getQuotes as Mock).mockResolvedValueOnce({ + value: [ + { + success: true, + block_number: "0x123", + pair: { pairName: "ETH/USDT", inputIndex: 0, outputIndex: 1 }, + data: { + formattedMaxOutput: "1.550122181502135692", + formattedRatio: "0", + formattedInverseRatio: "0", + }, + error: undefined, + }, + ], + }); + + const queryClient = new QueryClient(); + + render(TanstackOrderQuote, { + props: { + order: mockOrder, + handleQuoteDebugModal: vi.fn(), + }, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + const orderQuoteComponent = screen.getByTestId("bodyRow"); + + expect(orderQuoteComponent).toHaveTextContent("ETH/USDT"); + expect(orderQuoteComponent).toHaveTextContent("1.550122181502135692"); // maxOutput + expect(orderQuoteComponent).toHaveTextContent("0"); // ratio + expect(orderQuoteComponent).toHaveTextContent("(0)"); // inverse price + }); + }); + + it("triggers a toast when the quote fails to refresh", async () => { + (invalidateTanstackQueries as Mock).mockRejectedValueOnce( + new Error("Failed to refresh"), + ); + (mockOrder.getQuotes as Mock).mockResolvedValueOnce({ + value: [ + { + success: true, + block_number: "0x123", + pair: { pairName: "ETH/USDT", inputIndex: 0, outputIndex: 1 }, + data: { + maxOutput: "0x158323e942e36d8c", + ratio: "0x5b16799fcb6114f7", + }, + error: undefined, + }, + { + success: true, + block_number: "0x123", + pair: { pairName: "BTC/USDT", inputIndex: 0, outputIndex: 1 }, + data: { + maxOutput: "0x54fa82f5c7001dad", + ratio: "0x53e0089714d06709", + }, + error: undefined, + }, + ], + }); + const queryClient = new QueryClient(); + + render(TanstackOrderQuote, { + props: { + order: mockOrder, + handleQuoteDebugModal: vi.fn(), + }, + context: new Map([["$$_queryClient", queryClient]]), + }); + + const refreshButton = screen.getByTestId("refresh-button"); + fireEvent.click(refreshButton); + + await waitFor(() => { + expect(mockErrToast).toHaveBeenCalledWith("Failed to refresh"); + }); + }); + + it("copies the quote error to the clipboard and notifies the user", async () => { + (mockOrder.getQuotes as Mock).mockResolvedValueOnce({ + value: [ + { + success: false, + block_number: "0x123", + pair: { pairName: "ETH/USDT", inputIndex: 0, outputIndex: 1 }, + data: undefined, + error: "Failed to calculate quote", + }, + ], + }); + + const queryClient = new QueryClient(); + + render(TanstackOrderQuote, { + props: { + order: mockOrder, + handleQuoteDebugModal: vi.fn(), + }, + context: new Map([["$$_queryClient", queryClient]]), + }); + + const copyButton = await screen.findByRole("button", { + name: "Copy quote error", + }); + await fireEvent.click(copyButton); + + await waitFor(() => { + expect(clipboardWriteText).toHaveBeenCalledWith( + "Failed to calculate quote", + ); + expect(mockAddToast).toHaveBeenCalledWith({ + message: "Copied quote error", + type: "success", + color: "green", + }); + expect(mockErrToast).not.toHaveBeenCalled(); + }); + }); + + it("displays truncated amounts with tooltips", async () => { + (mockOrder.getQuotes as Mock).mockResolvedValueOnce({ + value: [ + { + success: true, + blockNumber: "0x123", + pair: { pairName: "ETH/USDT", inputIndex: 0, outputIndex: 1 }, + data: { + formattedMaxOutput: "1.550122181502135692", + formattedRatio: "6.563567234157974775", + formattedInverseRatio: "0.152345678901234567", + formattedMaxInput: "10.175432109876543210", + }, + error: undefined, + }, + ], + }); + + const queryClient = new QueryClient(); + + render(TanstackOrderQuote, { + props: { + order: mockOrder, + handleQuoteDebugModal: vi.fn(), + }, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + const maxOutputSpan = document.getElementById("max-output-0"); + expect(maxOutputSpan).not.toBeNull(); + expect(maxOutputSpan?.classList.contains("truncate")).toBe(true); + expect(maxOutputSpan).toHaveTextContent("1.550122181502135692"); + + const ratioSpan = document.getElementById("ratio-0"); + expect(ratioSpan).not.toBeNull(); + expect(ratioSpan?.classList.contains("truncate")).toBe(true); + expect(ratioSpan).toHaveTextContent("6.563567234157974775"); + expect(ratioSpan).toHaveTextContent("0.152345678901234567"); + + const maxInputSpan = document.getElementById("max-input-0"); + expect(maxInputSpan).not.toBeNull(); + expect(maxInputSpan?.classList.contains("truncate")).toBe(true); + expect(maxInputSpan).toHaveTextContent("10.175432109876543210"); + }); + }); }); diff --git a/packages/ui-components/src/__tests__/TanstackPageContentDetail.test.ts b/packages/ui-components/src/__tests__/TanstackPageContentDetail.test.ts index 699774ed6f..2daded74d7 100644 --- a/packages/ui-components/src/__tests__/TanstackPageContentDetail.test.ts +++ b/packages/ui-components/src/__tests__/TanstackPageContentDetail.test.ts @@ -1,71 +1,71 @@ -import { render, screen, waitFor } from '@testing-library/svelte'; -import { test } from 'vitest'; -import { expect } from '../lib/test/matchers'; -import TanstackPageContentDetailTest from './TanstackPageContentDetail.test.svelte'; -import { createResolvableQuery } from '../lib/__mocks__/queries'; +import { render, screen, waitFor } from "@testing-library/svelte"; +import { test } from "vitest"; +import { expect } from "../lib/test/matchers"; +import TanstackPageContentDetailTest from "./TanstackPageContentDetail.test.svelte"; +import { createResolvableQuery } from "../lib/__mocks__/queries"; -test('shows query data in correct places', async () => { - const { query, resolve } = createResolvableQuery(() => { - return 'test data'; - }); +test("shows query data in correct places", async () => { + const { query, resolve } = createResolvableQuery(() => { + return "test data"; + }); - render(TanstackPageContentDetailTest, { - query, - emptyMessage: 'No data', - below: 'Below' - }); + render(TanstackPageContentDetailTest, { + query, + emptyMessage: "No data", + below: "Below", + }); - resolve(); + resolve(); - await waitFor(() => { - expect(screen.getByTestId('top')).toHaveTextContent('test data'); - expect(screen.getByTestId('card')).toHaveTextContent('test data'); - expect(screen.getByTestId('chart')).toHaveTextContent('test data'); - expect(screen.getByTestId('below')).toHaveTextContent('Below'); - }); + await waitFor(() => { + expect(screen.getByTestId("top")).toHaveTextContent("test data"); + expect(screen.getByTestId("card")).toHaveTextContent("test data"); + expect(screen.getByTestId("chart")).toHaveTextContent("test data"); + expect(screen.getByTestId("below")).toHaveTextContent("Below"); + }); }); -test('shows empty message', async () => { - const { query, resolve } = createResolvableQuery(() => { - return undefined; - }); +test("shows empty message", async () => { + const { query, resolve } = createResolvableQuery(() => { + return undefined; + }); - render(TanstackPageContentDetailTest, { - query, - emptyMessage: 'No data', - below: 'Below' - }); + render(TanstackPageContentDetailTest, { + query, + emptyMessage: "No data", + below: "Below", + }); - resolve(); + resolve(); - await waitFor(() => { - expect(screen.getByTestId('emptyMessage')).toHaveTextContent('No data'); - }); + await waitFor(() => { + expect(screen.getByTestId("emptyMessage")).toHaveTextContent("No data"); + }); }); -test('shows the loading spinner when query is still loading/fetching and hides it when data is fetched', async () => { - const { query, resolve } = createResolvableQuery(() => { - return 'test data'; - }); +test("shows the loading spinner when query is still loading/fetching and hides it when data is fetched", async () => { + const { query, resolve } = createResolvableQuery(() => { + return "test data"; + }); - render(TanstackPageContentDetailTest, { - query, - emptyMessage: 'No data', - below: 'Below' - }); + render(TanstackPageContentDetailTest, { + query, + emptyMessage: "No data", + below: "Below", + }); - await waitFor(() => { - expect(screen.getByTestId('loadingSpinner')).toBeInTheDocument(); - }); + await waitFor(() => { + expect(screen.getByTestId("loadingSpinner")).toBeInTheDocument(); + }); - resolve(); + resolve(); - await waitFor(() => { - expect(screen.queryByTestId('loadingSpinner')).not.toBeInTheDocument(); + await waitFor(() => { + expect(screen.queryByTestId("loadingSpinner")).not.toBeInTheDocument(); - expect(screen.getByTestId('top')).toHaveTextContent('test data'); - expect(screen.getByTestId('card')).toHaveTextContent('test data'); - expect(screen.getByTestId('chart')).toHaveTextContent('test data'); - expect(screen.getByTestId('below')).toHaveTextContent('Below'); - }); + expect(screen.getByTestId("top")).toHaveTextContent("test data"); + expect(screen.getByTestId("card")).toHaveTextContent("test data"); + expect(screen.getByTestId("chart")).toHaveTextContent("test data"); + expect(screen.getByTestId("below")).toHaveTextContent("Below"); + }); }); diff --git a/packages/ui-components/src/__tests__/ToastDetail.test.ts b/packages/ui-components/src/__tests__/ToastDetail.test.ts index 66a52727e2..d74ce9eeb7 100644 --- a/packages/ui-components/src/__tests__/ToastDetail.test.ts +++ b/packages/ui-components/src/__tests__/ToastDetail.test.ts @@ -1,122 +1,124 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import { render, screen, fireEvent } from '@testing-library/svelte'; -import ToastDetail from '../lib/components/ToastDetail.svelte'; -import type { ToastProps } from '../lib/types/toast'; -import { useToasts } from '../lib/providers/toasts/useToasts'; -import { writable } from 'svelte/store'; +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { render, screen, fireEvent } from "@testing-library/svelte"; +import ToastDetail from "../lib/components/ToastDetail.svelte"; +import type { ToastProps } from "../lib/types/toast"; +import { useToasts } from "../lib/providers/toasts/useToasts"; +import { writable } from "svelte/store"; // Mock the useToasts hook -vi.mock('../lib/providers/toasts/useToasts', () => ({ - useToasts: vi.fn() +vi.mock("../lib/providers/toasts/useToasts", () => ({ + useToasts: vi.fn(), })); const mockRemoveToast = vi.fn(); -describe('ToastDetail', () => { - beforeEach(() => { - vi.clearAllMocks(); - vi.mocked(useToasts).mockReturnValue({ - removeToast: mockRemoveToast, - toasts: writable([]), - addToast: vi.fn(), - errToast: vi.fn() - }); - }); - - it('should render toast message', () => { - const toast: ToastProps = { - color: 'green', - message: 'Test message', - type: 'success', - links: [] - }; - - render(ToastDetail, { toast, i: 0 }); - expect(screen.getByText('Test message')).toBeInTheDocument(); - }); - - it('should render success icon for success type', () => { - const toast: ToastProps = { - color: 'green', - message: 'Success message', - type: 'success', - links: [] - }; - - render(ToastDetail, { toast, i: 0 }); - expect(screen.getByTestId('success-icon')).toBeInTheDocument(); - }); - - it('should render error icon for error type', () => { - const toast: ToastProps = { - color: 'red', - message: 'Error message', - type: 'error', - links: [] - }; - - render(ToastDetail, { toast, i: 0 }); - expect(screen.getByTestId('error-icon')).toBeInTheDocument(); - }); - - it('should render links when provided', () => { - const toast: ToastProps = { - color: 'green', - message: 'Message with links', - type: 'success', - links: [ - { - link: 'https://example.com', - label: 'Example Link' - }, - { - link: 'https://test.com', - label: 'Test Link' - } - ] - }; - - render(ToastDetail, { toast, i: 0 }); - - const links = screen.getAllByRole('link'); - expect(links).toHaveLength(2); - - expect(links[0]).toHaveAttribute('href', 'https://example.com'); - expect(links[0]).toHaveAttribute('target', '_blank'); - expect(links[0]).toHaveAttribute('rel', 'noopener noreferrer'); - expect(links[0]).toHaveTextContent('Example Link'); - - expect(links[1]).toHaveAttribute('href', 'https://test.com'); - expect(links[1]).toHaveAttribute('target', '_blank'); - expect(links[1]).toHaveAttribute('rel', 'noopener noreferrer'); - expect(links[1]).toHaveTextContent('Test Link'); - }); - - it('should call removeToast when close button is clicked', async () => { - const toast: ToastProps = { - color: 'green', - message: 'Test message', - type: 'success', - links: [] - }; - - render(ToastDetail, { toast, i: 1 }); - - const closeButton = screen.getByRole('button'); - await fireEvent.click(closeButton); - - expect(mockRemoveToast).toHaveBeenCalledWith(1); - }); - - it('should render detail when provided', () => { - const toast: ToastProps = { - color: 'red', - message: 'Error message', - type: 'error', - detail: 'Details about what caused the error' - }; - - render(ToastDetail, { toast, i: 0 }); - expect(screen.getByText('Details about what caused the error')).toBeInTheDocument(); - }); +describe("ToastDetail", () => { + beforeEach(() => { + vi.clearAllMocks(); + vi.mocked(useToasts).mockReturnValue({ + removeToast: mockRemoveToast, + toasts: writable([]), + addToast: vi.fn(), + errToast: vi.fn(), + }); + }); + + it("should render toast message", () => { + const toast: ToastProps = { + color: "green", + message: "Test message", + type: "success", + links: [], + }; + + render(ToastDetail, { toast, i: 0 }); + expect(screen.getByText("Test message")).toBeInTheDocument(); + }); + + it("should render success icon for success type", () => { + const toast: ToastProps = { + color: "green", + message: "Success message", + type: "success", + links: [], + }; + + render(ToastDetail, { toast, i: 0 }); + expect(screen.getByTestId("success-icon")).toBeInTheDocument(); + }); + + it("should render error icon for error type", () => { + const toast: ToastProps = { + color: "red", + message: "Error message", + type: "error", + links: [], + }; + + render(ToastDetail, { toast, i: 0 }); + expect(screen.getByTestId("error-icon")).toBeInTheDocument(); + }); + + it("should render links when provided", () => { + const toast: ToastProps = { + color: "green", + message: "Message with links", + type: "success", + links: [ + { + link: "https://example.com", + label: "Example Link", + }, + { + link: "https://test.com", + label: "Test Link", + }, + ], + }; + + render(ToastDetail, { toast, i: 0 }); + + const links = screen.getAllByRole("link"); + expect(links).toHaveLength(2); + + expect(links[0]).toHaveAttribute("href", "https://example.com"); + expect(links[0]).toHaveAttribute("target", "_blank"); + expect(links[0]).toHaveAttribute("rel", "noopener noreferrer"); + expect(links[0]).toHaveTextContent("Example Link"); + + expect(links[1]).toHaveAttribute("href", "https://test.com"); + expect(links[1]).toHaveAttribute("target", "_blank"); + expect(links[1]).toHaveAttribute("rel", "noopener noreferrer"); + expect(links[1]).toHaveTextContent("Test Link"); + }); + + it("should call removeToast when close button is clicked", async () => { + const toast: ToastProps = { + color: "green", + message: "Test message", + type: "success", + links: [], + }; + + render(ToastDetail, { toast, i: 1 }); + + const closeButton = screen.getByRole("button"); + await fireEvent.click(closeButton); + + expect(mockRemoveToast).toHaveBeenCalledWith(1); + }); + + it("should render detail when provided", () => { + const toast: ToastProps = { + color: "red", + message: "Error message", + type: "error", + detail: "Details about what caused the error", + }; + + render(ToastDetail, { toast, i: 0 }); + expect( + screen.getByText("Details about what caused the error"), + ).toBeInTheDocument(); + }); }); diff --git a/packages/ui-components/src/__tests__/ToastProvider.test.ts b/packages/ui-components/src/__tests__/ToastProvider.test.ts index d724e99bb0..a7d5ea15ee 100644 --- a/packages/ui-components/src/__tests__/ToastProvider.test.ts +++ b/packages/ui-components/src/__tests__/ToastProvider.test.ts @@ -1,121 +1,127 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import { render, screen } from '@testing-library/svelte'; -import ToastProvider from '../lib/providers/toasts/ToastProvider.svelte'; -import { writable, type Writable } from 'svelte/store'; -import type { ToastProps } from '../lib/types/toast'; - -vi.mock('../lib/providers/toasts/context', async () => ({ - setToastsContext: vi.fn(), - getToastsContext: vi.fn() +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { render, screen } from "@testing-library/svelte"; +import ToastProvider from "../lib/providers/toasts/ToastProvider.svelte"; +import { writable, type Writable } from "svelte/store"; +import type { ToastProps } from "../lib/types/toast"; + +vi.mock("../lib/providers/toasts/context", async () => ({ + setToastsContext: vi.fn(), + getToastsContext: vi.fn(), })); -import { setToastsContext } from '../lib/providers/toasts/context'; - -describe('ToastProvider', () => { - beforeEach(() => { - vi.clearAllMocks(); - }); - - it('should create and set up a writable store for toasts', () => { - render(ToastProvider); - - expect(setToastsContext).toHaveBeenCalledTimes(1); - const toastsArg = vi.mocked(setToastsContext).mock.calls[0][0]; - expect(toastsArg).toBeDefined(); - - // Verify it's a writable store - let value: ToastProps[] = []; - const unsubscribe = toastsArg.subscribe((v) => { - value = v; - }); - expect(value).toEqual([]); - unsubscribe(); - }); - - it('should properly render toast notifications', () => { - const mockToasts = writable([ - { - color: 'green', - message: 'Test toast', - type: 'success', - links: [] - } - ]); - - // Mock the context to return our test store - vi.mocked(setToastsContext).mockImplementation((store: Writable) => { - mockToasts.subscribe((value) => { - store.set(value); - }); - }); - - render(ToastProvider); - - expect(screen.getByRole('alert')).toBeInTheDocument(); - expect(screen.getByText('Test toast')).toBeInTheDocument(); - expect(screen.getByRole('alert')).toHaveTextContent('Test toast'); - }); - - it('should render multiple toasts when present', () => { - const mockToasts = writable([ - { - color: 'green', - message: 'First toast', - type: 'success', - links: [] - }, - { - color: 'red', - message: 'Second toast', - type: 'error', - links: [] - } - ]); - - // Mock the context to return our test store - vi.mocked(setToastsContext).mockImplementation((store: Writable) => { - mockToasts.subscribe((value) => { - store.set(value); - }); - }); - - render(ToastProvider); - - const alerts = screen.getAllByRole('alert'); - expect(alerts).toHaveLength(2); - expect(screen.getByText('First toast')).toBeInTheDocument(); - expect(screen.getByText('Second toast')).toBeInTheDocument(); - }); - - it('should render toasts with links when provided', () => { - const mockToasts = writable([ - { - color: 'green', - message: 'Test toast with link', - type: 'success', - links: [ - { - link: 'https://example.com', - label: 'Example Link' - } - ] - } - ]); - - // Mock the context to return our test store - vi.mocked(setToastsContext).mockImplementation((store: Writable) => { - mockToasts.subscribe((value) => { - store.set(value); - }); - }); - - render(ToastProvider); - - expect(screen.getByText('Test toast with link')).toBeInTheDocument(); - const link = screen.getByText('Example Link'); - expect(link).toBeInTheDocument(); - expect(link).toHaveAttribute('href', 'https://example.com'); - expect(link).toHaveAttribute('target', '_blank'); - expect(link).toHaveAttribute('rel', 'noopener noreferrer'); - }); +import { setToastsContext } from "../lib/providers/toasts/context"; + +describe("ToastProvider", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it("should create and set up a writable store for toasts", () => { + render(ToastProvider); + + expect(setToastsContext).toHaveBeenCalledTimes(1); + const toastsArg = vi.mocked(setToastsContext).mock.calls[0][0]; + expect(toastsArg).toBeDefined(); + + // Verify it's a writable store + let value: ToastProps[] = []; + const unsubscribe = toastsArg.subscribe((v) => { + value = v; + }); + expect(value).toEqual([]); + unsubscribe(); + }); + + it("should properly render toast notifications", () => { + const mockToasts = writable([ + { + color: "green", + message: "Test toast", + type: "success", + links: [], + }, + ]); + + // Mock the context to return our test store + vi.mocked(setToastsContext).mockImplementation( + (store: Writable) => { + mockToasts.subscribe((value) => { + store.set(value); + }); + }, + ); + + render(ToastProvider); + + expect(screen.getByRole("alert")).toBeInTheDocument(); + expect(screen.getByText("Test toast")).toBeInTheDocument(); + expect(screen.getByRole("alert")).toHaveTextContent("Test toast"); + }); + + it("should render multiple toasts when present", () => { + const mockToasts = writable([ + { + color: "green", + message: "First toast", + type: "success", + links: [], + }, + { + color: "red", + message: "Second toast", + type: "error", + links: [], + }, + ]); + + // Mock the context to return our test store + vi.mocked(setToastsContext).mockImplementation( + (store: Writable) => { + mockToasts.subscribe((value) => { + store.set(value); + }); + }, + ); + + render(ToastProvider); + + const alerts = screen.getAllByRole("alert"); + expect(alerts).toHaveLength(2); + expect(screen.getByText("First toast")).toBeInTheDocument(); + expect(screen.getByText("Second toast")).toBeInTheDocument(); + }); + + it("should render toasts with links when provided", () => { + const mockToasts = writable([ + { + color: "green", + message: "Test toast with link", + type: "success", + links: [ + { + link: "https://example.com", + label: "Example Link", + }, + ], + }, + ]); + + // Mock the context to return our test store + vi.mocked(setToastsContext).mockImplementation( + (store: Writable) => { + mockToasts.subscribe((value) => { + store.set(value); + }); + }, + ); + + render(ToastProvider); + + expect(screen.getByText("Test toast with link")).toBeInTheDocument(); + const link = screen.getByText("Example Link"); + expect(link).toBeInTheDocument(); + expect(link).toHaveAttribute("href", "https://example.com"); + expect(link).toHaveAttribute("target", "_blank"); + expect(link).toHaveAttribute("rel", "noopener noreferrer"); + }); }); diff --git a/packages/ui-components/src/__tests__/TokenBalance.test.ts b/packages/ui-components/src/__tests__/TokenBalance.test.ts index 29e7c49d62..48e92edb9a 100644 --- a/packages/ui-components/src/__tests__/TokenBalance.test.ts +++ b/packages/ui-components/src/__tests__/TokenBalance.test.ts @@ -1,108 +1,128 @@ -import { render, screen } from '@testing-library/svelte'; -import { describe, it, expect } from 'vitest'; -import TokenBalance from '../lib/components/deployment/TokenBalance.svelte'; -import type { ComponentProps } from 'svelte'; -import type { TokenBalance as TokenBalanceType } from '$lib/types/tokenBalance'; -import { Float, type AccountBalance } from '@rainlanguage/raindex'; +import { render, screen } from "@testing-library/svelte"; +import { describe, it, expect } from "vitest"; +import TokenBalance from "../lib/components/deployment/TokenBalance.svelte"; +import type { ComponentProps } from "svelte"; +import type { TokenBalance as TokenBalanceType } from "$lib/types/tokenBalance"; +import { Float, type AccountBalance } from "@rainlanguage/raindex"; type TokenBalanceComponentProps = ComponentProps; -vi.mock('@rainlanguage/raindex', async (importOriginal) => { - return { - ...(await importOriginal()) - }; +vi.mock("@rainlanguage/raindex", async (importOriginal) => { + return { + ...(await importOriginal()), + }; }); -describe('TokenBalance', () => { - const createMockTokenBalance = ( - balance = Float.parse('0').value, - formattedBalance: string = '0', - loading: boolean = false, - error: string = '' - ): TokenBalanceType => ({ - value: { balance, formattedBalance } as AccountBalance, - loading, - error - }); - - const defaultProps: TokenBalanceComponentProps = { - tokenBalance: createMockTokenBalance() - }; - - it('renders loading state correctly', () => { - const props: TokenBalanceComponentProps = { - ...defaultProps, - tokenBalance: createMockTokenBalance(Float.parse('0').value, '0', true, '') - }; - - render(TokenBalance, { props }); - - expect(screen.getByRole('status')).toBeInTheDocument(); - }); - - it('renders balance when balance is non-zero', () => { - const props: TokenBalanceComponentProps = { - ...defaultProps, - tokenBalance: createMockTokenBalance(Float.parse('1000').value, '1000', false, '') - }; - - render(TokenBalance, { props }); - - expect(screen.getByText('Balance: 1000')).toBeInTheDocument(); - }); - - it('renders error state correctly', () => { - const props: TokenBalanceComponentProps = { - ...defaultProps, - tokenBalance: createMockTokenBalance( - Float.parse('0').value, - '0', - false, - 'Failed to fetch balance' - ) - }; - - render(TokenBalance, { props }); - - expect(screen.getByText('Failed to fetch balance')).toBeInTheDocument(); - }); - - it('applies correct color classes for balance', () => { - const { container } = render(TokenBalance, { - props: { - ...defaultProps, - tokenBalance: createMockTokenBalance(Float.parse('1000').value, '1,000.00', false, '') - } - }); - - expect(container.querySelector('.text-gray-600')).toBeInTheDocument(); - }); - - it('uses red color for error state', () => { - const { container } = render(TokenBalance, { - props: { - ...defaultProps, - tokenBalance: createMockTokenBalance(Float.parse('0').value, '0', false, 'Error message') - } - }); - - expect(container.querySelector('.text-red-600')).toBeInTheDocument(); - }); - - it('prioritizes error display over balance when both exist', () => { - const props: TokenBalanceComponentProps = { - ...defaultProps, - tokenBalance: createMockTokenBalance( - Float.parse('1000').value, - '1000', - false, - 'Network error' - ) - }; - - render(TokenBalance, { props }); - - expect(screen.getByText('Network error')).toBeInTheDocument(); - expect(screen.queryByText('Balance: 1000')).not.toBeInTheDocument(); - }); +describe("TokenBalance", () => { + const createMockTokenBalance = ( + balance = Float.parse("0").value, + formattedBalance: string = "0", + loading: boolean = false, + error: string = "", + ): TokenBalanceType => ({ + value: { balance, formattedBalance } as AccountBalance, + loading, + error, + }); + + const defaultProps: TokenBalanceComponentProps = { + tokenBalance: createMockTokenBalance(), + }; + + it("renders loading state correctly", () => { + const props: TokenBalanceComponentProps = { + ...defaultProps, + tokenBalance: createMockTokenBalance( + Float.parse("0").value, + "0", + true, + "", + ), + }; + + render(TokenBalance, { props }); + + expect(screen.getByRole("status")).toBeInTheDocument(); + }); + + it("renders balance when balance is non-zero", () => { + const props: TokenBalanceComponentProps = { + ...defaultProps, + tokenBalance: createMockTokenBalance( + Float.parse("1000").value, + "1000", + false, + "", + ), + }; + + render(TokenBalance, { props }); + + expect(screen.getByText("Balance: 1000")).toBeInTheDocument(); + }); + + it("renders error state correctly", () => { + const props: TokenBalanceComponentProps = { + ...defaultProps, + tokenBalance: createMockTokenBalance( + Float.parse("0").value, + "0", + false, + "Failed to fetch balance", + ), + }; + + render(TokenBalance, { props }); + + expect(screen.getByText("Failed to fetch balance")).toBeInTheDocument(); + }); + + it("applies correct color classes for balance", () => { + const { container } = render(TokenBalance, { + props: { + ...defaultProps, + tokenBalance: createMockTokenBalance( + Float.parse("1000").value, + "1,000.00", + false, + "", + ), + }, + }); + + expect(container.querySelector(".text-gray-600")).toBeInTheDocument(); + }); + + it("uses red color for error state", () => { + const { container } = render(TokenBalance, { + props: { + ...defaultProps, + tokenBalance: createMockTokenBalance( + Float.parse("0").value, + "0", + false, + "Error message", + ), + }, + }); + + expect(container.querySelector(".text-red-600")).toBeInTheDocument(); + }); + + it("prioritizes error display over balance when both exist", () => { + const props: TokenBalanceComponentProps = { + ...defaultProps, + tokenBalance: createMockTokenBalance( + Float.parse("1000").value, + "1000", + false, + "Network error", + ), + }; + + render(TokenBalance, { props }); + + expect(screen.getByText("Network error")).toBeInTheDocument(); + expect(screen.queryByText("Balance: 1000")).not.toBeInTheDocument(); + }); }); diff --git a/packages/ui-components/src/__tests__/TokenIOInput.test.ts b/packages/ui-components/src/__tests__/TokenIOInput.test.ts index dee1ba200f..45963b76b3 100644 --- a/packages/ui-components/src/__tests__/TokenIOInput.test.ts +++ b/packages/ui-components/src/__tests__/TokenIOInput.test.ts @@ -1,222 +1,238 @@ -import { render, fireEvent, waitFor } from '@testing-library/svelte'; -import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; -import TokenIOInput from '../lib/components/deployment/TokenIOInput.svelte'; -import type { ComponentProps } from 'svelte'; -import { AccountBalance, RaindexOrderBuilder, Float } from '@rainlanguage/raindex'; -import { useRaindexOrderBuilder } from '$lib/hooks/useRaindexOrderBuilder'; -import type { TokenBalance } from '$lib/types/tokenBalance'; - -vi.mock('@rainlanguage/raindex', async (importOriginal) => { - return { - ...(await importOriginal()), - RaindexOrderBuilder: vi.fn() - }; +import { render, fireEvent, waitFor } from "@testing-library/svelte"; +import { describe, it, expect, vi, beforeEach, type Mock } from "vitest"; +import TokenIOInput from "../lib/components/deployment/TokenIOInput.svelte"; +import type { ComponentProps } from "svelte"; +import { + AccountBalance, + RaindexOrderBuilder, + Float, +} from "@rainlanguage/raindex"; +import { useRaindexOrderBuilder } from "$lib/hooks/useRaindexOrderBuilder"; +import type { TokenBalance } from "$lib/types/tokenBalance"; + +vi.mock("@rainlanguage/raindex", async (importOriginal) => { + return { + ...(await importOriginal()), + RaindexOrderBuilder: vi.fn(), + }; }); -vi.mock('$lib/hooks/useRaindexOrderBuilder', () => ({ - useRaindexOrderBuilder: vi.fn() +vi.mock("$lib/hooks/useRaindexOrderBuilder", () => ({ + useRaindexOrderBuilder: vi.fn(), })); type TokenIOInputComponentProps = ComponentProps; -describe('TokenInput', () => { - let builderInstance: RaindexOrderBuilder; - let mockStateUpdateCallback: Mock; - let mockProps: TokenIOInputComponentProps; - let outputMockProps: TokenIOInputComponentProps; - - const mockInput = { - token: { - address: '0x123', - key: 'test' - } - }; - const mockTokenInfo = { - value: { - symbol: 'MOCK', - name: 'Mock Token', - decimals: 18 - } - }; - - beforeEach(() => { - vi.clearAllMocks(); - - // Create a mock instance with all the methods - builderInstance = { - getTokenInfo: vi.fn().mockResolvedValue(mockTokenInfo), - setVaultId: vi.fn().mockImplementation(() => { - mockStateUpdateCallback(); - }), - getCurrentDeployment: vi.fn().mockResolvedValue({ - deployment: { - order: { - inputs: [mockInput] - } - } - }), - getVaultIds: vi.fn().mockReturnValue({ - value: new Map([ - ['input', new Map([['test', 'vault1']])], - ['output', new Map([['test', 'vault2']])] - ]) - }) - } as unknown as RaindexOrderBuilder; - - mockStateUpdateCallback = vi.fn(); - - (useRaindexOrderBuilder as Mock).mockReturnValue(builderInstance); - - mockProps = { - label: 'Input', - vault: mockInput, - tokenBalances: new Map() - } as unknown as TokenIOInputComponentProps; - outputMockProps = { - label: 'Output', - vault: mockInput, - tokenBalances: new Map() - } as unknown as TokenIOInputComponentProps; - }); - - it('renders with correct label and no token symbol', () => { - const { getByText } = render(TokenIOInput, mockProps); - expect(getByText('Input')).toBeInTheDocument(); - }); - - it('renders input field with correct placeholder', () => { - const { getByPlaceholderText } = render(TokenIOInput, mockProps); - const input = getByPlaceholderText('Enter vault ID'); - expect(input).toBeInTheDocument(); - }); - - it('displays the correct vault ID value', async () => { - const { getByText } = render(TokenIOInput, mockProps); - await waitFor(() => { - expect(getByText('MOCK vault ID')).toBeInTheDocument(); - }); - }); - - it('calls setVaultId when input changes', async () => { - const input = render(TokenIOInput, mockProps).getByPlaceholderText('Enter vault ID'); - await fireEvent.input(input, { target: { value: 'vault1' } }); - expect(builderInstance.setVaultId).toHaveBeenCalledWith('input', 'test', 'vault1'); - expect(mockStateUpdateCallback).toHaveBeenCalledTimes(1); - }); - - it('calls setVaultId on output vault when input changes', async () => { - const input = render(TokenIOInput, outputMockProps).getByPlaceholderText('Enter vault ID'); - await fireEvent.input(input, { target: { value: 'vault2' } }); - expect(builderInstance.setVaultId).toHaveBeenCalledWith('output', 'test', 'vault2'); - expect(mockStateUpdateCallback).toHaveBeenCalledTimes(1); - }); - - it('handles missing token info gracefully', () => { - const propsWithUnknownToken = { - ...mockProps, - vault: { token: { address: '0x789' } } - }; - const { getByText } = render( - TokenIOInput, - propsWithUnknownToken as unknown as TokenIOInputComponentProps - ); - expect(getByText('Input')).toBeInTheDocument(); - }); - - describe('Balance Display', () => { - it('passes token balance to VaultIdInformation component', async () => { - const tokenBalances = new Map(); - tokenBalances.set('test', { - value: { - balance: Float.parse('1').value, - formattedBalance: '1' - } as AccountBalance, - loading: false, - error: '' - }); - - const propsWithBalance = { - ...mockProps, - tokenBalances - }; - - const { findByText } = render(TokenIOInput, propsWithBalance); - - const labelWithSymbol = await findByText('Input (MOCK)'); - expect(labelWithSymbol).toBeInTheDocument(); - }); - - it('passes loading balance state to VaultIdInformation component', async () => { - const tokenBalances = new Map(); - tokenBalances.set('test', { - value: { - balance: Float.parse('0').value, - formattedBalance: '0' - } as AccountBalance, - loading: true, - error: '' - }); - - const propsWithLoadingBalance = { - ...mockProps, - tokenBalances - }; - - const { findByText } = render(TokenIOInput, propsWithLoadingBalance); - - const labelWithSymbol = await findByText('Input (MOCK)'); - expect(labelWithSymbol).toBeInTheDocument(); - }); - - it('passes balance error state to VaultIdInformation component', async () => { - const tokenBalances = new Map(); - tokenBalances.set('test', { - value: { - balance: Float.parse('0').value, - formattedBalance: '0' - } as AccountBalance, - loading: false, - error: 'Network error' - }); - - const propsWithErrorBalance = { - ...mockProps, - tokenBalances - }; - - const { findByText } = render(TokenIOInput, propsWithErrorBalance); - - const labelWithSymbol = await findByText('Input (MOCK)'); - expect(labelWithSymbol).toBeInTheDocument(); - }); - - it('handles missing token balance gracefully', async () => { - const propsWithoutBalance = { - ...mockProps, - tokenBalances: new Map() // Empty map - }; - - const { findByText } = render(TokenIOInput, propsWithoutBalance); - - const labelWithSymbol = await findByText('Input (MOCK)'); - expect(labelWithSymbol).toBeInTheDocument(); - }); - }); - - it('fetches and displays token symbol when token key is present', async () => { - const propsWithTokenKey = { - ...mockProps, - vault: { - token: { - key: '0x456' - } - } - } as unknown as TokenIOInputComponentProps; - - const { findByText } = render(TokenIOInput, propsWithTokenKey); - - const labelWithSymbol = await findByText('Input (MOCK)'); - expect(labelWithSymbol).toBeInTheDocument(); - expect(builderInstance.getTokenInfo).toHaveBeenCalledWith('0x456'); - }); +describe("TokenInput", () => { + let builderInstance: RaindexOrderBuilder; + let mockStateUpdateCallback: Mock; + let mockProps: TokenIOInputComponentProps; + let outputMockProps: TokenIOInputComponentProps; + + const mockInput = { + token: { + address: "0x123", + key: "test", + }, + }; + const mockTokenInfo = { + value: { + symbol: "MOCK", + name: "Mock Token", + decimals: 18, + }, + }; + + beforeEach(() => { + vi.clearAllMocks(); + + // Create a mock instance with all the methods + builderInstance = { + getTokenInfo: vi.fn().mockResolvedValue(mockTokenInfo), + setVaultId: vi.fn().mockImplementation(() => { + mockStateUpdateCallback(); + }), + getCurrentDeployment: vi.fn().mockResolvedValue({ + deployment: { + order: { + inputs: [mockInput], + }, + }, + }), + getVaultIds: vi.fn().mockReturnValue({ + value: new Map([ + ["input", new Map([["test", "vault1"]])], + ["output", new Map([["test", "vault2"]])], + ]), + }), + } as unknown as RaindexOrderBuilder; + + mockStateUpdateCallback = vi.fn(); + + (useRaindexOrderBuilder as Mock).mockReturnValue(builderInstance); + + mockProps = { + label: "Input", + vault: mockInput, + tokenBalances: new Map(), + } as unknown as TokenIOInputComponentProps; + outputMockProps = { + label: "Output", + vault: mockInput, + tokenBalances: new Map(), + } as unknown as TokenIOInputComponentProps; + }); + + it("renders with correct label and no token symbol", () => { + const { getByText } = render(TokenIOInput, mockProps); + expect(getByText("Input")).toBeInTheDocument(); + }); + + it("renders input field with correct placeholder", () => { + const { getByPlaceholderText } = render(TokenIOInput, mockProps); + const input = getByPlaceholderText("Enter vault ID"); + expect(input).toBeInTheDocument(); + }); + + it("displays the correct vault ID value", async () => { + const { getByText } = render(TokenIOInput, mockProps); + await waitFor(() => { + expect(getByText("MOCK vault ID")).toBeInTheDocument(); + }); + }); + + it("calls setVaultId when input changes", async () => { + const input = render(TokenIOInput, mockProps).getByPlaceholderText( + "Enter vault ID", + ); + await fireEvent.input(input, { target: { value: "vault1" } }); + expect(builderInstance.setVaultId).toHaveBeenCalledWith( + "input", + "test", + "vault1", + ); + expect(mockStateUpdateCallback).toHaveBeenCalledTimes(1); + }); + + it("calls setVaultId on output vault when input changes", async () => { + const input = render(TokenIOInput, outputMockProps).getByPlaceholderText( + "Enter vault ID", + ); + await fireEvent.input(input, { target: { value: "vault2" } }); + expect(builderInstance.setVaultId).toHaveBeenCalledWith( + "output", + "test", + "vault2", + ); + expect(mockStateUpdateCallback).toHaveBeenCalledTimes(1); + }); + + it("handles missing token info gracefully", () => { + const propsWithUnknownToken = { + ...mockProps, + vault: { token: { address: "0x789" } }, + }; + const { getByText } = render( + TokenIOInput, + propsWithUnknownToken as unknown as TokenIOInputComponentProps, + ); + expect(getByText("Input")).toBeInTheDocument(); + }); + + describe("Balance Display", () => { + it("passes token balance to VaultIdInformation component", async () => { + const tokenBalances = new Map(); + tokenBalances.set("test", { + value: { + balance: Float.parse("1").value, + formattedBalance: "1", + } as AccountBalance, + loading: false, + error: "", + }); + + const propsWithBalance = { + ...mockProps, + tokenBalances, + }; + + const { findByText } = render(TokenIOInput, propsWithBalance); + + const labelWithSymbol = await findByText("Input (MOCK)"); + expect(labelWithSymbol).toBeInTheDocument(); + }); + + it("passes loading balance state to VaultIdInformation component", async () => { + const tokenBalances = new Map(); + tokenBalances.set("test", { + value: { + balance: Float.parse("0").value, + formattedBalance: "0", + } as AccountBalance, + loading: true, + error: "", + }); + + const propsWithLoadingBalance = { + ...mockProps, + tokenBalances, + }; + + const { findByText } = render(TokenIOInput, propsWithLoadingBalance); + + const labelWithSymbol = await findByText("Input (MOCK)"); + expect(labelWithSymbol).toBeInTheDocument(); + }); + + it("passes balance error state to VaultIdInformation component", async () => { + const tokenBalances = new Map(); + tokenBalances.set("test", { + value: { + balance: Float.parse("0").value, + formattedBalance: "0", + } as AccountBalance, + loading: false, + error: "Network error", + }); + + const propsWithErrorBalance = { + ...mockProps, + tokenBalances, + }; + + const { findByText } = render(TokenIOInput, propsWithErrorBalance); + + const labelWithSymbol = await findByText("Input (MOCK)"); + expect(labelWithSymbol).toBeInTheDocument(); + }); + + it("handles missing token balance gracefully", async () => { + const propsWithoutBalance = { + ...mockProps, + tokenBalances: new Map(), // Empty map + }; + + const { findByText } = render(TokenIOInput, propsWithoutBalance); + + const labelWithSymbol = await findByText("Input (MOCK)"); + expect(labelWithSymbol).toBeInTheDocument(); + }); + }); + + it("fetches and displays token symbol when token key is present", async () => { + const propsWithTokenKey = { + ...mockProps, + vault: { + token: { + key: "0x456", + }, + }, + } as unknown as TokenIOInputComponentProps; + + const { findByText } = render(TokenIOInput, propsWithTokenKey); + + const labelWithSymbol = await findByText("Input (MOCK)"); + expect(labelWithSymbol).toBeInTheDocument(); + expect(builderInstance.getTokenInfo).toHaveBeenCalledWith("0x456"); + }); }); diff --git a/packages/ui-components/src/__tests__/TokenSelectionModal.test.ts b/packages/ui-components/src/__tests__/TokenSelectionModal.test.ts index 6ca3d982a8..175a2e5048 100644 --- a/packages/ui-components/src/__tests__/TokenSelectionModal.test.ts +++ b/packages/ui-components/src/__tests__/TokenSelectionModal.test.ts @@ -1,359 +1,372 @@ -import { render, screen, waitFor } from '@testing-library/svelte'; -import userEvent from '@testing-library/user-event'; -import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; -import TokenSelectionModal from '../lib/components/deployment/TokenSelectionModal.svelte'; -import type { ComponentProps } from 'svelte'; -import type { ExtendedTokenInfo, RaindexOrderBuilder } from '@rainlanguage/raindex'; -import { useRaindexOrderBuilder } from '$lib/hooks/useRaindexOrderBuilder'; +import { render, screen, waitFor } from "@testing-library/svelte"; +import userEvent from "@testing-library/user-event"; +import { describe, it, expect, vi, beforeEach, type Mock } from "vitest"; +import TokenSelectionModal from "../lib/components/deployment/TokenSelectionModal.svelte"; +import type { ComponentProps } from "svelte"; +import type { + ExtendedTokenInfo, + RaindexOrderBuilder, +} from "@rainlanguage/raindex"; +import { useRaindexOrderBuilder } from "$lib/hooks/useRaindexOrderBuilder"; type TokenSelectionModalProps = ComponentProps; const mockTokens: ExtendedTokenInfo[] = [ - { - key: 'token1', - address: '0x1234567890123456789012345678901234567890', - name: 'Test Token 1', - symbol: 'TEST1', - decimals: 18, - chainId: 1, - logoUri: 'https://example.com/token1-logo.png' - }, - { - key: 'token2', - address: '0x0987654321098765432109876543210987654321', - name: 'Another Token', - symbol: 'ANOTHER', - decimals: 6, - chainId: 1, - logoUri: undefined - } + { + key: "token1", + address: "0x1234567890123456789012345678901234567890", + name: "Test Token 1", + symbol: "TEST1", + decimals: 18, + chainId: 1, + logoUri: "https://example.com/token1-logo.png", + }, + { + key: "token2", + address: "0x0987654321098765432109876543210987654321", + name: "Another Token", + symbol: "ANOTHER", + decimals: 6, + chainId: 1, + logoUri: undefined, + }, ]; const mockBuilder: RaindexOrderBuilder = { - getAllTokens: vi.fn().mockResolvedValue({ - value: mockTokens - }) + getAllTokens: vi.fn().mockResolvedValue({ + value: mockTokens, + }), } as unknown as RaindexOrderBuilder; -vi.mock('../lib/hooks/useRaindexOrderBuilder', () => ({ - useRaindexOrderBuilder: vi.fn() +vi.mock("../lib/hooks/useRaindexOrderBuilder", () => ({ + useRaindexOrderBuilder: vi.fn(), })); -describe('TokenSelectionModal', () => { - let mockOnSelect: ReturnType; - - const defaultProps: TokenSelectionModalProps = { - selectedToken: null, - onSelect: vi.fn() - }; - - beforeEach(() => { - mockOnSelect = vi.fn(); - (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilder); - vi.clearAllMocks(); - }); - - it('renders modal button with default text when no token is selected', () => { - render(TokenSelectionModal, { - ...defaultProps, - onSelect: mockOnSelect - }); - - expect(screen.getByText('Select a token...')).toBeInTheDocument(); - }); - - it('renders modal button with selected token info when token is selected', () => { - const selectedToken = mockTokens[0]; - render(TokenSelectionModal, { - ...defaultProps, - selectedToken, - onSelect: mockOnSelect - }); - - expect(screen.getByText('Test Token 1 (TEST1)')).toBeInTheDocument(); - }); - - it('opens modal when button is clicked', async () => { - const user = userEvent.setup(); - render(TokenSelectionModal, { - ...defaultProps, - onSelect: mockOnSelect - }); - - const button = screen.getByRole('button'); - await user.click(button); - - expect(screen.getByText('Select a token')).toBeInTheDocument(); - }); - - it('shows search input in modal', async () => { - const user = userEvent.setup(); - render(TokenSelectionModal, { - ...defaultProps, - onSelect: mockOnSelect - }); - - const button = screen.getByRole('button'); - await user.click(button); - - expect(screen.getByPlaceholderText('Search tokens...')).toBeInTheDocument(); - }); - - it('loads tokens on mount', async () => { - render(TokenSelectionModal, { - ...defaultProps, - onSelect: mockOnSelect - }); - - const button = screen.getByRole('button'); - await userEvent.click(button); - - await waitFor(() => { - expect(mockBuilder.getAllTokens).toHaveBeenCalledWith(undefined); - }); - }); - - it('shows tokens in modal after loading', async () => { - const user = userEvent.setup(); - render(TokenSelectionModal, { - ...defaultProps, - onSelect: mockOnSelect - }); - - const button = screen.getByRole('button'); - await user.click(button); - - await waitFor(() => { - expect(screen.getByText('Test Token 1')).toBeInTheDocument(); - expect(screen.getByText('Another Token')).toBeInTheDocument(); - }); - }); - - it('calls onSelect when token is clicked', async () => { - const user = userEvent.setup(); - render(TokenSelectionModal, { - ...defaultProps, - onSelect: mockOnSelect - }); - - const button = screen.getByRole('button'); - await user.click(button); - - await waitFor(() => { - expect(screen.getByText('Test Token 1')).toBeInTheDocument(); - }); - - const tokenItem = screen.getByText('Test Token 1'); - await user.click(tokenItem); - - expect(mockOnSelect).toHaveBeenCalledWith(mockTokens[0]); - }); - - it('calls API with search term when searching', async () => { - const user = userEvent.setup(); - render(TokenSelectionModal, { - ...defaultProps, - onSelect: mockOnSelect - }); - - const button = screen.getByRole('button'); - await user.click(button); - - const searchInput = screen.getByPlaceholderText('Search tokens...'); - await user.type(searchInput, 'TEST'); - - await waitFor(() => { - expect(mockBuilder.getAllTokens).toHaveBeenCalledWith('TEST'); - }); - }); - - it('shows loading state while searching', async () => { - const mockBuilderWithDelay = { - getAllTokens: vi - .fn() - .mockImplementation( - () => new Promise((resolve) => setTimeout(() => resolve({ value: mockTokens }), 100)) - ) - } as unknown as RaindexOrderBuilder; - - (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilderWithDelay); - - const user = userEvent.setup(); - render(TokenSelectionModal, { - ...defaultProps, - onSelect: mockOnSelect - }); - - const button = screen.getByRole('button'); - await user.click(button); - - const searchInput = screen.getByPlaceholderText('Search tokens...'); - await user.type(searchInput, 'TEST'); - - expect(screen.getByText('Searching tokens...')).toBeInTheDocument(); - }); - - it('shows no results message when search returns empty', async () => { - const mockBuilderNoResults = { - getAllTokens: vi.fn().mockResolvedValue({ value: [] }) - } as unknown as RaindexOrderBuilder; - - (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilderNoResults); - - const user = userEvent.setup(); - render(TokenSelectionModal, { - ...defaultProps, - onSelect: mockOnSelect - }); - - const button = screen.getByRole('button'); - await user.click(button); - - await waitFor(() => { - expect(screen.getByText('No tokens found matching your search.')).toBeInTheDocument(); - }); - }); - - it('clears search when clear button is clicked', async () => { - const mockBuilderNoResults = { - getAllTokens: vi - .fn() - .mockResolvedValueOnce({ value: [] }) - .mockResolvedValueOnce({ value: mockTokens }) - } as unknown as RaindexOrderBuilder; - - (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilderNoResults); - - const user = userEvent.setup(); - render(TokenSelectionModal, { - ...defaultProps, - onSelect: mockOnSelect - }); - - const button = screen.getByRole('button'); - await user.click(button); - - await waitFor(() => { - expect(screen.getByText('No tokens found matching your search.')).toBeInTheDocument(); - }); - - const clearButton = screen.getByText('Clear search'); - await user.click(clearButton); - - await waitFor(() => { - expect(mockBuilderNoResults.getAllTokens).toHaveBeenCalledWith(undefined); - }); - }); - - it('automatically focuses search input when modal opens', async () => { - const user = userEvent.setup(); - render(TokenSelectionModal, { - ...defaultProps, - onSelect: mockOnSelect - }); - - const button = screen.getByRole('button'); - await user.click(button); - - await waitFor(() => { - const searchInput = screen.getByPlaceholderText('Search tokens...'); - expect(searchInput).toHaveFocus(); - }); - }); - - it('displays token logo image when logoUri is provided', async () => { - const user = userEvent.setup(); - render(TokenSelectionModal, { - ...defaultProps, - onSelect: mockOnSelect - }); - - const button = screen.getByRole('button'); - await user.click(button); - - await waitFor(() => { - const logoImage = screen.getByAltText('TEST1 logo'); - expect(logoImage).toBeInTheDocument(); - expect(logoImage).toHaveAttribute('src', 'https://example.com/token1-logo.png'); - }); - }); - - it('does not display logo image when logoUri is not provided', async () => { - const user = userEvent.setup(); - render(TokenSelectionModal, { - ...defaultProps, - onSelect: mockOnSelect - }); - - const button = screen.getByRole('button'); - await user.click(button); - - await waitFor(() => { - expect(screen.getByText('Another Token')).toBeInTheDocument(); - }); - - expect(screen.queryByAltText('ANOTHER logo')).not.toBeInTheDocument(); - }); - - it('displays symbol fallback for tokens without logo', async () => { - const user = userEvent.setup(); - render(TokenSelectionModal, { - ...defaultProps, - onSelect: mockOnSelect - }); - - const button = screen.getByRole('button'); - await user.click(button); - - await waitFor(() => { - expect(screen.getByText('AN')).toBeInTheDocument(); - }); - }); - - it('includes logoUri in token data when selecting a token with logo', async () => { - const user = userEvent.setup(); - render(TokenSelectionModal, { - ...defaultProps, - onSelect: mockOnSelect - }); - - const button = screen.getByRole('button'); - await user.click(button); - - await waitFor(() => { - expect(screen.getByText('Test Token 1')).toBeInTheDocument(); - }); - - const tokenItem = screen.getByText('Test Token 1'); - await user.click(tokenItem); - - expect(mockOnSelect).toHaveBeenCalledWith( - expect.objectContaining({ - logoUri: 'https://example.com/token1-logo.png' - }) - ); - }); - - it('falls back to symbol initials when image fails to load', async () => { - const user = userEvent.setup(); - render(TokenSelectionModal, { - ...defaultProps, - onSelect: mockOnSelect - }); - - const button = screen.getByRole('button'); - await user.click(button); - - await waitFor(() => { - expect(screen.getByAltText('TEST1 logo')).toBeInTheDocument(); - }); - - const logoImage = screen.getByAltText('TEST1 logo'); - logoImage.dispatchEvent(new Event('error')); - - await waitFor(() => { - expect(screen.queryByAltText('TEST1 logo')).not.toBeInTheDocument(); - expect(screen.getByText('TE')).toBeInTheDocument(); - }); - }); +describe("TokenSelectionModal", () => { + let mockOnSelect: ReturnType; + + const defaultProps: TokenSelectionModalProps = { + selectedToken: null, + onSelect: vi.fn(), + }; + + beforeEach(() => { + mockOnSelect = vi.fn(); + (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilder); + vi.clearAllMocks(); + }); + + it("renders modal button with default text when no token is selected", () => { + render(TokenSelectionModal, { + ...defaultProps, + onSelect: mockOnSelect, + }); + + expect(screen.getByText("Select a token...")).toBeInTheDocument(); + }); + + it("renders modal button with selected token info when token is selected", () => { + const selectedToken = mockTokens[0]; + render(TokenSelectionModal, { + ...defaultProps, + selectedToken, + onSelect: mockOnSelect, + }); + + expect(screen.getByText("Test Token 1 (TEST1)")).toBeInTheDocument(); + }); + + it("opens modal when button is clicked", async () => { + const user = userEvent.setup(); + render(TokenSelectionModal, { + ...defaultProps, + onSelect: mockOnSelect, + }); + + const button = screen.getByRole("button"); + await user.click(button); + + expect(screen.getByText("Select a token")).toBeInTheDocument(); + }); + + it("shows search input in modal", async () => { + const user = userEvent.setup(); + render(TokenSelectionModal, { + ...defaultProps, + onSelect: mockOnSelect, + }); + + const button = screen.getByRole("button"); + await user.click(button); + + expect(screen.getByPlaceholderText("Search tokens...")).toBeInTheDocument(); + }); + + it("loads tokens on mount", async () => { + render(TokenSelectionModal, { + ...defaultProps, + onSelect: mockOnSelect, + }); + + const button = screen.getByRole("button"); + await userEvent.click(button); + + await waitFor(() => { + expect(mockBuilder.getAllTokens).toHaveBeenCalledWith(undefined); + }); + }); + + it("shows tokens in modal after loading", async () => { + const user = userEvent.setup(); + render(TokenSelectionModal, { + ...defaultProps, + onSelect: mockOnSelect, + }); + + const button = screen.getByRole("button"); + await user.click(button); + + await waitFor(() => { + expect(screen.getByText("Test Token 1")).toBeInTheDocument(); + expect(screen.getByText("Another Token")).toBeInTheDocument(); + }); + }); + + it("calls onSelect when token is clicked", async () => { + const user = userEvent.setup(); + render(TokenSelectionModal, { + ...defaultProps, + onSelect: mockOnSelect, + }); + + const button = screen.getByRole("button"); + await user.click(button); + + await waitFor(() => { + expect(screen.getByText("Test Token 1")).toBeInTheDocument(); + }); + + const tokenItem = screen.getByText("Test Token 1"); + await user.click(tokenItem); + + expect(mockOnSelect).toHaveBeenCalledWith(mockTokens[0]); + }); + + it("calls API with search term when searching", async () => { + const user = userEvent.setup(); + render(TokenSelectionModal, { + ...defaultProps, + onSelect: mockOnSelect, + }); + + const button = screen.getByRole("button"); + await user.click(button); + + const searchInput = screen.getByPlaceholderText("Search tokens..."); + await user.type(searchInput, "TEST"); + + await waitFor(() => { + expect(mockBuilder.getAllTokens).toHaveBeenCalledWith("TEST"); + }); + }); + + it("shows loading state while searching", async () => { + const mockBuilderWithDelay = { + getAllTokens: vi + .fn() + .mockImplementation( + () => + new Promise((resolve) => + setTimeout(() => resolve({ value: mockTokens }), 100), + ), + ), + } as unknown as RaindexOrderBuilder; + + (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilderWithDelay); + + const user = userEvent.setup(); + render(TokenSelectionModal, { + ...defaultProps, + onSelect: mockOnSelect, + }); + + const button = screen.getByRole("button"); + await user.click(button); + + const searchInput = screen.getByPlaceholderText("Search tokens..."); + await user.type(searchInput, "TEST"); + + expect(screen.getByText("Searching tokens...")).toBeInTheDocument(); + }); + + it("shows no results message when search returns empty", async () => { + const mockBuilderNoResults = { + getAllTokens: vi.fn().mockResolvedValue({ value: [] }), + } as unknown as RaindexOrderBuilder; + + (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilderNoResults); + + const user = userEvent.setup(); + render(TokenSelectionModal, { + ...defaultProps, + onSelect: mockOnSelect, + }); + + const button = screen.getByRole("button"); + await user.click(button); + + await waitFor(() => { + expect( + screen.getByText("No tokens found matching your search."), + ).toBeInTheDocument(); + }); + }); + + it("clears search when clear button is clicked", async () => { + const mockBuilderNoResults = { + getAllTokens: vi + .fn() + .mockResolvedValueOnce({ value: [] }) + .mockResolvedValueOnce({ value: mockTokens }), + } as unknown as RaindexOrderBuilder; + + (useRaindexOrderBuilder as Mock).mockReturnValue(mockBuilderNoResults); + + const user = userEvent.setup(); + render(TokenSelectionModal, { + ...defaultProps, + onSelect: mockOnSelect, + }); + + const button = screen.getByRole("button"); + await user.click(button); + + await waitFor(() => { + expect( + screen.getByText("No tokens found matching your search."), + ).toBeInTheDocument(); + }); + + const clearButton = screen.getByText("Clear search"); + await user.click(clearButton); + + await waitFor(() => { + expect(mockBuilderNoResults.getAllTokens).toHaveBeenCalledWith(undefined); + }); + }); + + it("automatically focuses search input when modal opens", async () => { + const user = userEvent.setup(); + render(TokenSelectionModal, { + ...defaultProps, + onSelect: mockOnSelect, + }); + + const button = screen.getByRole("button"); + await user.click(button); + + await waitFor(() => { + const searchInput = screen.getByPlaceholderText("Search tokens..."); + expect(searchInput).toHaveFocus(); + }); + }); + + it("displays token logo image when logoUri is provided", async () => { + const user = userEvent.setup(); + render(TokenSelectionModal, { + ...defaultProps, + onSelect: mockOnSelect, + }); + + const button = screen.getByRole("button"); + await user.click(button); + + await waitFor(() => { + const logoImage = screen.getByAltText("TEST1 logo"); + expect(logoImage).toBeInTheDocument(); + expect(logoImage).toHaveAttribute( + "src", + "https://example.com/token1-logo.png", + ); + }); + }); + + it("does not display logo image when logoUri is not provided", async () => { + const user = userEvent.setup(); + render(TokenSelectionModal, { + ...defaultProps, + onSelect: mockOnSelect, + }); + + const button = screen.getByRole("button"); + await user.click(button); + + await waitFor(() => { + expect(screen.getByText("Another Token")).toBeInTheDocument(); + }); + + expect(screen.queryByAltText("ANOTHER logo")).not.toBeInTheDocument(); + }); + + it("displays symbol fallback for tokens without logo", async () => { + const user = userEvent.setup(); + render(TokenSelectionModal, { + ...defaultProps, + onSelect: mockOnSelect, + }); + + const button = screen.getByRole("button"); + await user.click(button); + + await waitFor(() => { + expect(screen.getByText("AN")).toBeInTheDocument(); + }); + }); + + it("includes logoUri in token data when selecting a token with logo", async () => { + const user = userEvent.setup(); + render(TokenSelectionModal, { + ...defaultProps, + onSelect: mockOnSelect, + }); + + const button = screen.getByRole("button"); + await user.click(button); + + await waitFor(() => { + expect(screen.getByText("Test Token 1")).toBeInTheDocument(); + }); + + const tokenItem = screen.getByText("Test Token 1"); + await user.click(tokenItem); + + expect(mockOnSelect).toHaveBeenCalledWith( + expect.objectContaining({ + logoUri: "https://example.com/token1-logo.png", + }), + ); + }); + + it("falls back to symbol initials when image fails to load", async () => { + const user = userEvent.setup(); + render(TokenSelectionModal, { + ...defaultProps, + onSelect: mockOnSelect, + }); + + const button = screen.getByRole("button"); + await user.click(button); + + await waitFor(() => { + expect(screen.getByAltText("TEST1 logo")).toBeInTheDocument(); + }); + + const logoImage = screen.getByAltText("TEST1 logo"); + logoImage.dispatchEvent(new Event("error")); + + await waitFor(() => { + expect(screen.queryByAltText("TEST1 logo")).not.toBeInTheDocument(); + expect(screen.getByText("TE")).toBeInTheDocument(); + }); + }); }); diff --git a/packages/ui-components/src/__tests__/Transaction.test.ts b/packages/ui-components/src/__tests__/Transaction.test.ts index 3773d0961d..08cd655614 100644 --- a/packages/ui-components/src/__tests__/Transaction.test.ts +++ b/packages/ui-components/src/__tests__/Transaction.test.ts @@ -1,373 +1,395 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import { TransactionStore } from '../lib/models/Transaction'; +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { TransactionStore } from "../lib/models/Transaction"; import { - TransactionStatusMessage, - TransactionStoreErrorMessage, - type TransactionArgs, - TransactionName, - type IndexingContext, - type AwaitIndexingFn -} from '../lib/types/transaction'; -import { waitForTransactionReceipt, type Config } from '@wagmi/core'; -import { get } from 'svelte/store'; -import type { Chain } from 'viem'; -import type { ToastLink } from '../lib/types/toast'; -import type { SgVault } from '@rainlanguage/raindex'; - -vi.mock('@wagmi/core', () => ({ - waitForTransactionReceipt: vi.fn() + TransactionStatusMessage, + TransactionStoreErrorMessage, + type TransactionArgs, + TransactionName, + type IndexingContext, + type AwaitIndexingFn, +} from "../lib/types/transaction"; +import { waitForTransactionReceipt, type Config } from "@wagmi/core"; +import { get } from "svelte/store"; +import type { Chain } from "viem"; +import type { ToastLink } from "../lib/types/toast"; +import type { SgVault } from "@rainlanguage/raindex"; + +vi.mock("@wagmi/core", () => ({ + waitForTransactionReceipt: vi.fn(), })); -describe('TransactionStore', () => { - const mockChain: Chain = { - id: 1, - name: 'Ethereum', - nativeCurrency: { - name: 'Ether', - symbol: 'ETH', - decimals: 18 - }, - rpcUrls: { - default: { http: ['https://eth.llamarpc.com'] }, - public: { http: ['https://eth.llamarpc.com'] } - }, - blockExplorers: { - default: { name: 'Etherscan', url: 'https://etherscan.io' } - } - }; - - const mockConfig = { - chains: [mockChain] as const, - connectors: [], - storage: { - getItem: vi.fn(), - setItem: vi.fn(), - removeItem: vi.fn(), - key: 'wagmi' - }, - state: { - connections: new Map(), - status: 'connected', - current: undefined - }, - setState: vi.fn(), - subscribe: vi.fn(), - destroy: vi.fn(), - getClient: vi.fn(), - _internal: {} - } as unknown as Config; - - const mockVault: SgVault = { - id: 'vault1', - vaultId: 'vault1', - token: { - id: 'token1', - address: '0xTokenAddress1', - name: 'Token1', - symbol: 'TKN1', - decimals: '18' - }, - owner: '0xOwnerAddress', - ordersAsInput: [], - ordersAsOutput: [], - balanceChanges: [], - balance: '1000000000000000000', - raindex: { - id: '0x00' - } - }; - - const mockChainId = 1; - const mockTxHash = '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'; - const mockOrderHash = '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890'; - const mockOnSuccess = vi.fn(); - const mockOnError = vi.fn(); - - const mockToastLinks: ToastLink[] = [ - { - link: 'https://etherscan.io/tx/test-tx', - label: 'View on Explorer' - } - ]; - - beforeEach(() => { - vi.clearAllMocks(); - }); - - describe('without awaitIndexingFn', () => { - it('should initialize with IDLE status and correct links', () => { - const transaction = new TransactionStore( - { - config: mockConfig, - chainId: mockChainId, - txHash: mockTxHash, - orderHash: mockOrderHash, - name: TransactionName.APPROVAL, - errorMessage: 'Transaction failed', - successMessage: 'Transaction successful', - queryKey: 'approval', - toastLinks: mockToastLinks, - entity: mockVault - } as TransactionArgs & { config: Config }, - mockOnSuccess, - mockOnError - ); - - const state = get(transaction.state); - expect(state.status).toBe(TransactionStatusMessage.IDLE); - expect(state.links).toEqual(mockToastLinks); - }); - - it('should mark SUCCESS immediately after receipt when no indexing function', async () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - vi.mocked(waitForTransactionReceipt).mockResolvedValue({} as any); - - const transaction = new TransactionStore( - { - config: mockConfig, - chainId: mockChainId, - txHash: mockTxHash, - name: TransactionName.APPROVAL, - errorMessage: 'Transaction failed', - successMessage: 'Transaction successful', - queryKey: 'approval', - toastLinks: mockToastLinks - } as TransactionArgs & { config: Config }, - mockOnSuccess, - mockOnError - ); - - await transaction.execute(); - - const state = get(transaction.state); - expect(state.status).toBe(TransactionStatusMessage.SUCCESS); - expect(mockOnSuccess).toHaveBeenCalled(); - expect(mockOnError).not.toHaveBeenCalled(); - }); - - it('should handle transaction receipt failure', async () => { - vi.mocked(waitForTransactionReceipt).mockRejectedValue(new Error('Transaction failed')); - - const transaction = new TransactionStore( - { - config: mockConfig, - chainId: mockChainId, - txHash: mockTxHash, - name: TransactionName.APPROVAL, - errorMessage: 'Transaction failed', - successMessage: 'Transaction successful', - queryKey: 'approval', - toastLinks: mockToastLinks - } as TransactionArgs & { config: Config }, - mockOnSuccess, - mockOnError - ); - - await transaction.execute(); - - const state = get(transaction.state); - expect(state.status).toBe(TransactionStatusMessage.ERROR); - expect(state.errorDetails).toBe(TransactionStoreErrorMessage.RECEIPT_FAILED); - expect(state.links).toEqual(mockToastLinks); - expect(mockOnError).toHaveBeenCalled(); - }); - }); - - describe('with awaitIndexingFn', () => { - it('should call awaitIndexingFn after receipt and handle success', async () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - vi.mocked(waitForTransactionReceipt).mockResolvedValue({} as any); - - const mockAwaitIndexingFn: AwaitIndexingFn = vi.fn(async (ctx: IndexingContext) => { - ctx.updateState({ status: TransactionStatusMessage.SUCCESS }); - ctx.onSuccess(); - }); - - const transaction = new TransactionStore( - { - config: mockConfig, - chainId: mockChainId, - txHash: mockTxHash, - name: TransactionName.REMOVAL, - errorMessage: 'Transaction failed', - successMessage: 'Transaction successful', - queryKey: 'removeOrder', - toastLinks: mockToastLinks, - awaitIndexingFn: mockAwaitIndexingFn - } as TransactionArgs & { config: Config }, - mockOnSuccess, - mockOnError - ); - - await transaction.execute(); - - expect(mockAwaitIndexingFn).toHaveBeenCalledWith( - expect.objectContaining({ - updateState: expect.any(Function), - onSuccess: mockOnSuccess, - onError: mockOnError, - links: mockToastLinks - }) - ); - - const state = get(transaction.state); - expect(state.status).toBe(TransactionStatusMessage.SUCCESS); - expect(mockOnSuccess).toHaveBeenCalled(); - }); - - it('should call awaitIndexingFn after receipt and handle error', async () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - vi.mocked(waitForTransactionReceipt).mockResolvedValue({} as any); - - const mockAwaitIndexingFn: AwaitIndexingFn = vi.fn(async (ctx: IndexingContext) => { - ctx.updateState({ - status: TransactionStatusMessage.ERROR, - errorDetails: TransactionStoreErrorMessage.SUBGRAPH_FAILED - }); - ctx.onError(); - }); - - const transaction = new TransactionStore( - { - config: mockConfig, - chainId: mockChainId, - txHash: mockTxHash, - name: TransactionName.REMOVAL, - errorMessage: 'Transaction failed', - successMessage: 'Transaction successful', - queryKey: 'removeOrder', - toastLinks: mockToastLinks, - awaitIndexingFn: mockAwaitIndexingFn - } as TransactionArgs & { config: Config }, - mockOnSuccess, - mockOnError - ); - - await transaction.execute(); - - const state = get(transaction.state); - expect(state.status).toBe(TransactionStatusMessage.ERROR); - expect(state.errorDetails).toBe(TransactionStoreErrorMessage.SUBGRAPH_FAILED); - expect(mockOnError).toHaveBeenCalled(); - }); - - it('should handle timeout error from indexing function', async () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - vi.mocked(waitForTransactionReceipt).mockResolvedValue({} as any); - - const mockAwaitIndexingFn: AwaitIndexingFn = vi.fn(async (ctx: IndexingContext) => { - ctx.updateState({ - status: TransactionStatusMessage.ERROR, - errorDetails: TransactionStoreErrorMessage.SUBGRAPH_TIMEOUT_ERROR - }); - ctx.onError(); - }); - - const transaction = new TransactionStore( - { - config: mockConfig, - chainId: mockChainId, - txHash: mockTxHash, - name: TransactionName.REMOVAL, - errorMessage: 'Transaction failed', - successMessage: 'Transaction successful', - queryKey: 'removeOrder', - toastLinks: mockToastLinks, - awaitIndexingFn: mockAwaitIndexingFn - } as TransactionArgs & { config: Config }, - mockOnSuccess, - mockOnError - ); - - await transaction.execute(); - - const state = get(transaction.state); - expect(state.status).toBe(TransactionStatusMessage.ERROR); - expect(state.errorDetails).toBe(TransactionStoreErrorMessage.SUBGRAPH_TIMEOUT_ERROR); - expect(mockOnError).toHaveBeenCalled(); - }); - - it('should allow indexing function to add links', async () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - vi.mocked(waitForTransactionReceipt).mockResolvedValue({} as any); - - const newOrderHash = '0xneworderhash123'; - const mockAwaitIndexingFn: AwaitIndexingFn = vi.fn(async (ctx: IndexingContext) => { - ctx.updateState({ status: TransactionStatusMessage.SUCCESS }); - // Add a "View order" link - const newLink = { - link: `/orders/1-0xraindex-${newOrderHash}`, - label: 'View order' - }; - ctx.updateState({ links: [newLink, ...ctx.links] }); - ctx.onSuccess(); - }); - - const transaction = new TransactionStore( - { - config: mockConfig, - chainId: mockChainId, - txHash: mockTxHash, - name: 'Deploying order', - errorMessage: 'Deployment failed', - successMessage: 'Order deployed successfully', - queryKey: 'addOrder', - toastLinks: mockToastLinks, - awaitIndexingFn: mockAwaitIndexingFn - } as TransactionArgs & { config: Config }, - mockOnSuccess, - mockOnError - ); - - await transaction.execute(); - - const state = get(transaction.state); - expect(state.status).toBe(TransactionStatusMessage.SUCCESS); - expect(state.links).toHaveLength(2); - expect(state.links[0]).toEqual({ - link: `/orders/1-0xraindex-${newOrderHash}`, - label: 'View order' - }); - expect(mockOnSuccess).toHaveBeenCalled(); - }); - - it('should update status to PENDING_SUBGRAPH when indexing function sets it', async () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - vi.mocked(waitForTransactionReceipt).mockResolvedValue({} as any); - - let capturedCtx: IndexingContext | null = null; - const mockAwaitIndexingFn: AwaitIndexingFn = vi.fn(async (ctx: IndexingContext) => { - capturedCtx = ctx; - ctx.updateState({ status: TransactionStatusMessage.PENDING_SUBGRAPH }); - // Simulate some async work - await new Promise((resolve) => setTimeout(resolve, 10)); - ctx.updateState({ status: TransactionStatusMessage.SUCCESS }); - ctx.onSuccess(); - }); - - const transaction = new TransactionStore( - { - config: mockConfig, - chainId: mockChainId, - txHash: mockTxHash, - name: TransactionName.DEPOSIT, - errorMessage: 'Deposit failed', - successMessage: 'Deposit successful', - queryKey: 'deposit', - toastLinks: mockToastLinks, - awaitIndexingFn: mockAwaitIndexingFn - } as TransactionArgs & { config: Config }, - mockOnSuccess, - mockOnError - ); - - await transaction.execute(); - - expect(capturedCtx).not.toBeNull(); - expect(mockOnSuccess).toHaveBeenCalled(); - - const state = get(transaction.state); - expect(state.status).toBe(TransactionStatusMessage.SUCCESS); - }); - }); +describe("TransactionStore", () => { + const mockChain: Chain = { + id: 1, + name: "Ethereum", + nativeCurrency: { + name: "Ether", + symbol: "ETH", + decimals: 18, + }, + rpcUrls: { + default: { http: ["https://eth.llamarpc.com"] }, + public: { http: ["https://eth.llamarpc.com"] }, + }, + blockExplorers: { + default: { name: "Etherscan", url: "https://etherscan.io" }, + }, + }; + + const mockConfig = { + chains: [mockChain] as const, + connectors: [], + storage: { + getItem: vi.fn(), + setItem: vi.fn(), + removeItem: vi.fn(), + key: "wagmi", + }, + state: { + connections: new Map(), + status: "connected", + current: undefined, + }, + setState: vi.fn(), + subscribe: vi.fn(), + destroy: vi.fn(), + getClient: vi.fn(), + _internal: {}, + } as unknown as Config; + + const mockVault: SgVault = { + id: "vault1", + vaultId: "vault1", + token: { + id: "token1", + address: "0xTokenAddress1", + name: "Token1", + symbol: "TKN1", + decimals: "18", + }, + owner: "0xOwnerAddress", + ordersAsInput: [], + ordersAsOutput: [], + balanceChanges: [], + balance: "1000000000000000000", + raindex: { + id: "0x00", + }, + }; + + const mockChainId = 1; + const mockTxHash = + "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; + const mockOrderHash = + "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"; + const mockOnSuccess = vi.fn(); + const mockOnError = vi.fn(); + + const mockToastLinks: ToastLink[] = [ + { + link: "https://etherscan.io/tx/test-tx", + label: "View on Explorer", + }, + ]; + + beforeEach(() => { + vi.clearAllMocks(); + }); + + describe("without awaitIndexingFn", () => { + it("should initialize with IDLE status and correct links", () => { + const transaction = new TransactionStore( + { + config: mockConfig, + chainId: mockChainId, + txHash: mockTxHash, + orderHash: mockOrderHash, + name: TransactionName.APPROVAL, + errorMessage: "Transaction failed", + successMessage: "Transaction successful", + queryKey: "approval", + toastLinks: mockToastLinks, + entity: mockVault, + } as TransactionArgs & { config: Config }, + mockOnSuccess, + mockOnError, + ); + + const state = get(transaction.state); + expect(state.status).toBe(TransactionStatusMessage.IDLE); + expect(state.links).toEqual(mockToastLinks); + }); + + it("should mark SUCCESS immediately after receipt when no indexing function", async () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + vi.mocked(waitForTransactionReceipt).mockResolvedValue({} as any); + + const transaction = new TransactionStore( + { + config: mockConfig, + chainId: mockChainId, + txHash: mockTxHash, + name: TransactionName.APPROVAL, + errorMessage: "Transaction failed", + successMessage: "Transaction successful", + queryKey: "approval", + toastLinks: mockToastLinks, + } as TransactionArgs & { config: Config }, + mockOnSuccess, + mockOnError, + ); + + await transaction.execute(); + + const state = get(transaction.state); + expect(state.status).toBe(TransactionStatusMessage.SUCCESS); + expect(mockOnSuccess).toHaveBeenCalled(); + expect(mockOnError).not.toHaveBeenCalled(); + }); + + it("should handle transaction receipt failure", async () => { + vi.mocked(waitForTransactionReceipt).mockRejectedValue( + new Error("Transaction failed"), + ); + + const transaction = new TransactionStore( + { + config: mockConfig, + chainId: mockChainId, + txHash: mockTxHash, + name: TransactionName.APPROVAL, + errorMessage: "Transaction failed", + successMessage: "Transaction successful", + queryKey: "approval", + toastLinks: mockToastLinks, + } as TransactionArgs & { config: Config }, + mockOnSuccess, + mockOnError, + ); + + await transaction.execute(); + + const state = get(transaction.state); + expect(state.status).toBe(TransactionStatusMessage.ERROR); + expect(state.errorDetails).toBe( + TransactionStoreErrorMessage.RECEIPT_FAILED, + ); + expect(state.links).toEqual(mockToastLinks); + expect(mockOnError).toHaveBeenCalled(); + }); + }); + + describe("with awaitIndexingFn", () => { + it("should call awaitIndexingFn after receipt and handle success", async () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + vi.mocked(waitForTransactionReceipt).mockResolvedValue({} as any); + + const mockAwaitIndexingFn: AwaitIndexingFn = vi.fn( + async (ctx: IndexingContext) => { + ctx.updateState({ status: TransactionStatusMessage.SUCCESS }); + ctx.onSuccess(); + }, + ); + + const transaction = new TransactionStore( + { + config: mockConfig, + chainId: mockChainId, + txHash: mockTxHash, + name: TransactionName.REMOVAL, + errorMessage: "Transaction failed", + successMessage: "Transaction successful", + queryKey: "removeOrder", + toastLinks: mockToastLinks, + awaitIndexingFn: mockAwaitIndexingFn, + } as TransactionArgs & { config: Config }, + mockOnSuccess, + mockOnError, + ); + + await transaction.execute(); + + expect(mockAwaitIndexingFn).toHaveBeenCalledWith( + expect.objectContaining({ + updateState: expect.any(Function), + onSuccess: mockOnSuccess, + onError: mockOnError, + links: mockToastLinks, + }), + ); + + const state = get(transaction.state); + expect(state.status).toBe(TransactionStatusMessage.SUCCESS); + expect(mockOnSuccess).toHaveBeenCalled(); + }); + + it("should call awaitIndexingFn after receipt and handle error", async () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + vi.mocked(waitForTransactionReceipt).mockResolvedValue({} as any); + + const mockAwaitIndexingFn: AwaitIndexingFn = vi.fn( + async (ctx: IndexingContext) => { + ctx.updateState({ + status: TransactionStatusMessage.ERROR, + errorDetails: TransactionStoreErrorMessage.SUBGRAPH_FAILED, + }); + ctx.onError(); + }, + ); + + const transaction = new TransactionStore( + { + config: mockConfig, + chainId: mockChainId, + txHash: mockTxHash, + name: TransactionName.REMOVAL, + errorMessage: "Transaction failed", + successMessage: "Transaction successful", + queryKey: "removeOrder", + toastLinks: mockToastLinks, + awaitIndexingFn: mockAwaitIndexingFn, + } as TransactionArgs & { config: Config }, + mockOnSuccess, + mockOnError, + ); + + await transaction.execute(); + + const state = get(transaction.state); + expect(state.status).toBe(TransactionStatusMessage.ERROR); + expect(state.errorDetails).toBe( + TransactionStoreErrorMessage.SUBGRAPH_FAILED, + ); + expect(mockOnError).toHaveBeenCalled(); + }); + + it("should handle timeout error from indexing function", async () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + vi.mocked(waitForTransactionReceipt).mockResolvedValue({} as any); + + const mockAwaitIndexingFn: AwaitIndexingFn = vi.fn( + async (ctx: IndexingContext) => { + ctx.updateState({ + status: TransactionStatusMessage.ERROR, + errorDetails: TransactionStoreErrorMessage.SUBGRAPH_TIMEOUT_ERROR, + }); + ctx.onError(); + }, + ); + + const transaction = new TransactionStore( + { + config: mockConfig, + chainId: mockChainId, + txHash: mockTxHash, + name: TransactionName.REMOVAL, + errorMessage: "Transaction failed", + successMessage: "Transaction successful", + queryKey: "removeOrder", + toastLinks: mockToastLinks, + awaitIndexingFn: mockAwaitIndexingFn, + } as TransactionArgs & { config: Config }, + mockOnSuccess, + mockOnError, + ); + + await transaction.execute(); + + const state = get(transaction.state); + expect(state.status).toBe(TransactionStatusMessage.ERROR); + expect(state.errorDetails).toBe( + TransactionStoreErrorMessage.SUBGRAPH_TIMEOUT_ERROR, + ); + expect(mockOnError).toHaveBeenCalled(); + }); + + it("should allow indexing function to add links", async () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + vi.mocked(waitForTransactionReceipt).mockResolvedValue({} as any); + + const newOrderHash = "0xneworderhash123"; + const mockAwaitIndexingFn: AwaitIndexingFn = vi.fn( + async (ctx: IndexingContext) => { + ctx.updateState({ status: TransactionStatusMessage.SUCCESS }); + // Add a "View order" link + const newLink = { + link: `/orders/1-0xraindex-${newOrderHash}`, + label: "View order", + }; + ctx.updateState({ links: [newLink, ...ctx.links] }); + ctx.onSuccess(); + }, + ); + + const transaction = new TransactionStore( + { + config: mockConfig, + chainId: mockChainId, + txHash: mockTxHash, + name: "Deploying order", + errorMessage: "Deployment failed", + successMessage: "Order deployed successfully", + queryKey: "addOrder", + toastLinks: mockToastLinks, + awaitIndexingFn: mockAwaitIndexingFn, + } as TransactionArgs & { config: Config }, + mockOnSuccess, + mockOnError, + ); + + await transaction.execute(); + + const state = get(transaction.state); + expect(state.status).toBe(TransactionStatusMessage.SUCCESS); + expect(state.links).toHaveLength(2); + expect(state.links[0]).toEqual({ + link: `/orders/1-0xraindex-${newOrderHash}`, + label: "View order", + }); + expect(mockOnSuccess).toHaveBeenCalled(); + }); + + it("should update status to PENDING_SUBGRAPH when indexing function sets it", async () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + vi.mocked(waitForTransactionReceipt).mockResolvedValue({} as any); + + let capturedCtx: IndexingContext | null = null; + const mockAwaitIndexingFn: AwaitIndexingFn = vi.fn( + async (ctx: IndexingContext) => { + capturedCtx = ctx; + ctx.updateState({ + status: TransactionStatusMessage.PENDING_SUBGRAPH, + }); + // Simulate some async work + await new Promise((resolve) => setTimeout(resolve, 10)); + ctx.updateState({ status: TransactionStatusMessage.SUCCESS }); + ctx.onSuccess(); + }, + ); + + const transaction = new TransactionStore( + { + config: mockConfig, + chainId: mockChainId, + txHash: mockTxHash, + name: TransactionName.DEPOSIT, + errorMessage: "Deposit failed", + successMessage: "Deposit successful", + queryKey: "deposit", + toastLinks: mockToastLinks, + awaitIndexingFn: mockAwaitIndexingFn, + } as TransactionArgs & { config: Config }, + mockOnSuccess, + mockOnError, + ); + + await transaction.execute(); + + expect(capturedCtx).not.toBeNull(); + expect(mockOnSuccess).toHaveBeenCalled(); + + const state = get(transaction.state); + expect(state.status).toBe(TransactionStatusMessage.SUCCESS); + }); + }); }); diff --git a/packages/ui-components/src/__tests__/TransactionDetail.test.ts b/packages/ui-components/src/__tests__/TransactionDetail.test.ts index 5087c4f724..984cc41a46 100644 --- a/packages/ui-components/src/__tests__/TransactionDetail.test.ts +++ b/packages/ui-components/src/__tests__/TransactionDetail.test.ts @@ -1,130 +1,144 @@ -import { describe, it, expect } from 'vitest'; -import { render, screen, waitFor } from '@testing-library/svelte'; -import TransactionDetail from '../lib/components/transactions/TransactionDetail.svelte'; -import { writable } from 'svelte/store'; -import type { TransactionStoreState } from '../lib/models/Transaction'; +import { describe, it, expect } from "vitest"; +import { render, screen, waitFor } from "@testing-library/svelte"; +import TransactionDetail from "../lib/components/transactions/TransactionDetail.svelte"; +import { writable } from "svelte/store"; +import type { TransactionStoreState } from "../lib/models/Transaction"; import { - TransactionName, - TransactionStatusMessage, - TransactionStoreErrorMessage -} from '../lib/types/transaction'; - -describe('TransactionDetail', () => { - it('should render different status emojis for different states', () => { - const statuses = [ - { status: TransactionStatusMessage.PENDING_RECEIPT, emoji: 'šŸ”„' }, - { status: TransactionStatusMessage.PENDING_SUBGRAPH, emoji: 'šŸ“Š' }, - { status: TransactionStatusMessage.SUCCESS, emoji: 'āœ…' }, - { status: TransactionStatusMessage.ERROR, emoji: 'āŒ' } - ] as const; - - statuses.forEach(({ status, emoji }) => { - const state = writable({ - name: TransactionName.REMOVAL, - status, - links: [] - }); - - const { container } = render(TransactionDetail, { state }); - expect(container.textContent).toContain(emoji); - }); - }); - - it('should render links from the links array', () => { - const mockLinks = [ - { - label: 'View on Explorer 1', - link: 'https://etherscan.io/tx/0xlink1' - }, - { - label: 'View on Explorer 2', - link: 'https://polygonscan.com/tx/0xlink2' - } - ]; - const state = writable({ - name: TransactionName.REMOVAL, - status: TransactionStatusMessage.PENDING_RECEIPT, - links: mockLinks - }); - - render(TransactionDetail, { state }); - - mockLinks.forEach((mockLink) => { - const linkElement = screen.getByRole('link', { name: mockLink.label }); - expect(linkElement).toBeInTheDocument(); - expect(linkElement).toHaveAttribute('href', mockLink.link); - expect(linkElement).toHaveAttribute('target', '_blank'); - expect(linkElement).toHaveAttribute('rel', 'noopener noreferrer'); - }); - }); - - it('should render no links if the links array is empty', () => { - const state = writable({ - name: TransactionName.REMOVAL, - status: TransactionStatusMessage.PENDING_RECEIPT, - links: [] - }); - - render(TransactionDetail, { state }); - - const linkElements = screen.queryAllByRole('link'); - expect(linkElements.length).toBe(0); - }); - - it('should update when the state changes', async () => { - const state = writable({ - name: TransactionName.REMOVAL, - status: TransactionStatusMessage.PENDING_RECEIPT, - links: [{ label: 'Initial Link', link: 'https://example.com/initial' }] - }); - - render(TransactionDetail, { state }); - - expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); - expect(screen.getByText(`šŸ”„ ${TransactionStatusMessage.PENDING_RECEIPT}`)).toBeInTheDocument(); - expect(screen.getByRole('link', { name: 'Initial Link' })).toBeInTheDocument(); - - state.update((current) => ({ - ...current, - status: TransactionStatusMessage.PENDING_SUBGRAPH, - links: [{ label: 'Updated Link', link: 'https://example.com/updated' }] - })); - - await waitFor(() => { - expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); - expect( - screen.getByText(`šŸ“Š ${TransactionStatusMessage.PENDING_SUBGRAPH}`) - ).toBeInTheDocument(); - expect(screen.queryByRole('link', { name: 'Initial Link' })).not.toBeInTheDocument(); - expect(screen.getByRole('link', { name: 'Updated Link' })).toBeInTheDocument(); - }); - - state.update((current) => ({ - ...current, - status: TransactionStatusMessage.SUCCESS, - links: [] - })); - - await waitFor(() => { - expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); - expect(screen.getByText(`āœ… ${TransactionStatusMessage.SUCCESS}`)).toBeInTheDocument(); - expect(screen.queryByRole('link', { name: 'Updated Link' })).not.toBeInTheDocument(); - }); - }); - - it('should handle error status with errorDetails if provided', () => { - const errorDetails = 'Something went terribly wrong.'; - const state = writable({ - status: TransactionStatusMessage.ERROR, - name: TransactionName.REMOVAL, - links: [], - errorDetails: errorDetails as TransactionStoreErrorMessage - }); - - render(TransactionDetail, { state }); - - expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); - expect(screen.getByText(`āŒ ${TransactionStatusMessage.ERROR}`)).toBeInTheDocument(); - expect(screen.getByText(errorDetails)).toBeInTheDocument(); - }); + TransactionName, + TransactionStatusMessage, + TransactionStoreErrorMessage, +} from "../lib/types/transaction"; + +describe("TransactionDetail", () => { + it("should render different status emojis for different states", () => { + const statuses = [ + { status: TransactionStatusMessage.PENDING_RECEIPT, emoji: "šŸ”„" }, + { status: TransactionStatusMessage.PENDING_SUBGRAPH, emoji: "šŸ“Š" }, + { status: TransactionStatusMessage.SUCCESS, emoji: "āœ…" }, + { status: TransactionStatusMessage.ERROR, emoji: "āŒ" }, + ] as const; + + statuses.forEach(({ status, emoji }) => { + const state = writable({ + name: TransactionName.REMOVAL, + status, + links: [], + }); + + const { container } = render(TransactionDetail, { state }); + expect(container.textContent).toContain(emoji); + }); + }); + + it("should render links from the links array", () => { + const mockLinks = [ + { + label: "View on Explorer 1", + link: "https://etherscan.io/tx/0xlink1", + }, + { + label: "View on Explorer 2", + link: "https://polygonscan.com/tx/0xlink2", + }, + ]; + const state = writable({ + name: TransactionName.REMOVAL, + status: TransactionStatusMessage.PENDING_RECEIPT, + links: mockLinks, + }); + + render(TransactionDetail, { state }); + + mockLinks.forEach((mockLink) => { + const linkElement = screen.getByRole("link", { name: mockLink.label }); + expect(linkElement).toBeInTheDocument(); + expect(linkElement).toHaveAttribute("href", mockLink.link); + expect(linkElement).toHaveAttribute("target", "_blank"); + expect(linkElement).toHaveAttribute("rel", "noopener noreferrer"); + }); + }); + + it("should render no links if the links array is empty", () => { + const state = writable({ + name: TransactionName.REMOVAL, + status: TransactionStatusMessage.PENDING_RECEIPT, + links: [], + }); + + render(TransactionDetail, { state }); + + const linkElements = screen.queryAllByRole("link"); + expect(linkElements.length).toBe(0); + }); + + it("should update when the state changes", async () => { + const state = writable({ + name: TransactionName.REMOVAL, + status: TransactionStatusMessage.PENDING_RECEIPT, + links: [{ label: "Initial Link", link: "https://example.com/initial" }], + }); + + render(TransactionDetail, { state }); + + expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); + expect( + screen.getByText(`šŸ”„ ${TransactionStatusMessage.PENDING_RECEIPT}`), + ).toBeInTheDocument(); + expect( + screen.getByRole("link", { name: "Initial Link" }), + ).toBeInTheDocument(); + + state.update((current) => ({ + ...current, + status: TransactionStatusMessage.PENDING_SUBGRAPH, + links: [{ label: "Updated Link", link: "https://example.com/updated" }], + })); + + await waitFor(() => { + expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); + expect( + screen.getByText(`šŸ“Š ${TransactionStatusMessage.PENDING_SUBGRAPH}`), + ).toBeInTheDocument(); + expect( + screen.queryByRole("link", { name: "Initial Link" }), + ).not.toBeInTheDocument(); + expect( + screen.getByRole("link", { name: "Updated Link" }), + ).toBeInTheDocument(); + }); + + state.update((current) => ({ + ...current, + status: TransactionStatusMessage.SUCCESS, + links: [], + })); + + await waitFor(() => { + expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); + expect( + screen.getByText(`āœ… ${TransactionStatusMessage.SUCCESS}`), + ).toBeInTheDocument(); + expect( + screen.queryByRole("link", { name: "Updated Link" }), + ).not.toBeInTheDocument(); + }); + }); + + it("should handle error status with errorDetails if provided", () => { + const errorDetails = "Something went terribly wrong."; + const state = writable({ + status: TransactionStatusMessage.ERROR, + name: TransactionName.REMOVAL, + links: [], + errorDetails: errorDetails as TransactionStoreErrorMessage, + }); + + render(TransactionDetail, { state }); + + expect(screen.getByText(TransactionName.REMOVAL)).toBeInTheDocument(); + expect( + screen.getByText(`āŒ ${TransactionStatusMessage.ERROR}`), + ).toBeInTheDocument(); + expect(screen.getByText(errorDetails)).toBeInTheDocument(); + }); }); diff --git a/packages/ui-components/src/__tests__/TransactionList.test.ts b/packages/ui-components/src/__tests__/TransactionList.test.ts index bde9354659..b90f758654 100644 --- a/packages/ui-components/src/__tests__/TransactionList.test.ts +++ b/packages/ui-components/src/__tests__/TransactionList.test.ts @@ -1,208 +1,220 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import { render, screen, waitFor } from '@testing-library/svelte'; -import TransactionList from '../lib/components/transactions/TransactionList.svelte'; -import { TransactionManager } from '../lib/providers/transactions/TransactionManager'; -import { writable } from 'svelte/store'; -import type { Transaction, TransactionStoreState } from '../lib/models/Transaction'; -import { TransactionStatusMessage, TransactionName } from '../lib/types/transaction'; -import { useTransactions } from '../lib/providers/transactions/useTransactions'; - -vi.mock('$lib/components/transaction/TransactionDetail.svelte', async () => { - const mockTransactionDetail = (await import('../lib/__mocks__/MockComponent.svelte')).default; - return { default: mockTransactionDetail }; +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { render, screen, waitFor } from "@testing-library/svelte"; +import TransactionList from "../lib/components/transactions/TransactionList.svelte"; +import { TransactionManager } from "../lib/providers/transactions/TransactionManager"; +import { writable } from "svelte/store"; +import type { + Transaction, + TransactionStoreState, +} from "../lib/models/Transaction"; +import { + TransactionStatusMessage, + TransactionName, +} from "../lib/types/transaction"; +import { useTransactions } from "../lib/providers/transactions/useTransactions"; + +vi.mock("$lib/components/transaction/TransactionDetail.svelte", async () => { + const mockTransactionDetail = ( + await import("../lib/__mocks__/MockComponent.svelte") + ).default; + return { default: mockTransactionDetail }; }); -vi.mock('../lib/providers/transactions/useTransactions', () => ({ - useTransactions: vi.fn() +vi.mock("../lib/providers/transactions/useTransactions", () => ({ + useTransactions: vi.fn(), })); -describe('TransactionList', () => { - let mockTransactionManager: TransactionManager; - let mockTransactionsStore: ReturnType>; - - beforeEach(() => { - vi.clearAllMocks(); - - mockTransactionsStore = writable([]); - - mockTransactionManager = { - transactions: vi.fn().mockReturnValue(mockTransactionsStore) - } as unknown as TransactionManager; - - vi.mocked(useTransactions).mockReturnValue({ - manager: mockTransactionManager, - transactions: mockTransactionsStore - }); - }); - - it('should not render anything when there are no transactions', () => { - const { container } = render(TransactionList); - expect(container.innerHTML).toBe(''); - }); - - it('should render a list of transactions when transactions exist', () => { - const mockTransactions = [ - { - state: writable({ - status: TransactionStatusMessage.IDLE, - name: TransactionName.REMOVAL, - links: [ - { - label: 'View on Explorer', - link: 'https://etherscan.io/tx/0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef' - } - ] - }) - }, - { - state: writable({ - status: TransactionStatusMessage.SUCCESS, - name: TransactionName.REMOVAL, - links: [ - { - label: 'View on Explorer', - link: 'https://etherscan.io/tx/0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890' - } - ] - }) - } - ] as unknown as Transaction[]; - - mockTransactionsStore.set(mockTransactions); - - const { container } = render(TransactionList); - - const listContainer = container.querySelector('[data-testid="transaction-list"]'); - expect(listContainer).toBeInTheDocument(); - expect(listContainer).toHaveClass('h-full', 'overflow-y-auto'); - - const list = screen.getByRole('list'); - expect(list).toBeInTheDocument(); - expect(list.children).toHaveLength(2); - }); - - it('should update when transactions change', async () => { - const { container } = render(TransactionList); - - expect(container.innerHTML).toBe(''); - - mockTransactionsStore.set([ - { - state: writable({ - status: TransactionStatusMessage.IDLE, - name: TransactionName.REMOVAL, - links: [ - { - label: 'View on Explorer', - link: 'https://etherscan.io/tx/0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef' - } - ] - }) - } - ] as unknown as Transaction[]); - - await waitFor(() => { - expect(screen.getByRole('list')).toBeInTheDocument(); - expect(screen.getByRole('list').children).toHaveLength(1); - }); - - mockTransactionsStore.set([]); - - await waitFor(() => { - expect(container.innerHTML).toBe(''); - }); - }); - - it('should get transactions from the manager', () => { - render(TransactionList); - expect(useTransactions).toHaveBeenCalled(); - }); - - it('should render transactions in reverse order (newest to oldest)', () => { - const mockTransactions = [ - { - state: writable({ - status: TransactionStatusMessage.IDLE, - name: TransactionName.REMOVAL, - links: [ - { - label: 'View on Explorer', - link: 'https://etherscan.io/tx/0x1111111111111111111111111111111111111111111111111111111111111111' - } - ] - }) - }, - { - state: writable({ - status: TransactionStatusMessage.SUCCESS, - name: TransactionName.REMOVAL, - links: [ - { - label: 'View on Explorer', - link: 'https://etherscan.io/tx/0x2222222222222222222222222222222222222222222222222222222222222222' - } - ] - }) - }, - { - state: writable({ - status: TransactionStatusMessage.PENDING_APPROVAL, - name: TransactionName.REMOVAL, - links: [ - { - label: 'View on Explorer', - link: 'https://etherscan.io/tx/0x3333333333333333333333333333333333333333333333333333333333333333' - } - ] - }) - } - ] as unknown as Transaction[]; - - mockTransactionsStore.set(mockTransactions); - - const { container } = render(TransactionList); - - const listItems = container.querySelectorAll('li'); - expect(listItems).toHaveLength(3); - - // Check that the order is reversed - the last item in the array should be first in the list - const firstItemContent = listItems[0].textContent; - const secondItemContent = listItems[1].textContent; - const thirdItemContent = listItems[2].textContent; - - // Since we're using a mock component, we need to check the rendered content - // The mock component should render in reverse order - expect(firstItemContent).toBeTruthy(); - expect(secondItemContent).toBeTruthy(); - expect(thirdItemContent).toBeTruthy(); - }); - - it('should have a scrollable container for transactions', () => { - const mockTransactions = Array(10) - .fill(null) - .map((_, index) => ({ - state: writable({ - status: TransactionStatusMessage.SUCCESS, - name: TransactionName.REMOVAL, - links: [ - { - label: 'View on Explorer', - link: `https://etherscan.io/tx/0x${index.toString().padStart(64, '0')}` - } - ] - }) - })) as unknown as Transaction[]; - - mockTransactionsStore.set(mockTransactions); - - const { container } = render(TransactionList); - - const listContainer = container.querySelector('[data-testid="transaction-list"]'); - expect(listContainer).toBeInTheDocument(); - expect(listContainer).toHaveClass('h-full', 'overflow-y-auto'); - - const list = screen.getByRole('list'); - expect(list).toBeInTheDocument(); - expect(list.children).toHaveLength(10); - }); +describe("TransactionList", () => { + let mockTransactionManager: TransactionManager; + let mockTransactionsStore: ReturnType>; + + beforeEach(() => { + vi.clearAllMocks(); + + mockTransactionsStore = writable([]); + + mockTransactionManager = { + transactions: vi.fn().mockReturnValue(mockTransactionsStore), + } as unknown as TransactionManager; + + vi.mocked(useTransactions).mockReturnValue({ + manager: mockTransactionManager, + transactions: mockTransactionsStore, + }); + }); + + it("should not render anything when there are no transactions", () => { + const { container } = render(TransactionList); + expect(container.innerHTML).toBe(""); + }); + + it("should render a list of transactions when transactions exist", () => { + const mockTransactions = [ + { + state: writable({ + status: TransactionStatusMessage.IDLE, + name: TransactionName.REMOVAL, + links: [ + { + label: "View on Explorer", + link: "https://etherscan.io/tx/0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + }, + ], + }), + }, + { + state: writable({ + status: TransactionStatusMessage.SUCCESS, + name: TransactionName.REMOVAL, + links: [ + { + label: "View on Explorer", + link: "https://etherscan.io/tx/0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890", + }, + ], + }), + }, + ] as unknown as Transaction[]; + + mockTransactionsStore.set(mockTransactions); + + const { container } = render(TransactionList); + + const listContainer = container.querySelector( + '[data-testid="transaction-list"]', + ); + expect(listContainer).toBeInTheDocument(); + expect(listContainer).toHaveClass("h-full", "overflow-y-auto"); + + const list = screen.getByRole("list"); + expect(list).toBeInTheDocument(); + expect(list.children).toHaveLength(2); + }); + + it("should update when transactions change", async () => { + const { container } = render(TransactionList); + + expect(container.innerHTML).toBe(""); + + mockTransactionsStore.set([ + { + state: writable({ + status: TransactionStatusMessage.IDLE, + name: TransactionName.REMOVAL, + links: [ + { + label: "View on Explorer", + link: "https://etherscan.io/tx/0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + }, + ], + }), + }, + ] as unknown as Transaction[]); + + await waitFor(() => { + expect(screen.getByRole("list")).toBeInTheDocument(); + expect(screen.getByRole("list").children).toHaveLength(1); + }); + + mockTransactionsStore.set([]); + + await waitFor(() => { + expect(container.innerHTML).toBe(""); + }); + }); + + it("should get transactions from the manager", () => { + render(TransactionList); + expect(useTransactions).toHaveBeenCalled(); + }); + + it("should render transactions in reverse order (newest to oldest)", () => { + const mockTransactions = [ + { + state: writable({ + status: TransactionStatusMessage.IDLE, + name: TransactionName.REMOVAL, + links: [ + { + label: "View on Explorer", + link: "https://etherscan.io/tx/0x1111111111111111111111111111111111111111111111111111111111111111", + }, + ], + }), + }, + { + state: writable({ + status: TransactionStatusMessage.SUCCESS, + name: TransactionName.REMOVAL, + links: [ + { + label: "View on Explorer", + link: "https://etherscan.io/tx/0x2222222222222222222222222222222222222222222222222222222222222222", + }, + ], + }), + }, + { + state: writable({ + status: TransactionStatusMessage.PENDING_APPROVAL, + name: TransactionName.REMOVAL, + links: [ + { + label: "View on Explorer", + link: "https://etherscan.io/tx/0x3333333333333333333333333333333333333333333333333333333333333333", + }, + ], + }), + }, + ] as unknown as Transaction[]; + + mockTransactionsStore.set(mockTransactions); + + const { container } = render(TransactionList); + + const listItems = container.querySelectorAll("li"); + expect(listItems).toHaveLength(3); + + // Check that the order is reversed - the last item in the array should be first in the list + const firstItemContent = listItems[0].textContent; + const secondItemContent = listItems[1].textContent; + const thirdItemContent = listItems[2].textContent; + + // Since we're using a mock component, we need to check the rendered content + // The mock component should render in reverse order + expect(firstItemContent).toBeTruthy(); + expect(secondItemContent).toBeTruthy(); + expect(thirdItemContent).toBeTruthy(); + }); + + it("should have a scrollable container for transactions", () => { + const mockTransactions = Array(10) + .fill(null) + .map((_, index) => ({ + state: writable({ + status: TransactionStatusMessage.SUCCESS, + name: TransactionName.REMOVAL, + links: [ + { + label: "View on Explorer", + link: `https://etherscan.io/tx/0x${index.toString().padStart(64, "0")}`, + }, + ], + }), + })) as unknown as Transaction[]; + + mockTransactionsStore.set(mockTransactions); + + const { container } = render(TransactionList); + + const listContainer = container.querySelector( + '[data-testid="transaction-list"]', + ); + expect(listContainer).toBeInTheDocument(); + expect(listContainer).toHaveClass("h-full", "overflow-y-auto"); + + const list = screen.getByRole("list"); + expect(list).toBeInTheDocument(); + expect(list.children).toHaveLength(10); + }); }); diff --git a/packages/ui-components/src/__tests__/TransactionManager.test.ts b/packages/ui-components/src/__tests__/TransactionManager.test.ts index 39253521de..ff293a494f 100644 --- a/packages/ui-components/src/__tests__/TransactionManager.test.ts +++ b/packages/ui-components/src/__tests__/TransactionManager.test.ts @@ -1,1403 +1,1447 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { describe, it, expect, vi, beforeEach } from "vitest"; import { - TransactionManager, - createSdkIndexingFn -} from '../lib/providers/transactions/TransactionManager'; -import { TransactionStore } from '../lib/models/Transaction'; -import type { QueryClient } from '@tanstack/svelte-query'; -import type { Config } from '@wagmi/core'; -import type { ToastProps } from '../lib/types/toast'; + TransactionManager, + createSdkIndexingFn, +} from "../lib/providers/transactions/TransactionManager"; +import { TransactionStore } from "../lib/models/Transaction"; +import type { QueryClient } from "@tanstack/svelte-query"; +import type { Config } from "@wagmi/core"; +import type { ToastProps } from "../lib/types/toast"; import { - TransactionName, - TransactionStatusMessage, - TransactionStoreErrorMessage, - type InternalTransactionArgs, - type IndexingContext -} from '../lib/types/transaction'; -import { getExplorerLink } from '../lib/services/getExplorerLink'; + TransactionName, + TransactionStatusMessage, + TransactionStoreErrorMessage, + type InternalTransactionArgs, + type IndexingContext, +} from "../lib/types/transaction"; +import { getExplorerLink } from "../lib/services/getExplorerLink"; import { - Float, - RaindexClient, - RaindexOrder, - RaindexVault, - type Address, - type WasmEncodedResult -} from '@rainlanguage/raindex'; - -vi.mock('../lib/models/Transaction', () => ({ - TransactionStore: vi.fn() + Float, + RaindexClient, + RaindexOrder, + RaindexVault, + type Address, + type WasmEncodedResult, +} from "@rainlanguage/raindex"; + +vi.mock("../lib/models/Transaction", () => ({ + TransactionStore: vi.fn(), })); -vi.mock('../lib/services/getExplorerLink', () => ({ - getExplorerLink: vi.fn() +vi.mock("../lib/services/getExplorerLink", () => ({ + getExplorerLink: vi.fn(), })); -vi.mock('@rainlanguage/raindex', async (importOriginal) => ({ - ...(await importOriginal()), - getTransactionRemoveOrders: vi.fn(), - getTransaction: vi.fn(), - getTransactionAddOrders: vi.fn() +vi.mock("@rainlanguage/raindex", async (importOriginal) => ({ + ...(await importOriginal()), + getTransactionRemoveOrders: vi.fn(), + getTransaction: vi.fn(), + getTransactionAddOrders: vi.fn(), })); -describe('TransactionManager', () => { - let mockQueryClient: QueryClient; - let mockAddToast: (toast: Omit) => void; - let mockWagmiConfig: Config; - let manager: TransactionManager; - - const mockRaindexClient = { - getRemoveOrdersForTransaction: vi.fn(), - getTransaction: vi.fn(), - getAddOrdersForTransaction: vi.fn() - } as unknown as RaindexClient; - - const mockSgOrderEntity = { - id: 'mockOrderEntityId', - raindex: 'mockRaindex', - getRemoveOrdersForTransaction: vi.fn() - } as unknown as RaindexOrder; - - const mockSgVaultEntity = { - token: { symbol: 'MOCKVAULT', decimals: '18' }, - vaultId: 'mockVaultEntityId', - id: 'mockVaultEntityId' - } as unknown as RaindexVault; - - const mockBaseArgs: InternalTransactionArgs = { - txHash: '0xcallbacktxhash' as `0x${string}`, - chainId: 1, - queryKey: '0xcallbackkey' - }; - - beforeEach(() => { - vi.clearAllMocks(); - - mockQueryClient = { - invalidateQueries: vi.fn() - } as unknown as QueryClient; - - mockAddToast = vi.fn(); - - mockWagmiConfig = {} as Config; - manager = new TransactionManager(mockQueryClient, mockAddToast, mockWagmiConfig); - }); - - describe('initialization', () => { - it('should initialize with empty transactions store', () => { - const transactions = manager.getTransactions(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let storeValue: any[] = []; - transactions.subscribe((value) => { - storeValue = value; - }); - expect(storeValue).toEqual([]); - }); - }); - - describe('createRemoveOrderTransaction', () => { - const removeOrderMockArgs: InternalTransactionArgs & { - raindexClient: RaindexClient; - entity: RaindexOrder; - } = { - txHash: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef' as `0x${string}`, - chainId: 1, - queryKey: '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890', - entity: mockSgOrderEntity, - raindexClient: mockRaindexClient - }; - - beforeEach(() => { - vi.mocked(getExplorerLink).mockResolvedValue( - 'https://explorer.example.com/tx/0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef' - ); - }); - - it('should create a transaction with correct parameters and awaitIndexingFn', async () => { - const mockTransaction = { execute: vi.fn() }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createRemoveOrderTransaction(removeOrderMockArgs); - - expect(TransactionStore).toHaveBeenCalledWith( - expect.objectContaining({ - name: TransactionName.REMOVAL, - errorMessage: 'Order removal failed.', - successMessage: 'Order removed successfully.', - queryKey: removeOrderMockArgs.queryKey, - toastLinks: [ - { - link: 'https://explorer.example.com/tx/0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', - label: 'View on explorer' - } - ], - config: mockWagmiConfig, - awaitIndexingFn: expect.any(Function) - }), - expect.any(Function), - expect.any(Function) - ); - - // Verify awaitIndexingFn is a function - const callArgs = vi.mocked(TransactionStore).mock.calls[0][0]; - expect(typeof callArgs.awaitIndexingFn).toBe('function'); - }); - - it('should execute the transaction after creation', async () => { - const mockExecute = vi.fn(); - const mockTransaction = { execute: mockExecute }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createRemoveOrderTransaction(removeOrderMockArgs); - - expect(mockExecute).toHaveBeenCalled(); - }); - - it('should add transaction to store', async () => { - const mockTransaction = { execute: vi.fn() }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createRemoveOrderTransaction(removeOrderMockArgs); - - const transactions = manager.getTransactions(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let storeValue: any[] = []; - transactions.subscribe((value) => { - storeValue = value; - }); - expect(storeValue).toContain(mockTransaction); - }); - - it('should handle successful transaction', async () => { - const mockTransaction = { execute: vi.fn() }; - let onSuccess: () => void; - vi.mocked(TransactionStore).mockImplementation((args, success) => { - onSuccess = success; - return mockTransaction as unknown as TransactionStore; - }); - - await manager.createRemoveOrderTransaction(removeOrderMockArgs); - - onSuccess!(); - - expect(mockQueryClient.invalidateQueries).toHaveBeenCalledWith({ - queryKey: [removeOrderMockArgs.queryKey] - }); - }); - - it('should handle failed transaction', async () => { - const mockTransaction = { execute: vi.fn() }; - let onError: () => void; - vi.mocked(TransactionStore).mockImplementation((args, success, error) => { - onError = error; - return mockTransaction as unknown as TransactionStore; - }); - - await manager.createRemoveOrderTransaction(removeOrderMockArgs); - - onError!(); - - expect(mockAddToast).toHaveBeenCalledWith({ - message: 'Order removal failed.', - type: 'error', - color: 'red', - links: [ - { - link: 'https://explorer.example.com/tx/0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', - label: 'View on explorer' - } - ] - }); - }); - - it('should use SDK-based indexing via createSdkIndexingFn', async () => { - const mockTransaction = { execute: vi.fn() }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createRemoveOrderTransaction(removeOrderMockArgs); - - // Verify awaitIndexingFn was passed and is a function - const callArgs = vi.mocked(TransactionStore).mock.calls[0][0]; - expect(callArgs.awaitIndexingFn).toBeDefined(); - expect(typeof callArgs.awaitIndexingFn).toBe('function'); - - // Simulate calling the awaitIndexingFn to verify it calls the SDK - const mockContext: IndexingContext = { - updateState: vi.fn(), - onSuccess: vi.fn(), - onError: vi.fn(), - links: [] - }; - - // Mock a successful SDK response - vi.mocked(mockRaindexClient.getRemoveOrdersForTransaction).mockResolvedValueOnce({ - value: [{ orderHash: '0xremovedhash' }] - } as unknown as WasmEncodedResult); - - await callArgs.awaitIndexingFn!(mockContext); - - // Verify the SDK method was called with correct arguments - expect(mockRaindexClient.getRemoveOrdersForTransaction).toHaveBeenCalledWith( - removeOrderMockArgs.chainId, - mockSgOrderEntity.raindex, - removeOrderMockArgs.txHash - ); - - // Verify success was called - expect(mockContext.onSuccess).toHaveBeenCalled(); - }); - - it('should handle SDK timeout error in awaitIndexingFn', async () => { - const mockTransaction = { execute: vi.fn() }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createRemoveOrderTransaction(removeOrderMockArgs); - - const callArgs = vi.mocked(TransactionStore).mock.calls[0][0]; - - const mockContext: IndexingContext = { - updateState: vi.fn(), - onSuccess: vi.fn(), - onError: vi.fn(), - links: [] - }; - - // Mock a timeout error from the SDK - vi.mocked(mockRaindexClient.getRemoveOrdersForTransaction).mockResolvedValueOnce({ - error: { - readableMsg: - 'Timeout waiting for the subgraph to index transaction 0x123 after 10 attempts.' - } - } as unknown as WasmEncodedResult); - - await callArgs.awaitIndexingFn!(mockContext); - - // Verify error handling - expect(mockContext.updateState).toHaveBeenCalledWith({ - status: TransactionStatusMessage.ERROR, - errorDetails: TransactionStoreErrorMessage.SUBGRAPH_TIMEOUT_ERROR - }); - expect(mockContext.onError).toHaveBeenCalled(); - expect(mockContext.onSuccess).not.toHaveBeenCalled(); - }); - }); - - describe('createWithdrawTransaction', () => { - const withdrawMockArgs: InternalTransactionArgs & { - raindexClient: RaindexClient; - entity: RaindexVault; - } = { - txHash: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef' as `0x${string}`, - chainId: 1, - queryKey: '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890', - entity: mockSgVaultEntity, - raindexClient: mockRaindexClient - }; - - beforeEach(() => { - vi.mocked(getExplorerLink).mockResolvedValue( - 'https://explorer.example.com/tx/0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef' - ); - }); - - it('should create a transaction with correct parameters and awaitIndexingFn', async () => { - const mockTransaction = { execute: vi.fn() }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createWithdrawTransaction(withdrawMockArgs); - - expect(TransactionStore).toHaveBeenCalledWith( - expect.objectContaining({ - name: TransactionName.WITHDRAWAL, - errorMessage: 'Withdrawal failed.', - successMessage: 'Withdrawal successful.', - queryKey: withdrawMockArgs.queryKey, - toastLinks: [ - { - link: `/vaults/${withdrawMockArgs.chainId}-${withdrawMockArgs.entity.raindex}-${withdrawMockArgs.queryKey}`, - label: 'View vault' - }, - { - link: 'https://explorer.example.com/tx/0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', - label: 'View on explorer' - } - ], - config: mockWagmiConfig, - awaitIndexingFn: expect.any(Function) - }), - expect.any(Function), - expect.any(Function) - ); - - // Verify awaitIndexingFn is a function - const callArgs = vi.mocked(TransactionStore).mock.calls[0][0]; - expect(typeof callArgs.awaitIndexingFn).toBe('function'); - }); - - it('should execute the transaction after creation', async () => { - const mockExecute = vi.fn(); - const mockTransaction = { execute: mockExecute }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createWithdrawTransaction(withdrawMockArgs); - - expect(mockExecute).toHaveBeenCalled(); - }); - - it('should add transaction to store', async () => { - const mockTransaction = { execute: vi.fn() }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createWithdrawTransaction(withdrawMockArgs); - - const transactions = manager.getTransactions(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let storeValue: any[] = []; - transactions.subscribe((value) => { - storeValue = value; - }); - expect(storeValue).toContain(mockTransaction); - }); - - it('should handle successful transaction', async () => { - const mockTransaction = { execute: vi.fn() }; - let onSuccess: () => void; - vi.mocked(TransactionStore).mockImplementation((args, success) => { - onSuccess = success; - return mockTransaction as unknown as TransactionStore; - }); - - const testSpecificArgs: InternalTransactionArgs & { - raindexClient: RaindexClient; - entity: RaindexVault; - } = { - ...withdrawMockArgs, // Use base withdraw args - queryKey: '0xvaultid' // Override queryKey for this specific test - }; - - await manager.createWithdrawTransaction(testSpecificArgs); - - onSuccess!(); - - expect(mockQueryClient.invalidateQueries).toHaveBeenCalledWith({ - queryKey: ['0xvaultid'] - }); - }); - - it('should handle failed transaction', async () => { - const mockTransaction = { execute: vi.fn() }; - let onError: () => void; - vi.mocked(TransactionStore).mockImplementation((args, success, error) => { - onError = error; - return mockTransaction as unknown as TransactionStore; - }); - - await manager.createWithdrawTransaction(withdrawMockArgs); - - onError!(); - - expect(mockAddToast).toHaveBeenCalledWith({ - message: 'Withdrawal failed.', - type: 'error', - color: 'red', - links: expect.any(Array) - }); - }); - - it('should use SDK-based indexing via createSdkIndexingFn', async () => { - const mockTransaction = { execute: vi.fn() }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createWithdrawTransaction(withdrawMockArgs); - - // Verify awaitIndexingFn was passed and is a function - const callArgs = vi.mocked(TransactionStore).mock.calls[0][0]; - expect(callArgs.awaitIndexingFn).toBeDefined(); - expect(typeof callArgs.awaitIndexingFn).toBe('function'); - - // Simulate calling the awaitIndexingFn to verify it calls the SDK - const mockContext: IndexingContext = { - updateState: vi.fn(), - onSuccess: vi.fn(), - onError: vi.fn(), - links: [] - }; - - // Mock a successful SDK response - vi.mocked(mockRaindexClient.getTransaction).mockResolvedValueOnce({ - value: { id: '0xwithdrawhash', from: '0xowner', blockNumber: 123n, timestamp: 1700000000n } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } as any); - - await callArgs.awaitIndexingFn!(mockContext); - - // Verify the SDK method was called with correct arguments (chainId, raindex, txHash) - expect(mockRaindexClient.getTransaction).toHaveBeenCalledWith( - withdrawMockArgs.chainId, - withdrawMockArgs.entity.raindex, - withdrawMockArgs.txHash - ); - - // Verify success was called - expect(mockContext.onSuccess).toHaveBeenCalled(); - }); - }); - - describe('transaction callbacks', () => { - it('should handle successful transaction', async () => { - const mockTransaction = { execute: vi.fn() }; - let onSuccess: () => void; - vi.mocked(TransactionStore).mockImplementation((args, success) => { - onSuccess = success; - return mockTransaction as unknown as TransactionStore; - }); - - await manager.createRemoveOrderTransaction({ - ...mockBaseArgs, - queryKey: '0xsuccesskey', - entity: mockSgOrderEntity, - raindexClient: mockRaindexClient - }); - - onSuccess!(); - - expect(mockAddToast).not.toHaveBeenCalled(); - expect(mockQueryClient.invalidateQueries).toHaveBeenCalledWith({ - queryKey: ['0xsuccesskey'] - }); - }); - - it('should handle failed transaction', async () => { - const mockTransaction = { execute: vi.fn() }; - let onError: () => void; - vi.mocked(TransactionStore).mockImplementation((args, success, error) => { - onError = error; - return mockTransaction as unknown as TransactionStore; - }); - - await manager.createRemoveOrderTransaction({ - ...mockBaseArgs, - queryKey: '0xfailkey', - entity: mockSgOrderEntity, - raindexClient: mockRaindexClient - }); - - onError!(); - - expect(mockAddToast).toHaveBeenCalledWith({ - message: 'Order removal failed.', - type: 'error', - color: 'red', - links: expect.any(Array) - }); - }); - }); - - describe('clearTransactions', () => { - it('should clear all transactions from store', async () => { - const mockTransaction = { execute: vi.fn() }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createRemoveOrderTransaction({ - ...mockBaseArgs, - queryKey: '0xclearkey', - entity: mockSgOrderEntity, - raindexClient: mockRaindexClient - }); - - manager.clearTransactions(); - - const transactions = manager.getTransactions(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let storeValue: any[] = []; - transactions.subscribe((value) => { - storeValue = value; - }); - expect(storeValue).toEqual([]); - }); - }); - - describe('createApprovalTransaction', () => { - const mockEntity = { - token: { - symbol: 'TEST', - decimals: '18' - } - } as unknown as RaindexVault; - const mockArgs: InternalTransactionArgs = { - txHash: '0xapprovehash' as `0x${string}`, - chainId: 1, - queryKey: '0xvaultid' - }; - - beforeEach(() => { - vi.mocked(getExplorerLink).mockResolvedValue('https://explorer.example.com/tx/0xapprovehash'); - }); - - it('should create a transaction with correct parameters when entity is provided', async () => { - const mockTransaction = { execute: vi.fn() }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createApprovalTransaction({ ...mockArgs, entity: mockEntity }); - - expect(TransactionStore).toHaveBeenCalledWith( - { - ...mockArgs, - entity: mockEntity, - name: 'Approving TEST spend', - errorMessage: 'Approval failed.', - successMessage: 'Approval successful.', - queryKey: mockArgs.queryKey, - toastLinks: [ - { - link: `/vaults/${mockArgs.chainId}-${mockEntity.raindex}-${mockArgs.queryKey}`, - label: 'View vault' - }, - { - link: 'https://explorer.example.com/tx/0xapprovehash', - label: 'View on explorer' - } - ], - config: mockWagmiConfig - }, - expect.any(Function), - expect.any(Function) - ); - }); - - it('should create a transaction with correct parameters when entity is not provided', async () => { - const mockTransaction = { execute: vi.fn() }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - // entity is deliberately omitted here - await manager.createApprovalTransaction({ ...mockArgs }); - - expect(TransactionStore).toHaveBeenCalledWith( - { - ...mockArgs, - name: 'Approving token spend', - errorMessage: 'Approval failed.', - successMessage: 'Approval successful.', - queryKey: mockArgs.queryKey, - toastLinks: [ - { - link: 'https://explorer.example.com/tx/0xapprovehash', - label: 'View on explorer' - } - ], - config: mockWagmiConfig - }, - expect.any(Function), - expect.any(Function) - ); - }); - }); - - describe('createMetaTransaction', () => { - const mockArgs: InternalTransactionArgs = { - txHash: '0xmetahash' as `0x${string}`, - chainId: 10, - queryKey: '0xmetakey' - }; - - beforeEach(() => { - vi.mocked(getExplorerLink).mockResolvedValue('https://explorer.example.com/tx/0xmetahash'); - }); - - it('should create a transaction with correct parameters', async () => { - const mockTransaction = { execute: vi.fn() }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createMetaTransaction(mockArgs); - - expect(TransactionStore).toHaveBeenCalledWith( - { - ...mockArgs, - name: 'Publishing metadata', - errorMessage: 'Metadata publication failed.', - successMessage: 'Metadata published.', - queryKey: mockArgs.queryKey, - toastLinks: [ - { - link: 'https://explorer.example.com/tx/0xmetahash', - label: 'View on explorer' - } - ], - config: mockWagmiConfig - }, - expect.any(Function), - expect.any(Function) - ); - }); - - it('should execute the transaction and store it', async () => { - const mockExecute = vi.fn(); - const mockTransaction = { execute: mockExecute }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createMetaTransaction(mockArgs); - - expect(mockExecute).toHaveBeenCalled(); - - const transactions = manager.getTransactions(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let storeValue: any[] = []; - transactions.subscribe((value) => { - storeValue = value; - }); - expect(storeValue).toContain(mockTransaction); - }); - }); - - describe('createDepositTransaction', () => { - const mockEntity = { - token: { - symbol: 'TEST', - decimals: '18' - } - } as unknown as RaindexVault; - const mockArgs: InternalTransactionArgs & { - amount: Float; - entity: RaindexVault; - raindexClient: RaindexClient; - } = { - txHash: '0xdeposithash' as `0x${string}`, - chainId: 1, - queryKey: '0xvaultid', - entity: mockEntity, - amount: Float.parse('1').value as Float, - raindexClient: mockRaindexClient - }; - - beforeEach(() => { - vi.mocked(getExplorerLink).mockResolvedValue('https://explorer.example.com/tx/0xdeposithash'); - }); - - it('should create a transaction with correct parameters and awaitIndexingFn', async () => { - const mockTransaction = { execute: vi.fn() }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createDepositTransaction(mockArgs); - - expect(TransactionStore).toHaveBeenCalledWith( - expect.objectContaining({ - name: `Depositing ${mockArgs.amount.format().value} ${mockEntity.token.symbol}`, - errorMessage: 'Deposit failed.', - successMessage: 'Deposit successful.', - queryKey: mockArgs.queryKey, - toastLinks: [ - { - link: `/vaults/${mockArgs.chainId}-${mockEntity.raindex}-${mockArgs.queryKey}`, - label: 'View vault' - }, - { - link: 'https://explorer.example.com/tx/0xdeposithash', - label: 'View on explorer' - } - ], - config: mockWagmiConfig, - awaitIndexingFn: expect.any(Function) - }), - expect.any(Function), - expect.any(Function) - ); - - // Verify awaitIndexingFn is a function - const callArgs = vi.mocked(TransactionStore).mock.calls[0][0]; - expect(typeof callArgs.awaitIndexingFn).toBe('function'); - }); - - it('should execute the transaction after creation', async () => { - const mockExecute = vi.fn(); - const mockTransaction = { execute: mockExecute }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createDepositTransaction(mockArgs); - - expect(mockExecute).toHaveBeenCalled(); - }); - - it('should add transaction to store', async () => { - const mockTransaction = { execute: vi.fn() }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createDepositTransaction(mockArgs); - - const transactions = manager.getTransactions(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let storeValue: any[] = []; - transactions.subscribe((value) => { - storeValue = value; - }); - expect(storeValue).toContain(mockTransaction); - }); - - it('should handle successful transaction', async () => { - const mockTransaction = { execute: vi.fn() }; - let onSuccess: () => void; - vi.mocked(TransactionStore).mockImplementation((args, success) => { - onSuccess = success; - return mockTransaction as unknown as TransactionStore; - }); - - await manager.createDepositTransaction(mockArgs); - - onSuccess!(); - - expect(mockQueryClient.invalidateQueries).toHaveBeenCalledWith({ - queryKey: ['0xvaultid'] - }); - }); - - it('should handle failed transaction', async () => { - const mockTransaction = { execute: vi.fn() }; - let onError: () => void; - vi.mocked(TransactionStore).mockImplementation((args, success, error) => { - onError = error; - return mockTransaction as unknown as TransactionStore; - }); - - await manager.createDepositTransaction(mockArgs); - - onError!(); - - expect(mockAddToast).toHaveBeenCalledWith({ - message: 'Deposit failed.', - type: 'error', - color: 'red', - links: expect.any(Array) - }); - }); - - it('should use SDK-based indexing via createSdkIndexingFn', async () => { - const mockTransaction = { execute: vi.fn() }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createDepositTransaction(mockArgs); - - // Verify awaitIndexingFn was passed and is a function - const callArgs = vi.mocked(TransactionStore).mock.calls[0][0]; - expect(callArgs.awaitIndexingFn).toBeDefined(); - expect(typeof callArgs.awaitIndexingFn).toBe('function'); - - // Simulate calling the awaitIndexingFn to verify it calls the SDK - const mockContext: IndexingContext = { - updateState: vi.fn(), - onSuccess: vi.fn(), - onError: vi.fn(), - links: [] - }; - - // Mock a successful SDK response - vi.mocked(mockRaindexClient.getTransaction).mockResolvedValueOnce({ - value: { id: '0xdeposithash', from: '0xowner', blockNumber: 123n, timestamp: 1700000000n } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } as any); - - await callArgs.awaitIndexingFn!(mockContext); - - // Verify the SDK method was called with correct arguments (chainId, raindex, txHash) - expect(mockRaindexClient.getTransaction).toHaveBeenCalledWith( - mockArgs.chainId, - mockArgs.entity.raindex, - mockArgs.txHash - ); - - // Verify success was called - expect(mockContext.onSuccess).toHaveBeenCalled(); - }); - - it('should handle SDK timeout error in awaitIndexingFn', async () => { - const mockTransaction = { execute: vi.fn() }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createDepositTransaction(mockArgs); - - const callArgs = vi.mocked(TransactionStore).mock.calls[0][0]; - - const mockContext: IndexingContext = { - updateState: vi.fn(), - onSuccess: vi.fn(), - onError: vi.fn(), - links: [] - }; - - // Mock a timeout error from the SDK - vi.mocked(mockRaindexClient.getTransaction).mockResolvedValueOnce({ - error: { - readableMsg: 'Timeout waiting for transaction 0x123 to be indexed after 10 attempts.' - } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } as any); - - await callArgs.awaitIndexingFn!(mockContext); - - // Verify error handling - expect(mockContext.updateState).toHaveBeenCalledWith({ - status: TransactionStatusMessage.ERROR, - errorDetails: TransactionStoreErrorMessage.SUBGRAPH_TIMEOUT_ERROR - }); - expect(mockContext.onError).toHaveBeenCalled(); - expect(mockContext.onSuccess).not.toHaveBeenCalled(); - }); - }); - - describe('createAddOrderTransaction', () => { - const addOrderMockArgs: InternalTransactionArgs & { - raindexClient: RaindexClient; - raindex: Address; - } = { - txHash: '0xaddordertxhash' as `0x${string}`, - chainId: 1, - queryKey: 'myNewStrategyDeployment', - raindexClient: mockRaindexClient, - raindex: '0xraindex' as Address - }; - - beforeEach(() => { - vi.mocked(getExplorerLink).mockResolvedValue( - 'https://explorer.example.com/tx/0xaddordertxhash' - ); - }); - - it('should create a transaction with correct parameters and awaitIndexingFn', async () => { - const mockTransaction = { execute: vi.fn() }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createAddOrderTransaction(addOrderMockArgs); - - expect(TransactionStore).toHaveBeenCalledWith( - expect.objectContaining({ - name: 'Deploying order', - errorMessage: 'Deployment failed.', - successMessage: 'Order deployed successfully.', - queryKey: addOrderMockArgs.queryKey, - awaitIndexingFn: expect.any(Function), - toastLinks: [ - { - link: 'https://explorer.example.com/tx/0xaddordertxhash', - label: 'View on explorer' - } - ], - config: mockWagmiConfig - }), - expect.any(Function), // onSuccess - expect.any(Function) // onError - ); - - // Verify awaitIndexingFn is a function (SDK-based indexing) - const callArgs = vi.mocked(TransactionStore).mock.calls[0][0]; - expect(typeof callArgs.awaitIndexingFn).toBe('function'); - }); - - it('should execute the transaction after creation', async () => { - const mockExecute = vi.fn(); - const mockTransaction = { execute: mockExecute }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createAddOrderTransaction(addOrderMockArgs); - - expect(mockExecute).toHaveBeenCalled(); - }); - - it('should add transaction to store', async () => { - const mockTransaction = { execute: vi.fn() }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createAddOrderTransaction(addOrderMockArgs); - - const transactions = manager.getTransactions(); - let storeValue: unknown[] = []; - transactions.subscribe((value) => { - storeValue = value; - }); - expect(storeValue).toContain(mockTransaction); - }); - - it('should handle successful transaction', async () => { - const mockTransaction = { execute: vi.fn() }; - let onSuccess: (newOrderHash?: string) => void; - vi.mocked(TransactionStore).mockImplementation((args, success) => { - onSuccess = success; - return mockTransaction as unknown as TransactionStore; - }); - const newOrderHash = '0xneworderhashfromcallback'; - - await manager.createAddOrderTransaction(addOrderMockArgs); - - onSuccess!(newOrderHash); // Simulate successful execution and subgraph indexing providing a new order hash - - expect(mockQueryClient.invalidateQueries).toHaveBeenCalledWith({ - queryKey: [addOrderMockArgs.queryKey] - }); - }); - - it('should handle failed transaction', async () => { - const mockTransaction = { execute: vi.fn() }; - let onError: () => void; - vi.mocked(TransactionStore).mockImplementation((args, success, error) => { - onError = error; - return mockTransaction as unknown as TransactionStore; - }); - - await manager.createAddOrderTransaction(addOrderMockArgs); - - onError!(); - - expect(mockAddToast).toHaveBeenCalledWith({ - message: 'Deployment failed.', - type: 'error', - color: 'red', - links: [ - { - link: 'https://explorer.example.com/tx/0xaddordertxhash', - label: 'View on explorer' - } - ] - }); - }); - }); - - describe('createTakeOrderTransaction', () => { - const takeOrderMockArgs: InternalTransactionArgs & { - raindexClient: RaindexClient; - entity: RaindexOrder; - } = { - txHash: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef' as `0x${string}`, - chainId: 1, - queryKey: '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890', - entity: mockSgOrderEntity, - raindexClient: mockRaindexClient - }; - - beforeEach(() => { - vi.mocked(getExplorerLink).mockResolvedValue( - 'https://explorer.example.com/tx/0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef' - ); - }); - - it('should create transaction with correct name and messages', async () => { - const mockTransaction = { execute: vi.fn() }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createTakeOrderTransaction(takeOrderMockArgs); - - expect(TransactionStore).toHaveBeenCalledWith( - expect.objectContaining({ - name: TransactionName.TAKE_ORDER, - errorMessage: 'Take order failed.', - successMessage: 'Order taken successfully.', - queryKey: takeOrderMockArgs.queryKey - }), - expect.any(Function), - expect.any(Function) - ); - }); - - it('should call getExplorerLink with correct params', async () => { - const mockTransaction = { execute: vi.fn() }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createTakeOrderTransaction(takeOrderMockArgs); - - expect(getExplorerLink).toHaveBeenCalledWith( - takeOrderMockArgs.txHash, - takeOrderMockArgs.chainId, - 'tx' - ); - expect(TransactionStore).toHaveBeenCalledWith( - expect.objectContaining({ - toastLinks: [ - { - link: 'https://explorer.example.com/tx/0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', - label: 'View on explorer' - } - ] - }), - expect.any(Function), - expect.any(Function) - ); - }); - - it('should use SDK-based indexing via createSdkIndexingFn for order tracking', async () => { - const mockTransaction = { execute: vi.fn() }; - vi.mocked(TransactionStore).mockImplementation( - () => mockTransaction as unknown as TransactionStore - ); - - await manager.createTakeOrderTransaction(takeOrderMockArgs); - - const callArgs = vi.mocked(TransactionStore).mock.calls[0][0]; - expect(callArgs.awaitIndexingFn).toBeDefined(); - expect(typeof callArgs.awaitIndexingFn).toBe('function'); - - const mockContext: IndexingContext = { - updateState: vi.fn(), - onSuccess: vi.fn(), - onError: vi.fn(), - links: [] - }; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - vi.mocked(mockRaindexClient.getTransaction).mockResolvedValueOnce({ - value: { id: '0x0123', from: '0xowner', blockNumber: 123n, timestamp: 1700000000n } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } as any); - - await callArgs.awaitIndexingFn!(mockContext); - - expect(mockRaindexClient.getTransaction).toHaveBeenCalledWith( - takeOrderMockArgs.chainId, - takeOrderMockArgs.entity.raindex, - takeOrderMockArgs.txHash - ); - - expect(mockContext.onSuccess).toHaveBeenCalled(); - }); - - it('should handle successful transaction completion', async () => { - const mockTransaction = { execute: vi.fn() }; - let onSuccess: () => void; - vi.mocked(TransactionStore).mockImplementation((args, success) => { - onSuccess = success; - return mockTransaction as unknown as TransactionStore; - }); - - await manager.createTakeOrderTransaction(takeOrderMockArgs); - - onSuccess!(); - - expect(mockQueryClient.invalidateQueries).toHaveBeenCalledWith({ - queryKey: [takeOrderMockArgs.queryKey] - }); - }); - - it('should handle transaction failure', async () => { - const mockTransaction = { execute: vi.fn() }; - let onError: () => void; - vi.mocked(TransactionStore).mockImplementation((args, success, error) => { - onError = error; - return mockTransaction as unknown as TransactionStore; - }); - - await manager.createTakeOrderTransaction(takeOrderMockArgs); - - onError!(); - - expect(mockAddToast).toHaveBeenCalledWith({ - message: 'Take order failed.', - type: 'error', - color: 'red', - links: [ - { - link: 'https://explorer.example.com/tx/0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', - label: 'View on explorer' - } - ] - }); - }); - }); +describe("TransactionManager", () => { + let mockQueryClient: QueryClient; + let mockAddToast: (toast: Omit) => void; + let mockWagmiConfig: Config; + let manager: TransactionManager; + + const mockRaindexClient = { + getRemoveOrdersForTransaction: vi.fn(), + getTransaction: vi.fn(), + getAddOrdersForTransaction: vi.fn(), + } as unknown as RaindexClient; + + const mockSgOrderEntity = { + id: "mockOrderEntityId", + raindex: "mockRaindex", + getRemoveOrdersForTransaction: vi.fn(), + } as unknown as RaindexOrder; + + const mockSgVaultEntity = { + token: { symbol: "MOCKVAULT", decimals: "18" }, + vaultId: "mockVaultEntityId", + id: "mockVaultEntityId", + } as unknown as RaindexVault; + + const mockBaseArgs: InternalTransactionArgs = { + txHash: "0xcallbacktxhash" as `0x${string}`, + chainId: 1, + queryKey: "0xcallbackkey", + }; + + beforeEach(() => { + vi.clearAllMocks(); + + mockQueryClient = { + invalidateQueries: vi.fn(), + } as unknown as QueryClient; + + mockAddToast = vi.fn(); + + mockWagmiConfig = {} as Config; + manager = new TransactionManager( + mockQueryClient, + mockAddToast, + mockWagmiConfig, + ); + }); + + describe("initialization", () => { + it("should initialize with empty transactions store", () => { + const transactions = manager.getTransactions(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let storeValue: any[] = []; + transactions.subscribe((value) => { + storeValue = value; + }); + expect(storeValue).toEqual([]); + }); + }); + + describe("createRemoveOrderTransaction", () => { + const removeOrderMockArgs: InternalTransactionArgs & { + raindexClient: RaindexClient; + entity: RaindexOrder; + } = { + txHash: + "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" as `0x${string}`, + chainId: 1, + queryKey: + "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890", + entity: mockSgOrderEntity, + raindexClient: mockRaindexClient, + }; + + beforeEach(() => { + vi.mocked(getExplorerLink).mockResolvedValue( + "https://explorer.example.com/tx/0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + ); + }); + + it("should create a transaction with correct parameters and awaitIndexingFn", async () => { + const mockTransaction = { execute: vi.fn() }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createRemoveOrderTransaction(removeOrderMockArgs); + + expect(TransactionStore).toHaveBeenCalledWith( + expect.objectContaining({ + name: TransactionName.REMOVAL, + errorMessage: "Order removal failed.", + successMessage: "Order removed successfully.", + queryKey: removeOrderMockArgs.queryKey, + toastLinks: [ + { + link: "https://explorer.example.com/tx/0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + label: "View on explorer", + }, + ], + config: mockWagmiConfig, + awaitIndexingFn: expect.any(Function), + }), + expect.any(Function), + expect.any(Function), + ); + + // Verify awaitIndexingFn is a function + const callArgs = vi.mocked(TransactionStore).mock.calls[0][0]; + expect(typeof callArgs.awaitIndexingFn).toBe("function"); + }); + + it("should execute the transaction after creation", async () => { + const mockExecute = vi.fn(); + const mockTransaction = { execute: mockExecute }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createRemoveOrderTransaction(removeOrderMockArgs); + + expect(mockExecute).toHaveBeenCalled(); + }); + + it("should add transaction to store", async () => { + const mockTransaction = { execute: vi.fn() }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createRemoveOrderTransaction(removeOrderMockArgs); + + const transactions = manager.getTransactions(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let storeValue: any[] = []; + transactions.subscribe((value) => { + storeValue = value; + }); + expect(storeValue).toContain(mockTransaction); + }); + + it("should handle successful transaction", async () => { + const mockTransaction = { execute: vi.fn() }; + let onSuccess: () => void; + vi.mocked(TransactionStore).mockImplementation((args, success) => { + onSuccess = success; + return mockTransaction as unknown as TransactionStore; + }); + + await manager.createRemoveOrderTransaction(removeOrderMockArgs); + + onSuccess!(); + + expect(mockQueryClient.invalidateQueries).toHaveBeenCalledWith({ + queryKey: [removeOrderMockArgs.queryKey], + }); + }); + + it("should handle failed transaction", async () => { + const mockTransaction = { execute: vi.fn() }; + let onError: () => void; + vi.mocked(TransactionStore).mockImplementation((args, success, error) => { + onError = error; + return mockTransaction as unknown as TransactionStore; + }); + + await manager.createRemoveOrderTransaction(removeOrderMockArgs); + + onError!(); + + expect(mockAddToast).toHaveBeenCalledWith({ + message: "Order removal failed.", + type: "error", + color: "red", + links: [ + { + link: "https://explorer.example.com/tx/0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + label: "View on explorer", + }, + ], + }); + }); + + it("should use SDK-based indexing via createSdkIndexingFn", async () => { + const mockTransaction = { execute: vi.fn() }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createRemoveOrderTransaction(removeOrderMockArgs); + + // Verify awaitIndexingFn was passed and is a function + const callArgs = vi.mocked(TransactionStore).mock.calls[0][0]; + expect(callArgs.awaitIndexingFn).toBeDefined(); + expect(typeof callArgs.awaitIndexingFn).toBe("function"); + + // Simulate calling the awaitIndexingFn to verify it calls the SDK + const mockContext: IndexingContext = { + updateState: vi.fn(), + onSuccess: vi.fn(), + onError: vi.fn(), + links: [], + }; + + // Mock a successful SDK response + vi.mocked( + mockRaindexClient.getRemoveOrdersForTransaction, + ).mockResolvedValueOnce({ + value: [{ orderHash: "0xremovedhash" }], + } as unknown as WasmEncodedResult); + + await callArgs.awaitIndexingFn!(mockContext); + + // Verify the SDK method was called with correct arguments + expect( + mockRaindexClient.getRemoveOrdersForTransaction, + ).toHaveBeenCalledWith( + removeOrderMockArgs.chainId, + mockSgOrderEntity.raindex, + removeOrderMockArgs.txHash, + ); + + // Verify success was called + expect(mockContext.onSuccess).toHaveBeenCalled(); + }); + + it("should handle SDK timeout error in awaitIndexingFn", async () => { + const mockTransaction = { execute: vi.fn() }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createRemoveOrderTransaction(removeOrderMockArgs); + + const callArgs = vi.mocked(TransactionStore).mock.calls[0][0]; + + const mockContext: IndexingContext = { + updateState: vi.fn(), + onSuccess: vi.fn(), + onError: vi.fn(), + links: [], + }; + + // Mock a timeout error from the SDK + vi.mocked( + mockRaindexClient.getRemoveOrdersForTransaction, + ).mockResolvedValueOnce({ + error: { + readableMsg: + "Timeout waiting for the subgraph to index transaction 0x123 after 10 attempts.", + }, + } as unknown as WasmEncodedResult); + + await callArgs.awaitIndexingFn!(mockContext); + + // Verify error handling + expect(mockContext.updateState).toHaveBeenCalledWith({ + status: TransactionStatusMessage.ERROR, + errorDetails: TransactionStoreErrorMessage.SUBGRAPH_TIMEOUT_ERROR, + }); + expect(mockContext.onError).toHaveBeenCalled(); + expect(mockContext.onSuccess).not.toHaveBeenCalled(); + }); + }); + + describe("createWithdrawTransaction", () => { + const withdrawMockArgs: InternalTransactionArgs & { + raindexClient: RaindexClient; + entity: RaindexVault; + } = { + txHash: + "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" as `0x${string}`, + chainId: 1, + queryKey: + "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890", + entity: mockSgVaultEntity, + raindexClient: mockRaindexClient, + }; + + beforeEach(() => { + vi.mocked(getExplorerLink).mockResolvedValue( + "https://explorer.example.com/tx/0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + ); + }); + + it("should create a transaction with correct parameters and awaitIndexingFn", async () => { + const mockTransaction = { execute: vi.fn() }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createWithdrawTransaction(withdrawMockArgs); + + expect(TransactionStore).toHaveBeenCalledWith( + expect.objectContaining({ + name: TransactionName.WITHDRAWAL, + errorMessage: "Withdrawal failed.", + successMessage: "Withdrawal successful.", + queryKey: withdrawMockArgs.queryKey, + toastLinks: [ + { + link: `/vaults/${withdrawMockArgs.chainId}-${withdrawMockArgs.entity.raindex}-${withdrawMockArgs.queryKey}`, + label: "View vault", + }, + { + link: "https://explorer.example.com/tx/0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + label: "View on explorer", + }, + ], + config: mockWagmiConfig, + awaitIndexingFn: expect.any(Function), + }), + expect.any(Function), + expect.any(Function), + ); + + // Verify awaitIndexingFn is a function + const callArgs = vi.mocked(TransactionStore).mock.calls[0][0]; + expect(typeof callArgs.awaitIndexingFn).toBe("function"); + }); + + it("should execute the transaction after creation", async () => { + const mockExecute = vi.fn(); + const mockTransaction = { execute: mockExecute }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createWithdrawTransaction(withdrawMockArgs); + + expect(mockExecute).toHaveBeenCalled(); + }); + + it("should add transaction to store", async () => { + const mockTransaction = { execute: vi.fn() }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createWithdrawTransaction(withdrawMockArgs); + + const transactions = manager.getTransactions(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let storeValue: any[] = []; + transactions.subscribe((value) => { + storeValue = value; + }); + expect(storeValue).toContain(mockTransaction); + }); + + it("should handle successful transaction", async () => { + const mockTransaction = { execute: vi.fn() }; + let onSuccess: () => void; + vi.mocked(TransactionStore).mockImplementation((args, success) => { + onSuccess = success; + return mockTransaction as unknown as TransactionStore; + }); + + const testSpecificArgs: InternalTransactionArgs & { + raindexClient: RaindexClient; + entity: RaindexVault; + } = { + ...withdrawMockArgs, // Use base withdraw args + queryKey: "0xvaultid", // Override queryKey for this specific test + }; + + await manager.createWithdrawTransaction(testSpecificArgs); + + onSuccess!(); + + expect(mockQueryClient.invalidateQueries).toHaveBeenCalledWith({ + queryKey: ["0xvaultid"], + }); + }); + + it("should handle failed transaction", async () => { + const mockTransaction = { execute: vi.fn() }; + let onError: () => void; + vi.mocked(TransactionStore).mockImplementation((args, success, error) => { + onError = error; + return mockTransaction as unknown as TransactionStore; + }); + + await manager.createWithdrawTransaction(withdrawMockArgs); + + onError!(); + + expect(mockAddToast).toHaveBeenCalledWith({ + message: "Withdrawal failed.", + type: "error", + color: "red", + links: expect.any(Array), + }); + }); + + it("should use SDK-based indexing via createSdkIndexingFn", async () => { + const mockTransaction = { execute: vi.fn() }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createWithdrawTransaction(withdrawMockArgs); + + // Verify awaitIndexingFn was passed and is a function + const callArgs = vi.mocked(TransactionStore).mock.calls[0][0]; + expect(callArgs.awaitIndexingFn).toBeDefined(); + expect(typeof callArgs.awaitIndexingFn).toBe("function"); + + // Simulate calling the awaitIndexingFn to verify it calls the SDK + const mockContext: IndexingContext = { + updateState: vi.fn(), + onSuccess: vi.fn(), + onError: vi.fn(), + links: [], + }; + + // Mock a successful SDK response + vi.mocked(mockRaindexClient.getTransaction).mockResolvedValueOnce({ + value: { + id: "0xwithdrawhash", + from: "0xowner", + blockNumber: 123n, + timestamp: 1700000000n, + }, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any); + + await callArgs.awaitIndexingFn!(mockContext); + + // Verify the SDK method was called with correct arguments (chainId, raindex, txHash) + expect(mockRaindexClient.getTransaction).toHaveBeenCalledWith( + withdrawMockArgs.chainId, + withdrawMockArgs.entity.raindex, + withdrawMockArgs.txHash, + ); + + // Verify success was called + expect(mockContext.onSuccess).toHaveBeenCalled(); + }); + }); + + describe("transaction callbacks", () => { + it("should handle successful transaction", async () => { + const mockTransaction = { execute: vi.fn() }; + let onSuccess: () => void; + vi.mocked(TransactionStore).mockImplementation((args, success) => { + onSuccess = success; + return mockTransaction as unknown as TransactionStore; + }); + + await manager.createRemoveOrderTransaction({ + ...mockBaseArgs, + queryKey: "0xsuccesskey", + entity: mockSgOrderEntity, + raindexClient: mockRaindexClient, + }); + + onSuccess!(); + + expect(mockAddToast).not.toHaveBeenCalled(); + expect(mockQueryClient.invalidateQueries).toHaveBeenCalledWith({ + queryKey: ["0xsuccesskey"], + }); + }); + + it("should handle failed transaction", async () => { + const mockTransaction = { execute: vi.fn() }; + let onError: () => void; + vi.mocked(TransactionStore).mockImplementation((args, success, error) => { + onError = error; + return mockTransaction as unknown as TransactionStore; + }); + + await manager.createRemoveOrderTransaction({ + ...mockBaseArgs, + queryKey: "0xfailkey", + entity: mockSgOrderEntity, + raindexClient: mockRaindexClient, + }); + + onError!(); + + expect(mockAddToast).toHaveBeenCalledWith({ + message: "Order removal failed.", + type: "error", + color: "red", + links: expect.any(Array), + }); + }); + }); + + describe("clearTransactions", () => { + it("should clear all transactions from store", async () => { + const mockTransaction = { execute: vi.fn() }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createRemoveOrderTransaction({ + ...mockBaseArgs, + queryKey: "0xclearkey", + entity: mockSgOrderEntity, + raindexClient: mockRaindexClient, + }); + + manager.clearTransactions(); + + const transactions = manager.getTransactions(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let storeValue: any[] = []; + transactions.subscribe((value) => { + storeValue = value; + }); + expect(storeValue).toEqual([]); + }); + }); + + describe("createApprovalTransaction", () => { + const mockEntity = { + token: { + symbol: "TEST", + decimals: "18", + }, + } as unknown as RaindexVault; + const mockArgs: InternalTransactionArgs = { + txHash: "0xapprovehash" as `0x${string}`, + chainId: 1, + queryKey: "0xvaultid", + }; + + beforeEach(() => { + vi.mocked(getExplorerLink).mockResolvedValue( + "https://explorer.example.com/tx/0xapprovehash", + ); + }); + + it("should create a transaction with correct parameters when entity is provided", async () => { + const mockTransaction = { execute: vi.fn() }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createApprovalTransaction({ + ...mockArgs, + entity: mockEntity, + }); + + expect(TransactionStore).toHaveBeenCalledWith( + { + ...mockArgs, + entity: mockEntity, + name: "Approving TEST spend", + errorMessage: "Approval failed.", + successMessage: "Approval successful.", + queryKey: mockArgs.queryKey, + toastLinks: [ + { + link: `/vaults/${mockArgs.chainId}-${mockEntity.raindex}-${mockArgs.queryKey}`, + label: "View vault", + }, + { + link: "https://explorer.example.com/tx/0xapprovehash", + label: "View on explorer", + }, + ], + config: mockWagmiConfig, + }, + expect.any(Function), + expect.any(Function), + ); + }); + + it("should create a transaction with correct parameters when entity is not provided", async () => { + const mockTransaction = { execute: vi.fn() }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + // entity is deliberately omitted here + await manager.createApprovalTransaction({ ...mockArgs }); + + expect(TransactionStore).toHaveBeenCalledWith( + { + ...mockArgs, + name: "Approving token spend", + errorMessage: "Approval failed.", + successMessage: "Approval successful.", + queryKey: mockArgs.queryKey, + toastLinks: [ + { + link: "https://explorer.example.com/tx/0xapprovehash", + label: "View on explorer", + }, + ], + config: mockWagmiConfig, + }, + expect.any(Function), + expect.any(Function), + ); + }); + }); + + describe("createMetaTransaction", () => { + const mockArgs: InternalTransactionArgs = { + txHash: "0xmetahash" as `0x${string}`, + chainId: 10, + queryKey: "0xmetakey", + }; + + beforeEach(() => { + vi.mocked(getExplorerLink).mockResolvedValue( + "https://explorer.example.com/tx/0xmetahash", + ); + }); + + it("should create a transaction with correct parameters", async () => { + const mockTransaction = { execute: vi.fn() }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createMetaTransaction(mockArgs); + + expect(TransactionStore).toHaveBeenCalledWith( + { + ...mockArgs, + name: "Publishing metadata", + errorMessage: "Metadata publication failed.", + successMessage: "Metadata published.", + queryKey: mockArgs.queryKey, + toastLinks: [ + { + link: "https://explorer.example.com/tx/0xmetahash", + label: "View on explorer", + }, + ], + config: mockWagmiConfig, + }, + expect.any(Function), + expect.any(Function), + ); + }); + + it("should execute the transaction and store it", async () => { + const mockExecute = vi.fn(); + const mockTransaction = { execute: mockExecute }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createMetaTransaction(mockArgs); + + expect(mockExecute).toHaveBeenCalled(); + + const transactions = manager.getTransactions(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let storeValue: any[] = []; + transactions.subscribe((value) => { + storeValue = value; + }); + expect(storeValue).toContain(mockTransaction); + }); + }); + + describe("createDepositTransaction", () => { + const mockEntity = { + token: { + symbol: "TEST", + decimals: "18", + }, + } as unknown as RaindexVault; + const mockArgs: InternalTransactionArgs & { + amount: Float; + entity: RaindexVault; + raindexClient: RaindexClient; + } = { + txHash: "0xdeposithash" as `0x${string}`, + chainId: 1, + queryKey: "0xvaultid", + entity: mockEntity, + amount: Float.parse("1").value as Float, + raindexClient: mockRaindexClient, + }; + + beforeEach(() => { + vi.mocked(getExplorerLink).mockResolvedValue( + "https://explorer.example.com/tx/0xdeposithash", + ); + }); + + it("should create a transaction with correct parameters and awaitIndexingFn", async () => { + const mockTransaction = { execute: vi.fn() }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createDepositTransaction(mockArgs); + + expect(TransactionStore).toHaveBeenCalledWith( + expect.objectContaining({ + name: `Depositing ${mockArgs.amount.format().value} ${mockEntity.token.symbol}`, + errorMessage: "Deposit failed.", + successMessage: "Deposit successful.", + queryKey: mockArgs.queryKey, + toastLinks: [ + { + link: `/vaults/${mockArgs.chainId}-${mockEntity.raindex}-${mockArgs.queryKey}`, + label: "View vault", + }, + { + link: "https://explorer.example.com/tx/0xdeposithash", + label: "View on explorer", + }, + ], + config: mockWagmiConfig, + awaitIndexingFn: expect.any(Function), + }), + expect.any(Function), + expect.any(Function), + ); + + // Verify awaitIndexingFn is a function + const callArgs = vi.mocked(TransactionStore).mock.calls[0][0]; + expect(typeof callArgs.awaitIndexingFn).toBe("function"); + }); + + it("should execute the transaction after creation", async () => { + const mockExecute = vi.fn(); + const mockTransaction = { execute: mockExecute }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createDepositTransaction(mockArgs); + + expect(mockExecute).toHaveBeenCalled(); + }); + + it("should add transaction to store", async () => { + const mockTransaction = { execute: vi.fn() }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createDepositTransaction(mockArgs); + + const transactions = manager.getTransactions(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let storeValue: any[] = []; + transactions.subscribe((value) => { + storeValue = value; + }); + expect(storeValue).toContain(mockTransaction); + }); + + it("should handle successful transaction", async () => { + const mockTransaction = { execute: vi.fn() }; + let onSuccess: () => void; + vi.mocked(TransactionStore).mockImplementation((args, success) => { + onSuccess = success; + return mockTransaction as unknown as TransactionStore; + }); + + await manager.createDepositTransaction(mockArgs); + + onSuccess!(); + + expect(mockQueryClient.invalidateQueries).toHaveBeenCalledWith({ + queryKey: ["0xvaultid"], + }); + }); + + it("should handle failed transaction", async () => { + const mockTransaction = { execute: vi.fn() }; + let onError: () => void; + vi.mocked(TransactionStore).mockImplementation((args, success, error) => { + onError = error; + return mockTransaction as unknown as TransactionStore; + }); + + await manager.createDepositTransaction(mockArgs); + + onError!(); + + expect(mockAddToast).toHaveBeenCalledWith({ + message: "Deposit failed.", + type: "error", + color: "red", + links: expect.any(Array), + }); + }); + + it("should use SDK-based indexing via createSdkIndexingFn", async () => { + const mockTransaction = { execute: vi.fn() }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createDepositTransaction(mockArgs); + + // Verify awaitIndexingFn was passed and is a function + const callArgs = vi.mocked(TransactionStore).mock.calls[0][0]; + expect(callArgs.awaitIndexingFn).toBeDefined(); + expect(typeof callArgs.awaitIndexingFn).toBe("function"); + + // Simulate calling the awaitIndexingFn to verify it calls the SDK + const mockContext: IndexingContext = { + updateState: vi.fn(), + onSuccess: vi.fn(), + onError: vi.fn(), + links: [], + }; + + // Mock a successful SDK response + vi.mocked(mockRaindexClient.getTransaction).mockResolvedValueOnce({ + value: { + id: "0xdeposithash", + from: "0xowner", + blockNumber: 123n, + timestamp: 1700000000n, + }, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any); + + await callArgs.awaitIndexingFn!(mockContext); + + // Verify the SDK method was called with correct arguments (chainId, raindex, txHash) + expect(mockRaindexClient.getTransaction).toHaveBeenCalledWith( + mockArgs.chainId, + mockArgs.entity.raindex, + mockArgs.txHash, + ); + + // Verify success was called + expect(mockContext.onSuccess).toHaveBeenCalled(); + }); + + it("should handle SDK timeout error in awaitIndexingFn", async () => { + const mockTransaction = { execute: vi.fn() }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createDepositTransaction(mockArgs); + + const callArgs = vi.mocked(TransactionStore).mock.calls[0][0]; + + const mockContext: IndexingContext = { + updateState: vi.fn(), + onSuccess: vi.fn(), + onError: vi.fn(), + links: [], + }; + + // Mock a timeout error from the SDK + vi.mocked(mockRaindexClient.getTransaction).mockResolvedValueOnce({ + error: { + readableMsg: + "Timeout waiting for transaction 0x123 to be indexed after 10 attempts.", + }, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any); + + await callArgs.awaitIndexingFn!(mockContext); + + // Verify error handling + expect(mockContext.updateState).toHaveBeenCalledWith({ + status: TransactionStatusMessage.ERROR, + errorDetails: TransactionStoreErrorMessage.SUBGRAPH_TIMEOUT_ERROR, + }); + expect(mockContext.onError).toHaveBeenCalled(); + expect(mockContext.onSuccess).not.toHaveBeenCalled(); + }); + }); + + describe("createAddOrderTransaction", () => { + const addOrderMockArgs: InternalTransactionArgs & { + raindexClient: RaindexClient; + raindex: Address; + } = { + txHash: "0xaddordertxhash" as `0x${string}`, + chainId: 1, + queryKey: "myNewStrategyDeployment", + raindexClient: mockRaindexClient, + raindex: "0xraindex" as Address, + }; + + beforeEach(() => { + vi.mocked(getExplorerLink).mockResolvedValue( + "https://explorer.example.com/tx/0xaddordertxhash", + ); + }); + + it("should create a transaction with correct parameters and awaitIndexingFn", async () => { + const mockTransaction = { execute: vi.fn() }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createAddOrderTransaction(addOrderMockArgs); + + expect(TransactionStore).toHaveBeenCalledWith( + expect.objectContaining({ + name: "Deploying order", + errorMessage: "Deployment failed.", + successMessage: "Order deployed successfully.", + queryKey: addOrderMockArgs.queryKey, + awaitIndexingFn: expect.any(Function), + toastLinks: [ + { + link: "https://explorer.example.com/tx/0xaddordertxhash", + label: "View on explorer", + }, + ], + config: mockWagmiConfig, + }), + expect.any(Function), // onSuccess + expect.any(Function), // onError + ); + + // Verify awaitIndexingFn is a function (SDK-based indexing) + const callArgs = vi.mocked(TransactionStore).mock.calls[0][0]; + expect(typeof callArgs.awaitIndexingFn).toBe("function"); + }); + + it("should execute the transaction after creation", async () => { + const mockExecute = vi.fn(); + const mockTransaction = { execute: mockExecute }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createAddOrderTransaction(addOrderMockArgs); + + expect(mockExecute).toHaveBeenCalled(); + }); + + it("should add transaction to store", async () => { + const mockTransaction = { execute: vi.fn() }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createAddOrderTransaction(addOrderMockArgs); + + const transactions = manager.getTransactions(); + let storeValue: unknown[] = []; + transactions.subscribe((value) => { + storeValue = value; + }); + expect(storeValue).toContain(mockTransaction); + }); + + it("should handle successful transaction", async () => { + const mockTransaction = { execute: vi.fn() }; + let onSuccess: (newOrderHash?: string) => void; + vi.mocked(TransactionStore).mockImplementation((args, success) => { + onSuccess = success; + return mockTransaction as unknown as TransactionStore; + }); + const newOrderHash = "0xneworderhashfromcallback"; + + await manager.createAddOrderTransaction(addOrderMockArgs); + + onSuccess!(newOrderHash); // Simulate successful execution and subgraph indexing providing a new order hash + + expect(mockQueryClient.invalidateQueries).toHaveBeenCalledWith({ + queryKey: [addOrderMockArgs.queryKey], + }); + }); + + it("should handle failed transaction", async () => { + const mockTransaction = { execute: vi.fn() }; + let onError: () => void; + vi.mocked(TransactionStore).mockImplementation((args, success, error) => { + onError = error; + return mockTransaction as unknown as TransactionStore; + }); + + await manager.createAddOrderTransaction(addOrderMockArgs); + + onError!(); + + expect(mockAddToast).toHaveBeenCalledWith({ + message: "Deployment failed.", + type: "error", + color: "red", + links: [ + { + link: "https://explorer.example.com/tx/0xaddordertxhash", + label: "View on explorer", + }, + ], + }); + }); + }); + + describe("createTakeOrderTransaction", () => { + const takeOrderMockArgs: InternalTransactionArgs & { + raindexClient: RaindexClient; + entity: RaindexOrder; + } = { + txHash: + "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" as `0x${string}`, + chainId: 1, + queryKey: + "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890", + entity: mockSgOrderEntity, + raindexClient: mockRaindexClient, + }; + + beforeEach(() => { + vi.mocked(getExplorerLink).mockResolvedValue( + "https://explorer.example.com/tx/0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + ); + }); + + it("should create transaction with correct name and messages", async () => { + const mockTransaction = { execute: vi.fn() }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createTakeOrderTransaction(takeOrderMockArgs); + + expect(TransactionStore).toHaveBeenCalledWith( + expect.objectContaining({ + name: TransactionName.TAKE_ORDER, + errorMessage: "Take order failed.", + successMessage: "Order taken successfully.", + queryKey: takeOrderMockArgs.queryKey, + }), + expect.any(Function), + expect.any(Function), + ); + }); + + it("should call getExplorerLink with correct params", async () => { + const mockTransaction = { execute: vi.fn() }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createTakeOrderTransaction(takeOrderMockArgs); + + expect(getExplorerLink).toHaveBeenCalledWith( + takeOrderMockArgs.txHash, + takeOrderMockArgs.chainId, + "tx", + ); + expect(TransactionStore).toHaveBeenCalledWith( + expect.objectContaining({ + toastLinks: [ + { + link: "https://explorer.example.com/tx/0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + label: "View on explorer", + }, + ], + }), + expect.any(Function), + expect.any(Function), + ); + }); + + it("should use SDK-based indexing via createSdkIndexingFn for order tracking", async () => { + const mockTransaction = { execute: vi.fn() }; + vi.mocked(TransactionStore).mockImplementation( + () => mockTransaction as unknown as TransactionStore, + ); + + await manager.createTakeOrderTransaction(takeOrderMockArgs); + + const callArgs = vi.mocked(TransactionStore).mock.calls[0][0]; + expect(callArgs.awaitIndexingFn).toBeDefined(); + expect(typeof callArgs.awaitIndexingFn).toBe("function"); + + const mockContext: IndexingContext = { + updateState: vi.fn(), + onSuccess: vi.fn(), + onError: vi.fn(), + links: [], + }; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + vi.mocked(mockRaindexClient.getTransaction).mockResolvedValueOnce({ + value: { + id: "0x0123", + from: "0xowner", + blockNumber: 123n, + timestamp: 1700000000n, + }, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any); + + await callArgs.awaitIndexingFn!(mockContext); + + expect(mockRaindexClient.getTransaction).toHaveBeenCalledWith( + takeOrderMockArgs.chainId, + takeOrderMockArgs.entity.raindex, + takeOrderMockArgs.txHash, + ); + + expect(mockContext.onSuccess).toHaveBeenCalled(); + }); + + it("should handle successful transaction completion", async () => { + const mockTransaction = { execute: vi.fn() }; + let onSuccess: () => void; + vi.mocked(TransactionStore).mockImplementation((args, success) => { + onSuccess = success; + return mockTransaction as unknown as TransactionStore; + }); + + await manager.createTakeOrderTransaction(takeOrderMockArgs); + + onSuccess!(); + + expect(mockQueryClient.invalidateQueries).toHaveBeenCalledWith({ + queryKey: [takeOrderMockArgs.queryKey], + }); + }); + + it("should handle transaction failure", async () => { + const mockTransaction = { execute: vi.fn() }; + let onError: () => void; + vi.mocked(TransactionStore).mockImplementation((args, success, error) => { + onError = error; + return mockTransaction as unknown as TransactionStore; + }); + + await manager.createTakeOrderTransaction(takeOrderMockArgs); + + onError!(); + + expect(mockAddToast).toHaveBeenCalledWith({ + message: "Take order failed.", + type: "error", + color: "red", + links: [ + { + link: "https://explorer.example.com/tx/0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + label: "View on explorer", + }, + ], + }); + }); + }); }); -describe('createSdkIndexingFn', () => { - let mockContext: IndexingContext; - let mockUpdateState: ReturnType; - let mockOnSuccess: ReturnType; - let mockOnError: ReturnType; - - beforeEach(() => { - mockUpdateState = vi.fn(); - mockOnSuccess = vi.fn(); - mockOnError = vi.fn(); - - mockContext = { - updateState: mockUpdateState, - onSuccess: mockOnSuccess, - onError: mockOnError, - links: [{ link: '/existing', label: 'Existing Link' }] - }; - }); - - it('should set PENDING_SUBGRAPH status when called', async () => { - const mockCall = vi.fn().mockResolvedValue({ value: 'test-value' }); - const indexingFn = createSdkIndexingFn({ - call: mockCall, - isSuccess: () => true - }); - - await indexingFn(mockContext); - - expect(mockUpdateState).toHaveBeenCalledWith({ - status: TransactionStatusMessage.PENDING_SUBGRAPH - }); - }); - - it('should call onSuccess when SDK returns valid data and isSuccess returns true', async () => { - const mockCall = vi.fn().mockResolvedValue({ value: ['order1', 'order2'] }); - const indexingFn = createSdkIndexingFn({ - call: mockCall, - isSuccess: (value: string[]) => value.length > 0 - }); - - await indexingFn(mockContext); - - expect(mockUpdateState).toHaveBeenCalledWith({ - status: TransactionStatusMessage.SUCCESS - }); - expect(mockOnSuccess).toHaveBeenCalled(); - expect(mockOnError).not.toHaveBeenCalled(); - }); - - it('should call buildLinks and prepend links to context when provided', async () => { - const mockCall = vi.fn().mockResolvedValue({ value: { id: 'order-123' } }); - const mockBuildLinks = vi - .fn() - .mockReturnValue([{ link: '/orders/order-123', label: 'View Order' }]); - const indexingFn = createSdkIndexingFn({ - call: mockCall, - isSuccess: () => true, - buildLinks: mockBuildLinks - }); - - await indexingFn(mockContext); - - expect(mockBuildLinks).toHaveBeenCalledWith({ id: 'order-123' }); - expect(mockUpdateState).toHaveBeenCalledWith({ - links: [ - { link: '/orders/order-123', label: 'View Order' }, - { link: '/existing', label: 'Existing Link' } - ] - }); - }); - - it('should not update links when buildLinks returns empty array', async () => { - const mockCall = vi.fn().mockResolvedValue({ value: {} }); - const mockBuildLinks = vi.fn().mockReturnValue([]); - const indexingFn = createSdkIndexingFn({ - call: mockCall, - isSuccess: () => true, - buildLinks: mockBuildLinks - }); - - await indexingFn(mockContext); - - // Should not call updateState with links since array is empty - const linksUpdateCalls = mockUpdateState.mock.calls.filter( - (call) => call[0] && typeof call[0] === 'object' && 'links' in call[0] - ); - expect(linksUpdateCalls).toHaveLength(0); - }); - - it('should set SUBGRAPH_TIMEOUT_ERROR and call onError when error contains "timeout"', async () => { - const mockCall = vi.fn().mockResolvedValue({ - error: { readableMsg: 'Request timeout exceeded' } - } as WasmEncodedResult); - const indexingFn = createSdkIndexingFn({ - call: mockCall, - isSuccess: () => true - }); - - await indexingFn(mockContext); - - expect(mockUpdateState).toHaveBeenCalledWith({ - status: TransactionStatusMessage.ERROR, - errorDetails: TransactionStoreErrorMessage.SUBGRAPH_TIMEOUT_ERROR - }); - expect(mockOnError).toHaveBeenCalled(); - expect(mockOnSuccess).not.toHaveBeenCalled(); - }); - - it('should set SUBGRAPH_TIMEOUT_ERROR for case-insensitive timeout detection', async () => { - const mockCall = vi.fn().mockResolvedValue({ - error: { readableMsg: 'TIMEOUT occurred while fetching data' } - } as WasmEncodedResult); - const indexingFn = createSdkIndexingFn({ - call: mockCall, - isSuccess: () => true - }); - - await indexingFn(mockContext); - - expect(mockUpdateState).toHaveBeenCalledWith({ - status: TransactionStatusMessage.ERROR, - errorDetails: TransactionStoreErrorMessage.SUBGRAPH_TIMEOUT_ERROR - }); - }); - - it('should set SUBGRAPH_TIMEOUT_ERROR for SDK TransactionIndexingTimeout error format', async () => { - const mockCall = vi.fn().mockResolvedValue({ - error: { - readableMsg: 'Timeout waiting for transaction 0x123abc to be indexed after 10 attempts.' - } - } as WasmEncodedResult); - const indexingFn = createSdkIndexingFn({ - call: mockCall, - isSuccess: () => true - }); - - await indexingFn(mockContext); - - expect(mockUpdateState).toHaveBeenCalledWith({ - status: TransactionStatusMessage.ERROR, - errorDetails: TransactionStoreErrorMessage.SUBGRAPH_TIMEOUT_ERROR - }); - expect(mockOnError).toHaveBeenCalled(); - expect(mockOnSuccess).not.toHaveBeenCalled(); - }); - - it('should set SUBGRAPH_FAILED and call onError for non-timeout errors', async () => { - const mockCall = vi.fn().mockResolvedValue({ - error: { readableMsg: 'Network connection failed' } - } as WasmEncodedResult); - const indexingFn = createSdkIndexingFn({ - call: mockCall, - isSuccess: () => true - }); - - await indexingFn(mockContext); - - expect(mockUpdateState).toHaveBeenCalledWith({ - status: TransactionStatusMessage.ERROR, - errorDetails: TransactionStoreErrorMessage.SUBGRAPH_FAILED - }); - expect(mockOnError).toHaveBeenCalled(); - }); - - it('should set SUBGRAPH_FAILED when error has no readableMsg', async () => { - const mockCall = vi.fn().mockResolvedValue({ - error: {} - } as WasmEncodedResult); - const indexingFn = createSdkIndexingFn({ - call: mockCall, - isSuccess: () => true - }); - - await indexingFn(mockContext); - - expect(mockUpdateState).toHaveBeenCalledWith({ - status: TransactionStatusMessage.ERROR, - errorDetails: TransactionStoreErrorMessage.SUBGRAPH_FAILED - }); - }); - - it('should set SUBGRAPH_FAILED and call onError when isSuccess returns false', async () => { - const mockCall = vi.fn().mockResolvedValue({ value: [] }); - const indexingFn = createSdkIndexingFn({ - call: mockCall, - isSuccess: (value: unknown[]) => value.length > 0 // empty array fails - }); - - await indexingFn(mockContext); - - expect(mockUpdateState).toHaveBeenCalledWith({ - status: TransactionStatusMessage.ERROR, - errorDetails: TransactionStoreErrorMessage.SUBGRAPH_FAILED - }); - expect(mockOnError).toHaveBeenCalled(); - expect(mockOnSuccess).not.toHaveBeenCalled(); - }); - - it('should set SUBGRAPH_FAILED and call onError when value is undefined', async () => { - const mockCall = vi.fn().mockResolvedValue({ value: undefined }); - const indexingFn = createSdkIndexingFn({ - call: mockCall, - isSuccess: () => true - }); - - await indexingFn(mockContext); - - expect(mockUpdateState).toHaveBeenCalledWith({ - status: TransactionStatusMessage.ERROR, - errorDetails: TransactionStoreErrorMessage.SUBGRAPH_FAILED - }); - expect(mockOnError).toHaveBeenCalled(); - }); - - it('should set SUBGRAPH_FAILED and call onError when SDK call throws an exception', async () => { - const mockCall = vi.fn().mockRejectedValue(new Error('Unexpected error')); - const indexingFn = createSdkIndexingFn({ - call: mockCall, - isSuccess: () => true - }); - - await indexingFn(mockContext); - - expect(mockUpdateState).toHaveBeenCalledWith({ - status: TransactionStatusMessage.ERROR, - errorDetails: TransactionStoreErrorMessage.SUBGRAPH_FAILED - }); - expect(mockOnError).toHaveBeenCalled(); - expect(mockOnSuccess).not.toHaveBeenCalled(); - }); - - it('should work with complex value types', async () => { - type Order = { orderHash: string; owner: string }; - const orders: Order[] = [ - { orderHash: '0x123', owner: '0xabc' }, - { orderHash: '0x456', owner: '0xdef' } - ]; - const mockCall = vi.fn().mockResolvedValue({ value: orders }); - const indexingFn = createSdkIndexingFn({ - call: mockCall, - isSuccess: (value) => Array.isArray(value) && value.length > 0, - buildLinks: (value) => [{ link: `/orders/${value[0].orderHash}`, label: 'View Order' }] - }); - - await indexingFn(mockContext); - - expect(mockUpdateState).toHaveBeenCalledWith({ - links: [ - { link: '/orders/0x123', label: 'View Order' }, - { link: '/existing', label: 'Existing Link' } - ] - }); - expect(mockOnSuccess).toHaveBeenCalled(); - }); +describe("createSdkIndexingFn", () => { + let mockContext: IndexingContext; + let mockUpdateState: ReturnType; + let mockOnSuccess: ReturnType; + let mockOnError: ReturnType; + + beforeEach(() => { + mockUpdateState = vi.fn(); + mockOnSuccess = vi.fn(); + mockOnError = vi.fn(); + + mockContext = { + updateState: mockUpdateState, + onSuccess: mockOnSuccess, + onError: mockOnError, + links: [{ link: "/existing", label: "Existing Link" }], + }; + }); + + it("should set PENDING_SUBGRAPH status when called", async () => { + const mockCall = vi.fn().mockResolvedValue({ value: "test-value" }); + const indexingFn = createSdkIndexingFn({ + call: mockCall, + isSuccess: () => true, + }); + + await indexingFn(mockContext); + + expect(mockUpdateState).toHaveBeenCalledWith({ + status: TransactionStatusMessage.PENDING_SUBGRAPH, + }); + }); + + it("should call onSuccess when SDK returns valid data and isSuccess returns true", async () => { + const mockCall = vi.fn().mockResolvedValue({ value: ["order1", "order2"] }); + const indexingFn = createSdkIndexingFn({ + call: mockCall, + isSuccess: (value: string[]) => value.length > 0, + }); + + await indexingFn(mockContext); + + expect(mockUpdateState).toHaveBeenCalledWith({ + status: TransactionStatusMessage.SUCCESS, + }); + expect(mockOnSuccess).toHaveBeenCalled(); + expect(mockOnError).not.toHaveBeenCalled(); + }); + + it("should call buildLinks and prepend links to context when provided", async () => { + const mockCall = vi.fn().mockResolvedValue({ value: { id: "order-123" } }); + const mockBuildLinks = vi + .fn() + .mockReturnValue([{ link: "/orders/order-123", label: "View Order" }]); + const indexingFn = createSdkIndexingFn({ + call: mockCall, + isSuccess: () => true, + buildLinks: mockBuildLinks, + }); + + await indexingFn(mockContext); + + expect(mockBuildLinks).toHaveBeenCalledWith({ id: "order-123" }); + expect(mockUpdateState).toHaveBeenCalledWith({ + links: [ + { link: "/orders/order-123", label: "View Order" }, + { link: "/existing", label: "Existing Link" }, + ], + }); + }); + + it("should not update links when buildLinks returns empty array", async () => { + const mockCall = vi.fn().mockResolvedValue({ value: {} }); + const mockBuildLinks = vi.fn().mockReturnValue([]); + const indexingFn = createSdkIndexingFn({ + call: mockCall, + isSuccess: () => true, + buildLinks: mockBuildLinks, + }); + + await indexingFn(mockContext); + + // Should not call updateState with links since array is empty + const linksUpdateCalls = mockUpdateState.mock.calls.filter( + (call) => call[0] && typeof call[0] === "object" && "links" in call[0], + ); + expect(linksUpdateCalls).toHaveLength(0); + }); + + it('should set SUBGRAPH_TIMEOUT_ERROR and call onError when error contains "timeout"', async () => { + const mockCall = vi.fn().mockResolvedValue({ + error: { readableMsg: "Request timeout exceeded" }, + } as WasmEncodedResult); + const indexingFn = createSdkIndexingFn({ + call: mockCall, + isSuccess: () => true, + }); + + await indexingFn(mockContext); + + expect(mockUpdateState).toHaveBeenCalledWith({ + status: TransactionStatusMessage.ERROR, + errorDetails: TransactionStoreErrorMessage.SUBGRAPH_TIMEOUT_ERROR, + }); + expect(mockOnError).toHaveBeenCalled(); + expect(mockOnSuccess).not.toHaveBeenCalled(); + }); + + it("should set SUBGRAPH_TIMEOUT_ERROR for case-insensitive timeout detection", async () => { + const mockCall = vi.fn().mockResolvedValue({ + error: { readableMsg: "TIMEOUT occurred while fetching data" }, + } as WasmEncodedResult); + const indexingFn = createSdkIndexingFn({ + call: mockCall, + isSuccess: () => true, + }); + + await indexingFn(mockContext); + + expect(mockUpdateState).toHaveBeenCalledWith({ + status: TransactionStatusMessage.ERROR, + errorDetails: TransactionStoreErrorMessage.SUBGRAPH_TIMEOUT_ERROR, + }); + }); + + it("should set SUBGRAPH_TIMEOUT_ERROR for SDK TransactionIndexingTimeout error format", async () => { + const mockCall = vi.fn().mockResolvedValue({ + error: { + readableMsg: + "Timeout waiting for transaction 0x123abc to be indexed after 10 attempts.", + }, + } as WasmEncodedResult); + const indexingFn = createSdkIndexingFn({ + call: mockCall, + isSuccess: () => true, + }); + + await indexingFn(mockContext); + + expect(mockUpdateState).toHaveBeenCalledWith({ + status: TransactionStatusMessage.ERROR, + errorDetails: TransactionStoreErrorMessage.SUBGRAPH_TIMEOUT_ERROR, + }); + expect(mockOnError).toHaveBeenCalled(); + expect(mockOnSuccess).not.toHaveBeenCalled(); + }); + + it("should set SUBGRAPH_FAILED and call onError for non-timeout errors", async () => { + const mockCall = vi.fn().mockResolvedValue({ + error: { readableMsg: "Network connection failed" }, + } as WasmEncodedResult); + const indexingFn = createSdkIndexingFn({ + call: mockCall, + isSuccess: () => true, + }); + + await indexingFn(mockContext); + + expect(mockUpdateState).toHaveBeenCalledWith({ + status: TransactionStatusMessage.ERROR, + errorDetails: TransactionStoreErrorMessage.SUBGRAPH_FAILED, + }); + expect(mockOnError).toHaveBeenCalled(); + }); + + it("should set SUBGRAPH_FAILED when error has no readableMsg", async () => { + const mockCall = vi.fn().mockResolvedValue({ + error: {}, + } as WasmEncodedResult); + const indexingFn = createSdkIndexingFn({ + call: mockCall, + isSuccess: () => true, + }); + + await indexingFn(mockContext); + + expect(mockUpdateState).toHaveBeenCalledWith({ + status: TransactionStatusMessage.ERROR, + errorDetails: TransactionStoreErrorMessage.SUBGRAPH_FAILED, + }); + }); + + it("should set SUBGRAPH_FAILED and call onError when isSuccess returns false", async () => { + const mockCall = vi.fn().mockResolvedValue({ value: [] }); + const indexingFn = createSdkIndexingFn({ + call: mockCall, + isSuccess: (value: unknown[]) => value.length > 0, // empty array fails + }); + + await indexingFn(mockContext); + + expect(mockUpdateState).toHaveBeenCalledWith({ + status: TransactionStatusMessage.ERROR, + errorDetails: TransactionStoreErrorMessage.SUBGRAPH_FAILED, + }); + expect(mockOnError).toHaveBeenCalled(); + expect(mockOnSuccess).not.toHaveBeenCalled(); + }); + + it("should set SUBGRAPH_FAILED and call onError when value is undefined", async () => { + const mockCall = vi.fn().mockResolvedValue({ value: undefined }); + const indexingFn = createSdkIndexingFn({ + call: mockCall, + isSuccess: () => true, + }); + + await indexingFn(mockContext); + + expect(mockUpdateState).toHaveBeenCalledWith({ + status: TransactionStatusMessage.ERROR, + errorDetails: TransactionStoreErrorMessage.SUBGRAPH_FAILED, + }); + expect(mockOnError).toHaveBeenCalled(); + }); + + it("should set SUBGRAPH_FAILED and call onError when SDK call throws an exception", async () => { + const mockCall = vi.fn().mockRejectedValue(new Error("Unexpected error")); + const indexingFn = createSdkIndexingFn({ + call: mockCall, + isSuccess: () => true, + }); + + await indexingFn(mockContext); + + expect(mockUpdateState).toHaveBeenCalledWith({ + status: TransactionStatusMessage.ERROR, + errorDetails: TransactionStoreErrorMessage.SUBGRAPH_FAILED, + }); + expect(mockOnError).toHaveBeenCalled(); + expect(mockOnSuccess).not.toHaveBeenCalled(); + }); + + it("should work with complex value types", async () => { + type Order = { orderHash: string; owner: string }; + const orders: Order[] = [ + { orderHash: "0x123", owner: "0xabc" }, + { orderHash: "0x456", owner: "0xdef" }, + ]; + const mockCall = vi.fn().mockResolvedValue({ value: orders }); + const indexingFn = createSdkIndexingFn({ + call: mockCall, + isSuccess: (value) => Array.isArray(value) && value.length > 0, + buildLinks: (value) => [ + { link: `/orders/${value[0].orderHash}`, label: "View Order" }, + ], + }); + + await indexingFn(mockContext); + + expect(mockUpdateState).toHaveBeenCalledWith({ + links: [ + { link: "/orders/0x123", label: "View Order" }, + { link: "/existing", label: "Existing Link" }, + ], + }); + expect(mockOnSuccess).toHaveBeenCalled(); + }); }); diff --git a/packages/ui-components/src/__tests__/TransactionProvider.test.ts b/packages/ui-components/src/__tests__/TransactionProvider.test.ts index 6f4129cc95..3b2ccb8d97 100644 --- a/packages/ui-components/src/__tests__/TransactionProvider.test.ts +++ b/packages/ui-components/src/__tests__/TransactionProvider.test.ts @@ -1,89 +1,89 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import { render } from '@testing-library/svelte'; -import TransactionProvider from '../lib/providers/transactions/TransactionProvider.svelte'; -import { TransactionManager } from '../lib/providers/transactions/TransactionManager'; -import { writable } from 'svelte/store'; -import type { Config } from '@wagmi/core'; -import type { ToastProps } from '../lib/types/toast'; +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { render } from "@testing-library/svelte"; +import TransactionProvider from "../lib/providers/transactions/TransactionProvider.svelte"; +import { TransactionManager } from "../lib/providers/transactions/TransactionManager"; +import { writable } from "svelte/store"; +import type { Config } from "@wagmi/core"; +import type { ToastProps } from "../lib/types/toast"; -vi.mock('../lib/providers/transactions/context', () => ({ - setTransactionManagerContext: vi.fn() +vi.mock("../lib/providers/transactions/context", () => ({ + setTransactionManagerContext: vi.fn(), })); -vi.mock('@tanstack/svelte-query', () => ({ - useQueryClient: () => ({ - invalidateQueries: vi.fn() - }) +vi.mock("@tanstack/svelte-query", () => ({ + useQueryClient: () => ({ + invalidateQueries: vi.fn(), + }), })); -import { setTransactionManagerContext } from '../lib/providers/transactions/context'; +import { setTransactionManagerContext } from "../lib/providers/transactions/context"; -describe('TransactionProvider', () => { - const mockAddToast = vi.fn(); - const mockWagmiConfig = writable({ - chains: [], - connectors: [], - storage: { - getItem: vi.fn(), - setItem: vi.fn(), - removeItem: vi.fn() - }, - state: { - connections: new Map(), - status: 'disconnected' - }, - setState: vi.fn(), - subscribe: vi.fn(), - getState: vi.fn(), - destroy: vi.fn() - } as unknown as Config); +describe("TransactionProvider", () => { + const mockAddToast = vi.fn(); + const mockWagmiConfig = writable({ + chains: [], + connectors: [], + storage: { + getItem: vi.fn(), + setItem: vi.fn(), + removeItem: vi.fn(), + }, + state: { + connections: new Map(), + status: "disconnected", + }, + setState: vi.fn(), + subscribe: vi.fn(), + getState: vi.fn(), + destroy: vi.fn(), + } as unknown as Config); - beforeEach(() => { - vi.clearAllMocks(); - }); + beforeEach(() => { + vi.clearAllMocks(); + }); - it('should initialize TransactionManager with correct dependencies', () => { - render(TransactionProvider, { - addToast: mockAddToast, - wagmiConfig: mockWagmiConfig - }); + it("should initialize TransactionManager with correct dependencies", () => { + render(TransactionProvider, { + addToast: mockAddToast, + wagmiConfig: mockWagmiConfig, + }); - expect(setTransactionManagerContext).toHaveBeenCalledTimes(1); - const managerArg = vi.mocked(setTransactionManagerContext).mock.calls[0][0]; - expect(managerArg).toBeInstanceOf(TransactionManager); - }); + expect(setTransactionManagerContext).toHaveBeenCalledTimes(1); + const managerArg = vi.mocked(setTransactionManagerContext).mock.calls[0][0]; + expect(managerArg).toBeInstanceOf(TransactionManager); + }); - it('should pass addToast function to TransactionManager', () => { - render(TransactionProvider, { - addToast: mockAddToast, - wagmiConfig: mockWagmiConfig - }); + it("should pass addToast function to TransactionManager", () => { + render(TransactionProvider, { + addToast: mockAddToast, + wagmiConfig: mockWagmiConfig, + }); - const managerArg = vi.mocked(setTransactionManagerContext).mock - .calls[0][0] as TransactionManager; - const transactions = managerArg.getTransactions(); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let storeValue: any[] = []; - transactions.subscribe((value) => { - storeValue = value; - }); - expect(storeValue).toEqual([]); - }); + const managerArg = vi.mocked(setTransactionManagerContext).mock + .calls[0][0] as TransactionManager; + const transactions = managerArg.getTransactions(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let storeValue: any[] = []; + transactions.subscribe((value) => { + storeValue = value; + }); + expect(storeValue).toEqual([]); + }); - it('should handle toast notifications', () => { - const toast: ToastProps = { - message: 'Test toast', - type: 'success', - color: 'green', - links: [] - }; + it("should handle toast notifications", () => { + const toast: ToastProps = { + message: "Test toast", + type: "success", + color: "green", + links: [], + }; - render(TransactionProvider, { - addToast: mockAddToast, - wagmiConfig: mockWagmiConfig - }); + render(TransactionProvider, { + addToast: mockAddToast, + wagmiConfig: mockWagmiConfig, + }); - mockAddToast(toast); - expect(mockAddToast).toHaveBeenCalledWith(toast); - }); + mockAddToast(toast); + expect(mockAddToast).toHaveBeenCalledWith(toast); + }); }); diff --git a/packages/ui-components/src/__tests__/ValidOrdersSection.test.ts b/packages/ui-components/src/__tests__/ValidOrdersSection.test.ts index e7ffc532e6..8a22271508 100644 --- a/packages/ui-components/src/__tests__/ValidOrdersSection.test.ts +++ b/packages/ui-components/src/__tests__/ValidOrdersSection.test.ts @@ -1,32 +1,32 @@ -import { render, screen } from '@testing-library/svelte'; -import ValidOrdersSection from '$lib/components/deployment/ValidOrdersSection.svelte'; -import type { ValidOrderDetail } from '$lib/types/order'; +import { render, screen } from "@testing-library/svelte"; +import ValidOrdersSection from "$lib/components/deployment/ValidOrdersSection.svelte"; +import type { ValidOrderDetail } from "$lib/types/order"; -describe('validOrdersSection', () => { - const mockvalidOrders: ValidOrderDetail[] = [ - { - dotrain: '', - name: 'order1', - details: { - name: 'Order 1', - description: 'Test order 1', - short_description: 'Short description 1' - } - }, - { - dotrain: '', - name: 'order2', - details: { - name: 'Order 2', - description: 'Test order 2', - short_description: 'Short description 2' - } - } - ]; +describe("validOrdersSection", () => { + const mockvalidOrders: ValidOrderDetail[] = [ + { + dotrain: "", + name: "order1", + details: { + name: "Order 1", + description: "Test order 1", + short_description: "Short description 1", + }, + }, + { + dotrain: "", + name: "order2", + details: { + name: "Order 2", + description: "Test order 2", + short_description: "Short description 2", + }, + }, + ]; - it('should render correct number of OrderShortTile components', () => { - render(ValidOrdersSection, { props: { orders: mockvalidOrders } }); - const orderTiles = screen.getAllByTestId('order-short-tile'); - expect(orderTiles).toHaveLength(mockvalidOrders.length); - }); + it("should render correct number of OrderShortTile components", () => { + render(ValidOrdersSection, { props: { orders: mockvalidOrders } }); + const orderTiles = screen.getAllByTestId("order-short-tile"); + expect(orderTiles).toHaveLength(mockvalidOrders.length); + }); }); diff --git a/packages/ui-components/src/__tests__/VaultBalanceChangeTypeFilter.test.ts b/packages/ui-components/src/__tests__/VaultBalanceChangeTypeFilter.test.ts index c40ec55f4d..b85bba8371 100644 --- a/packages/ui-components/src/__tests__/VaultBalanceChangeTypeFilter.test.ts +++ b/packages/ui-components/src/__tests__/VaultBalanceChangeTypeFilter.test.ts @@ -1,68 +1,84 @@ -import { render, screen, fireEvent } from '@testing-library/svelte'; -import { describe, it, expect } from 'vitest'; -import VaultBalanceChangeTypeFilter from '../lib/components/VaultBalanceChangeTypeFilter.svelte'; -import { VAULT_BALANCE_CHANGE_FILTER_LABELS } from '../lib/utils/vaultBalanceChangeLabels'; - -describe('VaultBalanceChangeTypeFilter', () => { - it('renders the filter dropdown', () => { - render(VaultBalanceChangeTypeFilter); - - expect(screen.getByText('Change Type')).toBeInTheDocument(); - expect(screen.getByTestId('dropdown-checkbox-button')).toBeInTheDocument(); - }); - - it('shows "Select items" when nothing selected', () => { - render(VaultBalanceChangeTypeFilter); - - expect(screen.getByTestId('dropdown-checkbox-button')).toHaveTextContent('Select items'); - }); - - it('renders all filter options in dropdown', async () => { - render(VaultBalanceChangeTypeFilter); - - const button = screen.getByTestId('dropdown-checkbox-button'); - await fireEvent.click(button); - - const options = screen.getAllByTestId('dropdown-checkbox-option'); - expect(options.length).toBeGreaterThanOrEqual(5); - - expect(screen.getByText(VAULT_BALANCE_CHANGE_FILTER_LABELS.deposit)).toBeInTheDocument(); - expect(screen.getByText(VAULT_BALANCE_CHANGE_FILTER_LABELS.withdrawal)).toBeInTheDocument(); - expect(screen.getByText(VAULT_BALANCE_CHANGE_FILTER_LABELS.takeOrder)).toBeInTheDocument(); - expect(screen.getByText(VAULT_BALANCE_CHANGE_FILTER_LABELS.clear)).toBeInTheDocument(); - expect(screen.getByText(VAULT_BALANCE_CHANGE_FILTER_LABELS.clearBounty)).toBeInTheDocument(); - }); - - it('shows "All types" when all filters selected', async () => { - render(VaultBalanceChangeTypeFilter); - - const button = screen.getByTestId('dropdown-checkbox-button'); - await fireEvent.click(button); - - const allTypesCheckbox = screen.getByText('All types').closest('label'); - if (allTypesCheckbox) { - await fireEvent.click(allTypesCheckbox); - } - - expect(screen.getByTestId('dropdown-checkbox-button')).toHaveTextContent('All types'); - }); - - it('shows item count when some filters selected', async () => { - render(VaultBalanceChangeTypeFilter); - - const button = screen.getByTestId('dropdown-checkbox-button'); - await fireEvent.click(button); - - const withdrawalLabel = screen - .getByText(VAULT_BALANCE_CHANGE_FILTER_LABELS.withdrawal) - .closest('label'); - const depositLabel = screen - .getByText(VAULT_BALANCE_CHANGE_FILTER_LABELS.deposit) - .closest('label'); - - if (withdrawalLabel) await fireEvent.click(withdrawalLabel); - if (depositLabel) await fireEvent.click(depositLabel); - - expect(screen.getByTestId('dropdown-checkbox-button')).toHaveTextContent('2 items'); - }); +import { render, screen, fireEvent } from "@testing-library/svelte"; +import { describe, it, expect } from "vitest"; +import VaultBalanceChangeTypeFilter from "../lib/components/VaultBalanceChangeTypeFilter.svelte"; +import { VAULT_BALANCE_CHANGE_FILTER_LABELS } from "../lib/utils/vaultBalanceChangeLabels"; + +describe("VaultBalanceChangeTypeFilter", () => { + it("renders the filter dropdown", () => { + render(VaultBalanceChangeTypeFilter); + + expect(screen.getByText("Change Type")).toBeInTheDocument(); + expect(screen.getByTestId("dropdown-checkbox-button")).toBeInTheDocument(); + }); + + it('shows "Select items" when nothing selected', () => { + render(VaultBalanceChangeTypeFilter); + + expect(screen.getByTestId("dropdown-checkbox-button")).toHaveTextContent( + "Select items", + ); + }); + + it("renders all filter options in dropdown", async () => { + render(VaultBalanceChangeTypeFilter); + + const button = screen.getByTestId("dropdown-checkbox-button"); + await fireEvent.click(button); + + const options = screen.getAllByTestId("dropdown-checkbox-option"); + expect(options.length).toBeGreaterThanOrEqual(5); + + expect( + screen.getByText(VAULT_BALANCE_CHANGE_FILTER_LABELS.deposit), + ).toBeInTheDocument(); + expect( + screen.getByText(VAULT_BALANCE_CHANGE_FILTER_LABELS.withdrawal), + ).toBeInTheDocument(); + expect( + screen.getByText(VAULT_BALANCE_CHANGE_FILTER_LABELS.takeOrder), + ).toBeInTheDocument(); + expect( + screen.getByText(VAULT_BALANCE_CHANGE_FILTER_LABELS.clear), + ).toBeInTheDocument(); + expect( + screen.getByText(VAULT_BALANCE_CHANGE_FILTER_LABELS.clearBounty), + ).toBeInTheDocument(); + }); + + it('shows "All types" when all filters selected', async () => { + render(VaultBalanceChangeTypeFilter); + + const button = screen.getByTestId("dropdown-checkbox-button"); + await fireEvent.click(button); + + const allTypesCheckbox = screen.getByText("All types").closest("label"); + if (allTypesCheckbox) { + await fireEvent.click(allTypesCheckbox); + } + + expect(screen.getByTestId("dropdown-checkbox-button")).toHaveTextContent( + "All types", + ); + }); + + it("shows item count when some filters selected", async () => { + render(VaultBalanceChangeTypeFilter); + + const button = screen.getByTestId("dropdown-checkbox-button"); + await fireEvent.click(button); + + const withdrawalLabel = screen + .getByText(VAULT_BALANCE_CHANGE_FILTER_LABELS.withdrawal) + .closest("label"); + const depositLabel = screen + .getByText(VAULT_BALANCE_CHANGE_FILTER_LABELS.deposit) + .closest("label"); + + if (withdrawalLabel) await fireEvent.click(withdrawalLabel); + if (depositLabel) await fireEvent.click(depositLabel); + + expect(screen.getByTestId("dropdown-checkbox-button")).toHaveTextContent( + "2 items", + ); + }); }); diff --git a/packages/ui-components/src/__tests__/VaultBalanceChangesTable.test.ts b/packages/ui-components/src/__tests__/VaultBalanceChangesTable.test.ts index 66cb719400..59c1010216 100644 --- a/packages/ui-components/src/__tests__/VaultBalanceChangesTable.test.ts +++ b/packages/ui-components/src/__tests__/VaultBalanceChangesTable.test.ts @@ -1,222 +1,245 @@ -import { render, screen, waitFor } from '@testing-library/svelte'; -import { test, vi, describe } from 'vitest'; -import { expect } from '../lib/test/matchers'; -import { QueryClient } from '@tanstack/svelte-query'; -import VaultBalanceChangesTable from '../lib/components/tables/VaultBalanceChangesTable.svelte'; +import { render, screen, waitFor } from "@testing-library/svelte"; +import { test, vi, describe } from "vitest"; +import { expect } from "../lib/test/matchers"; +import { QueryClient } from "@tanstack/svelte-query"; +import VaultBalanceChangesTable from "../lib/components/tables/VaultBalanceChangesTable.svelte"; import type { - RaindexVault, - RaindexVaultBalanceChange, - RaindexVaultBalanceChangeType -} from '@rainlanguage/raindex'; -import { formatTimestampSecondsAsLocal } from '../lib/services/time'; -import { VAULT_BALANCE_CHANGE_LABELS } from '../lib/utils/vaultBalanceChangeLabels'; + RaindexVault, + RaindexVaultBalanceChange, + RaindexVaultBalanceChangeType, +} from "@rainlanguage/raindex"; +import { formatTimestampSecondsAsLocal } from "../lib/services/time"; +import { VAULT_BALANCE_CHANGE_LABELS } from "../lib/utils/vaultBalanceChangeLabels"; const TYPE_DISPLAY_NAMES: Record = { - deposit: 'Deposit', - withdrawal: 'Withdrawal', - takeOrder: 'Take order', - clear: 'Clear', - clearBounty: 'Clear Bounty', - unknown: 'Unknown' + deposit: "Deposit", + withdrawal: "Withdrawal", + takeOrder: "Take order", + clear: "Clear", + clearBounty: "Clear Bounty", + unknown: "Unknown", }; const createMockVaultBalanceChange = ( - overrides: Partial = {} + overrides: Partial = {}, ): RaindexVaultBalanceChange => { - const type = (overrides.type as RaindexVaultBalanceChangeType) || 'withdrawal'; - return { - type, - typeDisplayName: TYPE_DISPLAY_NAMES[type], - amount: BigInt(1000), - formattedAmount: '0.1', - oldBalance: BigInt(5000), - formattedOldBalance: '0.5', - newBalance: BigInt(4000), - formattedNewBalance: '0.4', - timestamp: BigInt(1625247600), - vaultId: BigInt(100), - token: { - id: 'token1', - address: '0xTokenAddress1', - name: 'Token1', - symbol: 'TKN1', - decimals: '4' - }, - transaction: { - id: 'tx1', - from: '0xUser1', - timestamp: BigInt(1625247600), - blockNumber: BigInt(1234567890) - }, - raindex: '0x00', - ...overrides - } as unknown as RaindexVaultBalanceChange; + const type = + (overrides.type as RaindexVaultBalanceChangeType) || "withdrawal"; + return { + type, + typeDisplayName: TYPE_DISPLAY_NAMES[type], + amount: BigInt(1000), + formattedAmount: "0.1", + oldBalance: BigInt(5000), + formattedOldBalance: "0.5", + newBalance: BigInt(4000), + formattedNewBalance: "0.4", + timestamp: BigInt(1625247600), + vaultId: BigInt(100), + token: { + id: "token1", + address: "0xTokenAddress1", + name: "Token1", + symbol: "TKN1", + decimals: "4", + }, + transaction: { + id: "tx1", + from: "0xUser1", + timestamp: BigInt(1625247600), + blockNumber: BigInt(1234567890), + }, + raindex: "0x00", + ...overrides, + } as unknown as RaindexVaultBalanceChange; }; -test('renders the vault list table with correct data', async () => { - const queryClient = new QueryClient(); - - const mockVaultBalanceChanges: RaindexVaultBalanceChange[] = [createMockVaultBalanceChange()]; - const mockVault: RaindexVault = { - id: 'vault1', - getBalanceChanges: vi.fn().mockResolvedValue({ value: mockVaultBalanceChanges }) - } as unknown as RaindexVault; - - render(VaultBalanceChangesTable, { - props: { - vault: mockVault - }, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - const rows = screen.getAllByTestId('bodyRow'); - expect(rows).toHaveLength(1); - }); +test("renders the vault list table with correct data", async () => { + const queryClient = new QueryClient(); + + const mockVaultBalanceChanges: RaindexVaultBalanceChange[] = [ + createMockVaultBalanceChange(), + ]; + const mockVault: RaindexVault = { + id: "vault1", + getBalanceChanges: vi + .fn() + .mockResolvedValue({ value: mockVaultBalanceChanges }), + } as unknown as RaindexVault; + + render(VaultBalanceChangesTable, { + props: { + vault: mockVault, + }, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + const rows = screen.getAllByTestId("bodyRow"); + expect(rows).toHaveLength(1); + }); }); -test('it shows the correct data in the table with combined Info column', async () => { - const queryClient = new QueryClient(); - - const mockVaultBalanceChanges: RaindexVaultBalanceChange[] = [createMockVaultBalanceChange()]; - const mockVault: RaindexVault = { - id: 'vault1', - getBalanceChanges: vi.fn().mockResolvedValue({ value: mockVaultBalanceChanges }) - } as unknown as RaindexVault; - - render(VaultBalanceChangesTable, { - props: { - vault: mockVault - }, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - // Info column now contains both type badge and date - const infoCell = screen.getByTestId('vaultBalanceChangesTableInfo'); - expect(infoCell).toHaveTextContent(VAULT_BALANCE_CHANGE_LABELS.withdrawal); - expect(infoCell).toHaveTextContent(formatTimestampSecondsAsLocal(BigInt('1625247600'))); - - // Transaction column now contains both Sender and Tx - const txCell = screen.getByTestId('vaultBalanceChangesTableTx'); - expect(txCell).toHaveTextContent('Sender:'); - expect(txCell).toHaveTextContent('Tx:'); - - // Balance Change column shows token symbol and amount - const balanceChangeCell = screen.getByTestId('vaultBalanceChangesTableBalanceChange'); - expect(balanceChangeCell).toHaveTextContent('TKN1'); - expect(balanceChangeCell).toHaveTextContent('0.1'); - - // New Balance column shows token symbol and amount - const balanceCell = screen.getByTestId('vaultBalanceChangesTableBalance'); - expect(balanceCell).toHaveTextContent('TKN1'); - expect(balanceCell).toHaveTextContent('0.4'); - }); +test("it shows the correct data in the table with combined Info column", async () => { + const queryClient = new QueryClient(); + + const mockVaultBalanceChanges: RaindexVaultBalanceChange[] = [ + createMockVaultBalanceChange(), + ]; + const mockVault: RaindexVault = { + id: "vault1", + getBalanceChanges: vi + .fn() + .mockResolvedValue({ value: mockVaultBalanceChanges }), + } as unknown as RaindexVault; + + render(VaultBalanceChangesTable, { + props: { + vault: mockVault, + }, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + // Info column now contains both type badge and date + const infoCell = screen.getByTestId("vaultBalanceChangesTableInfo"); + expect(infoCell).toHaveTextContent(VAULT_BALANCE_CHANGE_LABELS.withdrawal); + expect(infoCell).toHaveTextContent( + formatTimestampSecondsAsLocal(BigInt("1625247600")), + ); + + // Transaction column now contains both Sender and Tx + const txCell = screen.getByTestId("vaultBalanceChangesTableTx"); + expect(txCell).toHaveTextContent("Sender:"); + expect(txCell).toHaveTextContent("Tx:"); + + // Balance Change column shows token symbol and amount + const balanceChangeCell = screen.getByTestId( + "vaultBalanceChangesTableBalanceChange", + ); + expect(balanceChangeCell).toHaveTextContent("TKN1"); + expect(balanceChangeCell).toHaveTextContent("0.1"); + + // New Balance column shows token symbol and amount + const balanceCell = screen.getByTestId("vaultBalanceChangesTableBalance"); + expect(balanceCell).toHaveTextContent("TKN1"); + expect(balanceCell).toHaveTextContent("0.4"); + }); }); -describe('type badge labels', () => { - const testCases: { type: RaindexVaultBalanceChangeType; expectedLabel: string }[] = [ - { type: 'deposit', expectedLabel: 'Deposit' }, - { type: 'withdrawal', expectedLabel: 'Withdrawal' }, - { type: 'takeOrder', expectedLabel: 'Take order' }, - { type: 'clear', expectedLabel: 'Clear' }, - { type: 'clearBounty', expectedLabel: 'Clear Bounty' } - ]; - - testCases.forEach(({ type, expectedLabel }) => { - test(`displays ${type} with correct label`, async () => { - const queryClient = new QueryClient(); - - const mockVaultBalanceChanges: RaindexVaultBalanceChange[] = [ - createMockVaultBalanceChange({ type }) - ]; - const mockVault: RaindexVault = { - id: 'vault1', - getBalanceChanges: vi.fn().mockResolvedValue({ value: mockVaultBalanceChanges }) - } as unknown as RaindexVault; - - render(VaultBalanceChangesTable, { - props: { - vault: mockVault - }, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - const infoCell = screen.getByTestId('vaultBalanceChangesTableInfo'); - expect(infoCell).toHaveTextContent(expectedLabel); - }); - }); - }); +describe("type badge labels", () => { + const testCases: { + type: RaindexVaultBalanceChangeType; + expectedLabel: string; + }[] = [ + { type: "deposit", expectedLabel: "Deposit" }, + { type: "withdrawal", expectedLabel: "Withdrawal" }, + { type: "takeOrder", expectedLabel: "Take order" }, + { type: "clear", expectedLabel: "Clear" }, + { type: "clearBounty", expectedLabel: "Clear Bounty" }, + ]; + + testCases.forEach(({ type, expectedLabel }) => { + test(`displays ${type} with correct label`, async () => { + const queryClient = new QueryClient(); + + const mockVaultBalanceChanges: RaindexVaultBalanceChange[] = [ + createMockVaultBalanceChange({ type }), + ]; + const mockVault: RaindexVault = { + id: "vault1", + getBalanceChanges: vi + .fn() + .mockResolvedValue({ value: mockVaultBalanceChanges }), + } as unknown as RaindexVault; + + render(VaultBalanceChangesTable, { + props: { + vault: mockVault, + }, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + const infoCell = screen.getByTestId("vaultBalanceChangesTableInfo"); + expect(infoCell).toHaveTextContent(expectedLabel); + }); + }); + }); }); -describe('type badge colors', () => { - const colorTestCases: { type: RaindexVaultBalanceChangeType; expectedColor: string }[] = [ - { type: 'deposit', expectedColor: 'green' }, - { type: 'withdrawal', expectedColor: 'yellow' }, - { type: 'takeOrder', expectedColor: 'blue' }, - { type: 'clear', expectedColor: 'pink' }, - { type: 'clearBounty', expectedColor: 'purple' } - ]; - - colorTestCases.forEach(({ type, expectedColor }) => { - test(`displays ${type} with ${expectedColor} badge`, async () => { - const queryClient = new QueryClient(); - - const mockVaultBalanceChanges: RaindexVaultBalanceChange[] = [ - createMockVaultBalanceChange({ type }) - ]; - const mockVault: RaindexVault = { - id: 'vault1', - getBalanceChanges: vi.fn().mockResolvedValue({ value: mockVaultBalanceChanges }) - } as unknown as RaindexVault; - - render(VaultBalanceChangesTable, { - props: { - vault: mockVault - }, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - const badge = document.querySelector('#type-tx1'); - expect(badge?.className).toContain(`bg-${expectedColor}-100`); - }); - }); - }); +describe("type badge colors", () => { + const colorTestCases: { + type: RaindexVaultBalanceChangeType; + expectedColor: string; + }[] = [ + { type: "deposit", expectedColor: "green" }, + { type: "withdrawal", expectedColor: "yellow" }, + { type: "takeOrder", expectedColor: "blue" }, + { type: "clear", expectedColor: "pink" }, + { type: "clearBounty", expectedColor: "purple" }, + ]; + + colorTestCases.forEach(({ type, expectedColor }) => { + test(`displays ${type} with ${expectedColor} badge`, async () => { + const queryClient = new QueryClient(); + + const mockVaultBalanceChanges: RaindexVaultBalanceChange[] = [ + createMockVaultBalanceChange({ type }), + ]; + const mockVault: RaindexVault = { + id: "vault1", + getBalanceChanges: vi + .fn() + .mockResolvedValue({ value: mockVaultBalanceChanges }), + } as unknown as RaindexVault; + + render(VaultBalanceChangesTable, { + props: { + vault: mockVault, + }, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + const badge = document.querySelector("#type-tx1"); + expect(badge?.className).toContain(`bg-${expectedColor}-100`); + }); + }); + }); }); -test('renders the filter dropdown', async () => { - const queryClient = new QueryClient(); - const mockVault: RaindexVault = { - id: 'vault1', - getBalanceChanges: vi.fn().mockResolvedValue({ value: [] }) - } as unknown as RaindexVault; - - render(VaultBalanceChangesTable, { - props: { vault: mockVault }, - context: new Map([['$$_queryClient', queryClient]]) - }); - - expect(screen.getByText('Vault balance changes')).toBeInTheDocument(); - expect(screen.getByText('Change Type')).toBeInTheDocument(); - expect(screen.getByTestId('dropdown-checkbox-button')).toBeInTheDocument(); +test("renders the filter dropdown", async () => { + const queryClient = new QueryClient(); + const mockVault: RaindexVault = { + id: "vault1", + getBalanceChanges: vi.fn().mockResolvedValue({ value: [] }), + } as unknown as RaindexVault; + + render(VaultBalanceChangesTable, { + props: { vault: mockVault }, + context: new Map([["$$_queryClient", queryClient]]), + }); + + expect(screen.getByText("Vault balance changes")).toBeInTheDocument(); + expect(screen.getByText("Change Type")).toBeInTheDocument(); + expect(screen.getByTestId("dropdown-checkbox-button")).toBeInTheDocument(); }); -test('calls getBalanceChanges with undefined initially', async () => { - const queryClient = new QueryClient(); - const mockGetBalanceChanges = vi.fn().mockResolvedValue({ value: [] }); - const mockVault: RaindexVault = { - id: 'vault1', - getBalanceChanges: mockGetBalanceChanges - } as unknown as RaindexVault; - - render(VaultBalanceChangesTable, { - props: { vault: mockVault }, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - expect(mockGetBalanceChanges).toHaveBeenCalledWith(1, undefined); - }); +test("calls getBalanceChanges with undefined initially", async () => { + const queryClient = new QueryClient(); + const mockGetBalanceChanges = vi.fn().mockResolvedValue({ value: [] }); + const mockVault: RaindexVault = { + id: "vault1", + getBalanceChanges: mockGetBalanceChanges, + } as unknown as RaindexVault; + + render(VaultBalanceChangesTable, { + props: { vault: mockVault }, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + expect(mockGetBalanceChanges).toHaveBeenCalledWith(1, undefined); + }); }); diff --git a/packages/ui-components/src/__tests__/VaultBalanceChart.test.ts b/packages/ui-components/src/__tests__/VaultBalanceChart.test.ts index 56c44755dc..b84cb636b0 100644 --- a/packages/ui-components/src/__tests__/VaultBalanceChart.test.ts +++ b/packages/ui-components/src/__tests__/VaultBalanceChart.test.ts @@ -1,6 +1,6 @@ // TODO: Issue #1989 // import { render } from '@testing-library/svelte'; -import { test } from 'vitest'; +import { test } from "vitest"; // import { expect, test, vi } from 'vitest'; // import { QueryClient } from '@tanstack/svelte-query'; // import VaultBalanceChart from '../lib/components/charts/VaultBalanceChart.svelte'; @@ -15,18 +15,18 @@ import { test } from 'vitest'; // return { default: MockLightweightChart }; // }); -test('calls getVaultBalanceChanges with correct arguments', async () => { - // const queryClient = new QueryClient(); - // const mockVault: RaindexVault = { - // id: 'vault1', - // getBalanceChanges: vi.fn() - // } as unknown as RaindexVault; - // render(VaultBalanceChart, { - // props: { - // vault: mockVault, - // lightweightChartsTheme: writable({}) - // } as VaultBalanceChartProps, - // context: new Map([['$$_queryClient', queryClient]]) - // }); - // expect(mockVault.getBalanceChanges).toHaveBeenCalledWith(1); +test("calls getVaultBalanceChanges with correct arguments", async () => { + // const queryClient = new QueryClient(); + // const mockVault: RaindexVault = { + // id: 'vault1', + // getBalanceChanges: vi.fn() + // } as unknown as RaindexVault; + // render(VaultBalanceChart, { + // props: { + // vault: mockVault, + // lightweightChartsTheme: writable({}) + // } as VaultBalanceChartProps, + // context: new Map([['$$_queryClient', queryClient]]) + // }); + // expect(mockVault.getBalanceChanges).toHaveBeenCalledWith(1); }); diff --git a/packages/ui-components/src/__tests__/VaultCard.test.ts b/packages/ui-components/src/__tests__/VaultCard.test.ts index 5db4fd65ad..a82cf8fa52 100644 --- a/packages/ui-components/src/__tests__/VaultCard.test.ts +++ b/packages/ui-components/src/__tests__/VaultCard.test.ts @@ -1,112 +1,112 @@ -import { render, screen } from '@testing-library/svelte'; -import { describe, it, expect, vi } from 'vitest'; -import VaultCard from '../lib/components/VaultCard.svelte'; -import type { RaindexVault } from '@rainlanguage/raindex'; -import userEvent from '@testing-library/user-event'; +import { render, screen } from "@testing-library/svelte"; +import { describe, it, expect, vi } from "vitest"; +import VaultCard from "../lib/components/VaultCard.svelte"; +import type { RaindexVault } from "@rainlanguage/raindex"; +import userEvent from "@testing-library/user-event"; // Mock the navigation -vi.mock('$app/navigation', () => ({ - goto: vi.fn() +vi.mock("$app/navigation", () => ({ + goto: vi.fn(), })); const mockVault: RaindexVault = { - id: '0x1234567890abcdef1234567890abcdef12345678', - chainId: 1, - raindex: '0x2222222222222222222222222222222222222222', - token: { - symbol: 'ETH', - name: 'Ethereum', - address: '0x0000000000000000000000000000000000000000', - decimals: 18 - }, - formattedBalance: '1.5' + id: "0x1234567890abcdef1234567890abcdef12345678", + chainId: 1, + raindex: "0x2222222222222222222222222222222222222222", + token: { + symbol: "ETH", + name: "Ethereum", + address: "0x0000000000000000000000000000000000000000", + decimals: 18, + }, + formattedBalance: "1.5", } as unknown as RaindexVault; -describe('VaultCard', () => { - it('renders vault information correctly', () => { - render(VaultCard, { - vault: mockVault - }); - - expect(screen.getByTestId('vault-card')).toBeInTheDocument(); - expect(screen.getByText('ETH')).toBeInTheDocument(); - expect(screen.getByText('1.5')).toBeInTheDocument(); - }); - - it('navigates to vault details when clicked', async () => { - const { goto } = await import('$app/navigation'); - - render(VaultCard, { - vault: mockVault - }); - - const vaultCard = screen.getByTestId('vault-card'); - await userEvent.click(vaultCard); - - expect(goto).toHaveBeenCalledWith( - '/vaults/1-0x2222222222222222222222222222222222222222-0x1234567890abcdef1234567890abcdef12345678' - ); - }); - - it('displays different token symbols correctly', () => { - const daiVault = { - ...mockVault, - chainId: 137, - token: { - ...mockVault.token, - symbol: 'DAI' - }, - formattedBalance: '2500.0' - } as unknown as RaindexVault; - - render(VaultCard, { - vault: daiVault - }); - - expect(screen.getByText('DAI')).toBeInTheDocument(); - expect(screen.getByText('2500.0')).toBeInTheDocument(); - }); - - it('navigates with correct chain ID', async () => { - const { goto } = await import('$app/navigation'); - - const polygonVault = { - ...mockVault, - chainId: 137 - } as unknown as RaindexVault; - - render(VaultCard, { - vault: polygonVault - }); - - const vaultCard = screen.getByTestId('vault-card'); - await userEvent.click(vaultCard); - - expect(goto).toHaveBeenCalledWith( - '/vaults/137-0x2222222222222222222222222222222222222222-0x1234567890abcdef1234567890abcdef12345678' - ); - }); - - it('has proper accessibility attributes', () => { - render(VaultCard, { - vault: mockVault - }); - - const button = screen.getByTestId('vault-card'); - expect(button).toHaveAttribute('type', 'button'); - expect(button.tagName).toBe('BUTTON'); - }); - - it('displays formatted balance correctly', () => { - const vaultWithLongBalance = { - ...mockVault, - formattedBalance: '1,234,567.89' - } as unknown as RaindexVault; - - render(VaultCard, { - vault: vaultWithLongBalance - }); - - expect(screen.getByText('1,234,567.89')).toBeInTheDocument(); - }); +describe("VaultCard", () => { + it("renders vault information correctly", () => { + render(VaultCard, { + vault: mockVault, + }); + + expect(screen.getByTestId("vault-card")).toBeInTheDocument(); + expect(screen.getByText("ETH")).toBeInTheDocument(); + expect(screen.getByText("1.5")).toBeInTheDocument(); + }); + + it("navigates to vault details when clicked", async () => { + const { goto } = await import("$app/navigation"); + + render(VaultCard, { + vault: mockVault, + }); + + const vaultCard = screen.getByTestId("vault-card"); + await userEvent.click(vaultCard); + + expect(goto).toHaveBeenCalledWith( + "/vaults/1-0x2222222222222222222222222222222222222222-0x1234567890abcdef1234567890abcdef12345678", + ); + }); + + it("displays different token symbols correctly", () => { + const daiVault = { + ...mockVault, + chainId: 137, + token: { + ...mockVault.token, + symbol: "DAI", + }, + formattedBalance: "2500.0", + } as unknown as RaindexVault; + + render(VaultCard, { + vault: daiVault, + }); + + expect(screen.getByText("DAI")).toBeInTheDocument(); + expect(screen.getByText("2500.0")).toBeInTheDocument(); + }); + + it("navigates with correct chain ID", async () => { + const { goto } = await import("$app/navigation"); + + const polygonVault = { + ...mockVault, + chainId: 137, + } as unknown as RaindexVault; + + render(VaultCard, { + vault: polygonVault, + }); + + const vaultCard = screen.getByTestId("vault-card"); + await userEvent.click(vaultCard); + + expect(goto).toHaveBeenCalledWith( + "/vaults/137-0x2222222222222222222222222222222222222222-0x1234567890abcdef1234567890abcdef12345678", + ); + }); + + it("has proper accessibility attributes", () => { + render(VaultCard, { + vault: mockVault, + }); + + const button = screen.getByTestId("vault-card"); + expect(button).toHaveAttribute("type", "button"); + expect(button.tagName).toBe("BUTTON"); + }); + + it("displays formatted balance correctly", () => { + const vaultWithLongBalance = { + ...mockVault, + formattedBalance: "1,234,567.89", + } as unknown as RaindexVault; + + render(VaultCard, { + vault: vaultWithLongBalance, + }); + + expect(screen.getByText("1,234,567.89")).toBeInTheDocument(); + }); }); diff --git a/packages/ui-components/src/__tests__/VaultDetail.test.ts b/packages/ui-components/src/__tests__/VaultDetail.test.ts index 7c29847643..a8cef1840c 100644 --- a/packages/ui-components/src/__tests__/VaultDetail.test.ts +++ b/packages/ui-components/src/__tests__/VaultDetail.test.ts @@ -1,262 +1,285 @@ -import { render, screen, waitFor } from '@testing-library/svelte'; -import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; -import { QueryClient } from '@tanstack/svelte-query'; -import VaultDetail from '../lib/components/detail/VaultDetail.svelte'; -import { readable, writable } from 'svelte/store'; -import { darkChartTheme } from '../lib/utils/lightweightChartsThemes'; -import userEvent from '@testing-library/user-event'; -import type { ComponentProps } from 'svelte'; -import { useRaindexClient } from '$lib/hooks/useRaindexClient'; -import { RaindexClient, RaindexVault, type RaindexOrderAsIO } from '@rainlanguage/raindex'; -import { useAccount } from '../lib/providers/wallet/useAccount'; -import { QKEY_VAULT } from '$lib/queries/keys'; -import { useToasts } from '../lib/providers/toasts/useToasts'; -import { invalidateTanstackQueries } from '$lib/queries/queryClient'; -import { getExplorerLink } from '$lib/services/getExplorerLink'; +import { render, screen, waitFor } from "@testing-library/svelte"; +import { describe, it, expect, vi, beforeEach, type Mock } from "vitest"; +import { QueryClient } from "@tanstack/svelte-query"; +import VaultDetail from "../lib/components/detail/VaultDetail.svelte"; +import { readable, writable } from "svelte/store"; +import { darkChartTheme } from "../lib/utils/lightweightChartsThemes"; +import userEvent from "@testing-library/user-event"; +import type { ComponentProps } from "svelte"; +import { useRaindexClient } from "$lib/hooks/useRaindexClient"; +import { + RaindexClient, + RaindexVault, + type RaindexOrderAsIO, +} from "@rainlanguage/raindex"; +import { useAccount } from "../lib/providers/wallet/useAccount"; +import { QKEY_VAULT } from "$lib/queries/keys"; +import { useToasts } from "../lib/providers/toasts/useToasts"; +import { invalidateTanstackQueries } from "$lib/queries/queryClient"; +import { getExplorerLink } from "$lib/services/getExplorerLink"; type VaultDetailProps = ComponentProps; -vi.mock('../lib/providers/wallet/useAccount', () => ({ - useAccount: vi.fn() +vi.mock("../lib/providers/wallet/useAccount", () => ({ + useAccount: vi.fn(), })); -vi.mock('$lib/hooks/useRaindexClient', () => ({ - useRaindexClient: vi.fn() +vi.mock("$lib/hooks/useRaindexClient", () => ({ + useRaindexClient: vi.fn(), })); -vi.mock('@rainlanguage/raindex', () => ({ - RaindexClient: vi.fn() +vi.mock("@rainlanguage/raindex", () => ({ + RaindexClient: vi.fn(), })); -vi.mock('$app/navigation', () => ({ - goto: vi.fn() +vi.mock("$app/navigation", () => ({ + goto: vi.fn(), })); -vi.mock('$lib/services/modal', () => ({ - handleDepositModal: vi.fn(), - handleWithdrawModal: vi.fn() +vi.mock("$lib/services/modal", () => ({ + handleDepositModal: vi.fn(), + handleWithdrawModal: vi.fn(), })); -vi.mock('$lib/queries/queryClient', () => ({ - invalidateTanstackQueries: vi.fn() +vi.mock("$lib/queries/queryClient", () => ({ + invalidateTanstackQueries: vi.fn(), })); -vi.mock('$lib/providers/toasts/useToasts', () => ({ - useToasts: vi.fn() +vi.mock("$lib/providers/toasts/useToasts", () => ({ + useToasts: vi.fn(), })); -vi.mock('$lib/services/getExplorerLink', () => ({ - getExplorerLink: vi.fn() +vi.mock("$lib/services/getExplorerLink", () => ({ + getExplorerLink: vi.fn(), })); const mockErrToast = vi.fn(); const defaultProps: VaultDetailProps = { - chainId: 1, - raindexAddress: '0x00', - id: '100', - lightweightChartsTheme: readable(darkChartTheme), - onDeposit: vi.fn(), - onWithdraw: vi.fn() + chainId: 1, + raindexAddress: "0x00", + id: "100", + lightweightChartsTheme: readable(darkChartTheme), + onDeposit: vi.fn(), + onWithdraw: vi.fn(), } as unknown as VaultDetailProps; const mockMatchesAccount = vi.fn(); -describe('VaultDetail', () => { - let queryClient: QueryClient; - let mockRaindexClient: RaindexClient; - let mockData: RaindexVault; - - beforeEach(async () => { - vi.clearAllMocks(); - queryClient = new QueryClient(); - - mockMatchesAccount.mockReturnValue(true); - - (useAccount as Mock).mockReturnValue({ - matchesAccount: mockMatchesAccount - }); - - (useToasts as Mock).mockReturnValue({ - errToast: mockErrToast, - toasts: writable([]), - removeToast: vi.fn() - }); - - (getExplorerLink as Mock).mockReturnValue( - 'https://etherscan.io/address/0x1234567890123456789012345678901234567890' - ); - - mockRaindexClient = { - getVault: vi.fn() - } as unknown as RaindexClient; - (useRaindexClient as Mock).mockReturnValue(mockRaindexClient); - - mockData = { - id: '1', - chainId: 1, - owner: '0x1234567890123456789012345678901234567890', - vaultId: BigInt(1000), - token: { - id: '0x456', - address: '0x456', - name: 'USDC coin', - symbol: 'USDC', - decimals: '6' - }, - balance: BigInt(100000000000), - formattedBalance: '100000', - ordersAsInput: [], - ordersAsOutput: [], - raindex: '0x00' - } as unknown as RaindexVault; - (mockRaindexClient.getVault as Mock).mockResolvedValue({ value: mockData }); - }); - - it('calls the vault detail query fn with the correct vault id', async () => { - render(VaultDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - expect(mockRaindexClient.getVault).toHaveBeenCalledWith(1, '0x00', '100'); - }); - - it('shows the correct empty message when the query returns no data', async () => { - (mockRaindexClient.getVault as Mock).mockResolvedValue({ value: null }); - - render(VaultDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - expect(screen.getByText('Vault not found')).toBeInTheDocument(); - }); - }); - - it('shows the correct data when the query returns data', async () => { - render(VaultDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - expect(screen.getByTestId('vaultDetailTokenName')).toHaveTextContent('USDC coin'); - expect(screen.getByTestId('vaultDetailVaultId')).toHaveTextContent('Vault ID 0x3e8'); - expect(screen.getByTestId('vaultDetailOwnerAddress')).toHaveTextContent( - 'Owner address 0x123' - ); - expect(screen.getByTestId('vaultDetailTokenAddress')).toHaveTextContent( - 'Token address 0x456' - ); - expect(screen.getByTestId('vaultDetailBalance')).toHaveTextContent('Balance 100000 USDC'); - expect(screen.queryByTestId('vaultDetailOrdersAsInput')).toHaveTextContent('None'); - expect(screen.queryByTestId('vaultDetailOrdersAsOutput')).toHaveTextContent('None'); - }); - }); - - it('shows deposit/withdraw buttons when account matches are met', async () => { - mockMatchesAccount.mockReturnValue(true); - - render(VaultDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - expect(screen.getAllByTestId('deposit-button')).toHaveLength(1); - expect(screen.getAllByTestId('withdraw-button')).toHaveLength(1); - }); - }); - - it("doesn't show deposit/withdraw buttons when account doesn't match", async () => { - mockMatchesAccount.mockReturnValue(false); - - render(VaultDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - expect(screen.queryByTestId('depositOrWithdrawButton')).not.toBeInTheDocument(); - }); - }); - - it('refresh button triggers query invalidation when clicked', async () => { - // @ts-expect-error - we are mutating the mock data - mockData.ordersAsInput = [{ id: '1' }] as unknown as RaindexOrderAsIO[]; - // @ts-expect-error - we are mutating the mock data - mockData.ordersAsOutput = [{ id: '2' }] as unknown as RaindexOrderAsIO[]; - - render(VaultDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(async () => { - const refreshButton = await screen.getByTestId('top-refresh'); - await userEvent.click(refreshButton); - expect(invalidateTanstackQueries).toHaveBeenCalledWith(queryClient, [ - '100', - QKEY_VAULT + '100' - ]); - }); - }); - - it('failed query invalidation triggers a toast', async () => { - // @ts-expect-error - we are mutating the mock data - mockData.ordersAsInput = [{ id: '1' }] as unknown as RaindexOrderAsIO[]; - // @ts-expect-error - we are mutating the mock data - mockData.ordersAsOutput = [{ id: '2' }] as unknown as RaindexOrderAsIO[]; - - (invalidateTanstackQueries as Mock).mockRejectedValue(new Error('Failed to refresh')); - - render(VaultDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(async () => { - const refreshButton = screen.getByTestId('top-refresh'); - await userEvent.click(refreshButton); - expect(mockErrToast).toHaveBeenCalledWith('Failed to refresh'); - }); - }); - - it('renders owner address as explorer link when explorer is available', async () => { - const explorerUrl = 'https://etherscan.io/address/0x1234567890123456789012345678901234567890'; - (getExplorerLink as Mock).mockReturnValue(explorerUrl); - - render(VaultDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - const ownerLink = screen.getByRole('link', { - name: /0x1234567890123456789012345678901234567890/i - }); - expect(ownerLink).toBeInTheDocument(); - expect(ownerLink).toHaveAttribute('href', explorerUrl); - expect(ownerLink).toHaveAttribute('target', '_blank'); - expect(ownerLink).toHaveAttribute('rel', 'noopener noreferrer'); - }); - }); - - it('falls back to Hash component when no explorer link is available', async () => { - (getExplorerLink as Mock).mockReturnValue(''); - - render(VaultDetail, { - props: defaultProps, - context: new Map([['$$_queryClient', queryClient]]) - }); - - await waitFor(() => { - expect(screen.getByTestId('vaultDetailOwnerAddress')).toHaveTextContent('0x123'); - expect( - screen.queryByRole('link', { name: /0x1234567890123456789012345678901234567890/i }) - ).not.toBeInTheDocument(); - }); - }); +describe("VaultDetail", () => { + let queryClient: QueryClient; + let mockRaindexClient: RaindexClient; + let mockData: RaindexVault; + + beforeEach(async () => { + vi.clearAllMocks(); + queryClient = new QueryClient(); + + mockMatchesAccount.mockReturnValue(true); + + (useAccount as Mock).mockReturnValue({ + matchesAccount: mockMatchesAccount, + }); + + (useToasts as Mock).mockReturnValue({ + errToast: mockErrToast, + toasts: writable([]), + removeToast: vi.fn(), + }); + + (getExplorerLink as Mock).mockReturnValue( + "https://etherscan.io/address/0x1234567890123456789012345678901234567890", + ); + + mockRaindexClient = { + getVault: vi.fn(), + } as unknown as RaindexClient; + (useRaindexClient as Mock).mockReturnValue(mockRaindexClient); + + mockData = { + id: "1", + chainId: 1, + owner: "0x1234567890123456789012345678901234567890", + vaultId: BigInt(1000), + token: { + id: "0x456", + address: "0x456", + name: "USDC coin", + symbol: "USDC", + decimals: "6", + }, + balance: BigInt(100000000000), + formattedBalance: "100000", + ordersAsInput: [], + ordersAsOutput: [], + raindex: "0x00", + } as unknown as RaindexVault; + (mockRaindexClient.getVault as Mock).mockResolvedValue({ value: mockData }); + }); + + it("calls the vault detail query fn with the correct vault id", async () => { + render(VaultDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + expect(mockRaindexClient.getVault).toHaveBeenCalledWith(1, "0x00", "100"); + }); + + it("shows the correct empty message when the query returns no data", async () => { + (mockRaindexClient.getVault as Mock).mockResolvedValue({ value: null }); + + render(VaultDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + expect(screen.getByText("Vault not found")).toBeInTheDocument(); + }); + }); + + it("shows the correct data when the query returns data", async () => { + render(VaultDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + expect(screen.getByTestId("vaultDetailTokenName")).toHaveTextContent( + "USDC coin", + ); + expect(screen.getByTestId("vaultDetailVaultId")).toHaveTextContent( + "Vault ID 0x3e8", + ); + expect(screen.getByTestId("vaultDetailOwnerAddress")).toHaveTextContent( + "Owner address 0x123", + ); + expect(screen.getByTestId("vaultDetailTokenAddress")).toHaveTextContent( + "Token address 0x456", + ); + expect(screen.getByTestId("vaultDetailBalance")).toHaveTextContent( + "Balance 100000 USDC", + ); + expect( + screen.queryByTestId("vaultDetailOrdersAsInput"), + ).toHaveTextContent("None"); + expect( + screen.queryByTestId("vaultDetailOrdersAsOutput"), + ).toHaveTextContent("None"); + }); + }); + + it("shows deposit/withdraw buttons when account matches are met", async () => { + mockMatchesAccount.mockReturnValue(true); + + render(VaultDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + expect(screen.getAllByTestId("deposit-button")).toHaveLength(1); + expect(screen.getAllByTestId("withdraw-button")).toHaveLength(1); + }); + }); + + it("doesn't show deposit/withdraw buttons when account doesn't match", async () => { + mockMatchesAccount.mockReturnValue(false); + + render(VaultDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + expect( + screen.queryByTestId("depositOrWithdrawButton"), + ).not.toBeInTheDocument(); + }); + }); + + it("refresh button triggers query invalidation when clicked", async () => { + // @ts-expect-error - we are mutating the mock data + mockData.ordersAsInput = [{ id: "1" }] as unknown as RaindexOrderAsIO[]; + // @ts-expect-error - we are mutating the mock data + mockData.ordersAsOutput = [{ id: "2" }] as unknown as RaindexOrderAsIO[]; + + render(VaultDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(async () => { + const refreshButton = await screen.getByTestId("top-refresh"); + await userEvent.click(refreshButton); + expect(invalidateTanstackQueries).toHaveBeenCalledWith(queryClient, [ + "100", + QKEY_VAULT + "100", + ]); + }); + }); + + it("failed query invalidation triggers a toast", async () => { + // @ts-expect-error - we are mutating the mock data + mockData.ordersAsInput = [{ id: "1" }] as unknown as RaindexOrderAsIO[]; + // @ts-expect-error - we are mutating the mock data + mockData.ordersAsOutput = [{ id: "2" }] as unknown as RaindexOrderAsIO[]; + + (invalidateTanstackQueries as Mock).mockRejectedValue( + new Error("Failed to refresh"), + ); + + render(VaultDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(async () => { + const refreshButton = screen.getByTestId("top-refresh"); + await userEvent.click(refreshButton); + expect(mockErrToast).toHaveBeenCalledWith("Failed to refresh"); + }); + }); + + it("renders owner address as explorer link when explorer is available", async () => { + const explorerUrl = + "https://etherscan.io/address/0x1234567890123456789012345678901234567890"; + (getExplorerLink as Mock).mockReturnValue(explorerUrl); + + render(VaultDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + const ownerLink = screen.getByRole("link", { + name: /0x1234567890123456789012345678901234567890/i, + }); + expect(ownerLink).toBeInTheDocument(); + expect(ownerLink).toHaveAttribute("href", explorerUrl); + expect(ownerLink).toHaveAttribute("target", "_blank"); + expect(ownerLink).toHaveAttribute("rel", "noopener noreferrer"); + }); + }); + + it("falls back to Hash component when no explorer link is available", async () => { + (getExplorerLink as Mock).mockReturnValue(""); + + render(VaultDetail, { + props: defaultProps, + context: new Map([["$$_queryClient", queryClient]]), + }); + + await waitFor(() => { + expect(screen.getByTestId("vaultDetailOwnerAddress")).toHaveTextContent( + "0x123", + ); + expect( + screen.queryByRole("link", { + name: /0x1234567890123456789012345678901234567890/i, + }), + ).not.toBeInTheDocument(); + }); + }); }); diff --git a/packages/ui-components/src/__tests__/VaultIdInformation.test.ts b/packages/ui-components/src/__tests__/VaultIdInformation.test.ts index 36f8d4b55b..c820785468 100644 --- a/packages/ui-components/src/__tests__/VaultIdInformation.test.ts +++ b/packages/ui-components/src/__tests__/VaultIdInformation.test.ts @@ -1,73 +1,74 @@ -import { render, screen } from '@testing-library/svelte'; -import { describe, it, expect } from 'vitest'; -import type { ComponentProps } from 'svelte'; -import VaultIdInformation from '$lib/components/deployment/VaultIdInformation.svelte'; -import { Float, type AccountBalance } from '@rainlanguage/raindex'; +import { render, screen } from "@testing-library/svelte"; +import { describe, it, expect } from "vitest"; +import type { ComponentProps } from "svelte"; +import VaultIdInformation from "$lib/components/deployment/VaultIdInformation.svelte"; +import { Float, type AccountBalance } from "@rainlanguage/raindex"; -export type VaultIdInformationComponentProps = ComponentProps; +export type VaultIdInformationComponentProps = + ComponentProps; -vi.mock('@rainlanguage/raindex', async (importOriginal) => { - return { - ...(await importOriginal()) - }; +vi.mock("@rainlanguage/raindex", async (importOriginal) => { + return { + ...(await importOriginal()), + }; }); -describe('VaultIdInformation', () => { - const defaultProps: VaultIdInformationComponentProps = { - title: 'Test Title', - description: 'Test Description', - tokenBalance: { - value: { - balance: Float.parse('100').value, - formattedBalance: '100' - } as AccountBalance, - loading: false, - error: '' - } - }; +describe("VaultIdInformation", () => { + const defaultProps: VaultIdInformationComponentProps = { + title: "Test Title", + description: "Test Description", + tokenBalance: { + value: { + balance: Float.parse("100").value, + formattedBalance: "100", + } as AccountBalance, + loading: false, + error: "", + }, + }; - it('renders title, description, and token balance', () => { - render(VaultIdInformation, defaultProps); + it("renders title, description, and token balance", () => { + render(VaultIdInformation, defaultProps); - expect(screen.getByText('Test Title')).toBeInTheDocument(); - expect(screen.getByText('Test Description')).toBeInTheDocument(); - expect(screen.getByText('Balance: 100')).toBeInTheDocument(); - }); + expect(screen.getByText("Test Title")).toBeInTheDocument(); + expect(screen.getByText("Test Description")).toBeInTheDocument(); + expect(screen.getByText("Balance: 100")).toBeInTheDocument(); + }); - it('shows loading state when tokenBalance is loading', () => { - const loadingProps: VaultIdInformationComponentProps = { - ...defaultProps, - tokenBalance: { - value: { - balance: Float.parse('0').value, - formattedBalance: '0' - } as AccountBalance, - loading: true, - error: '' - } - }; + it("shows loading state when tokenBalance is loading", () => { + const loadingProps: VaultIdInformationComponentProps = { + ...defaultProps, + tokenBalance: { + value: { + balance: Float.parse("0").value, + formattedBalance: "0", + } as AccountBalance, + loading: true, + error: "", + }, + }; - render(VaultIdInformation, loadingProps); + render(VaultIdInformation, loadingProps); - expect(screen.queryByText(/Balance:/)).not.toBeInTheDocument(); - }); + expect(screen.queryByText(/Balance:/)).not.toBeInTheDocument(); + }); - it('shows error message when tokenBalance has error', () => { - const errorProps: VaultIdInformationComponentProps = { - ...defaultProps, - tokenBalance: { - value: { - balance: Float.parse('0').value, - formattedBalance: '0' - } as AccountBalance, - loading: false, - error: 'Failed to fetch balance' - } - }; + it("shows error message when tokenBalance has error", () => { + const errorProps: VaultIdInformationComponentProps = { + ...defaultProps, + tokenBalance: { + value: { + balance: Float.parse("0").value, + formattedBalance: "0", + } as AccountBalance, + loading: false, + error: "Failed to fetch balance", + }, + }; - render(VaultIdInformation, errorProps); + render(VaultIdInformation, errorProps); - expect(screen.getByText('Failed to fetch balance')).toBeInTheDocument(); - expect(screen.queryByText(/Balance:/)).not.toBeInTheDocument(); - }); + expect(screen.getByText("Failed to fetch balance")).toBeInTheDocument(); + expect(screen.queryByText(/Balance:/)).not.toBeInTheDocument(); + }); }); diff --git a/packages/ui-components/src/__tests__/VaultsListTable.test.ts b/packages/ui-components/src/__tests__/VaultsListTable.test.ts index b68ee2386e..95521759e9 100644 --- a/packages/ui-components/src/__tests__/VaultsListTable.test.ts +++ b/packages/ui-components/src/__tests__/VaultsListTable.test.ts @@ -1,519 +1,531 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { render, screen, waitFor } from '@testing-library/svelte'; -import { describe, it, expect, vi, type Mock, beforeEach } from 'vitest'; -import VaultsListTable from '../lib/components/tables/VaultsListTable.svelte'; -import { readable } from 'svelte/store'; -import { Float, type RaindexVault, type RaindexVaultsList } from '@rainlanguage/raindex'; -import type { ComponentProps } from 'svelte'; -import userEvent from '@testing-library/user-event'; -import { useAccount } from '$lib/providers/wallet/useAccount'; -import { useToasts } from '$lib/providers/toasts/useToasts'; - -vi.mock('$lib/providers/wallet/useAccount', () => ({ - useAccount: vi.fn() +import { render, screen, waitFor } from "@testing-library/svelte"; +import { describe, it, expect, vi, type Mock, beforeEach } from "vitest"; +import VaultsListTable from "../lib/components/tables/VaultsListTable.svelte"; +import { readable } from "svelte/store"; +import { + Float, + type RaindexVault, + type RaindexVaultsList, +} from "@rainlanguage/raindex"; +import type { ComponentProps } from "svelte"; +import userEvent from "@testing-library/user-event"; +import { useAccount } from "$lib/providers/wallet/useAccount"; +import { useToasts } from "$lib/providers/toasts/useToasts"; + +vi.mock("$lib/providers/wallet/useAccount", () => ({ + useAccount: vi.fn(), })); -vi.mock('$lib/providers/toasts/useToasts', () => ({ - useToasts: vi.fn() +vi.mock("$lib/providers/toasts/useToasts", () => ({ + useToasts: vi.fn(), })); -vi.mock('$lib/hooks/useRaindexClient', () => ({ - useRaindexClient: vi.fn() +vi.mock("$lib/hooks/useRaindexClient", () => ({ + useRaindexClient: vi.fn(), })); -import { useRaindexClient } from '$lib/hooks/useRaindexClient'; +import { useRaindexClient } from "$lib/hooks/useRaindexClient"; const mockMatchesAccount = vi.fn(); -const mockAccountStore = readable('0xabcdef1234567890abcdef1234567890abcdef12'); +const mockAccountStore = readable("0xabcdef1234567890abcdef1234567890abcdef12"); const mockGetVaults = vi.fn(); const mockGetTokens = vi.fn(); const mockVault = { - chainId: 1, - id: '0x1234567890abcdef1234567890abcdef12345678', - owner: '0xabcdef1234567890abcdef1234567890abcdef12', - vaultId: BigInt(42), - balance: Float.parse('1000000000000000000').value, - formattedBalance: '1', - token: { - id: '0x1111111111111111111111111111111111111111', - address: '0x1111111111111111111111111111111111111111', - name: 'Mock Token', - symbol: 'MTK', - decimals: '18' - }, - raindex: '0x2222222222222222222222222222222222222222', - ordersAsInput: [], - ordersAsOutput: [] + chainId: 1, + id: "0x1234567890abcdef1234567890abcdef12345678", + owner: "0xabcdef1234567890abcdef1234567890abcdef12", + vaultId: BigInt(42), + balance: Float.parse("1000000000000000000").value, + formattedBalance: "1", + token: { + id: "0x1111111111111111111111111111111111111111", + address: "0x1111111111111111111111111111111111111111", + name: "Mock Token", + symbol: "MTK", + decimals: "18", + }, + raindex: "0x2222222222222222222222222222222222222222", + ordersAsInput: [], + ordersAsOutput: [], } as unknown as RaindexVault; const mockVaultsList = { - items: [mockVault] + items: [mockVault], } as unknown as RaindexVaultsList; -vi.mock('@tanstack/svelte-query'); +vi.mock("@tanstack/svelte-query"); // Hoisted mock stores const { - mockActiveNetworkRefStore, - mockActiveRaindexRefStore, - mockHideZeroBalanceVaultsStore, - mockHideInactiveOrdersVaultsStore, - mockOrderHashStore, - mockShowInactiveOrdersStore, - mockActiveAccountsStore, - mockSelectedChainIdsStore, - mockActiveTokensStore, - mockActiveRaindexAddressesStore, - mockOwnerFilterStore -} = await vi.hoisted(() => import('../lib/__mocks__/stores')); + mockActiveNetworkRefStore, + mockActiveRaindexRefStore, + mockHideZeroBalanceVaultsStore, + mockHideInactiveOrdersVaultsStore, + mockOrderHashStore, + mockShowInactiveOrdersStore, + mockActiveAccountsStore, + mockSelectedChainIdsStore, + mockActiveTokensStore, + mockActiveRaindexAddressesStore, + mockOwnerFilterStore, +} = await vi.hoisted(() => import("../lib/__mocks__/stores")); const defaultProps = { - orderHash: mockOrderHashStore, - showInactiveOrders: mockShowInactiveOrdersStore, - hideZeroBalanceVaults: mockHideZeroBalanceVaultsStore, - hideInactiveOrdersVaults: mockHideInactiveOrdersVaultsStore, - activeNetworkRef: mockActiveNetworkRefStore, - activeRaindexRef: mockActiveRaindexRefStore, - activeAccounts: mockActiveAccountsStore, - selectedChainIds: mockSelectedChainIdsStore, - activeTokens: mockActiveTokensStore, - activeRaindexAddresses: mockActiveRaindexAddressesStore, - ownerFilter: mockOwnerFilterStore + orderHash: mockOrderHashStore, + showInactiveOrders: mockShowInactiveOrdersStore, + hideZeroBalanceVaults: mockHideZeroBalanceVaultsStore, + hideInactiveOrdersVaults: mockHideInactiveOrdersVaultsStore, + activeNetworkRef: mockActiveNetworkRefStore, + activeRaindexRef: mockActiveRaindexRefStore, + activeAccounts: mockActiveAccountsStore, + selectedChainIds: mockSelectedChainIdsStore, + activeTokens: mockActiveTokensStore, + activeRaindexAddresses: mockActiveRaindexAddressesStore, + ownerFilter: mockOwnerFilterStore, }; type VaultsListTableProps = ComponentProps; -describe('VaultsListTable', () => { - beforeEach(() => { - vi.clearAllMocks(); - (useAccount as Mock).mockReturnValue({ - matchesAccount: mockMatchesAccount, - account: mockAccountStore - }); - (useToasts as Mock).mockReturnValue({ - errToast: vi.fn(), - successToast: vi.fn(), - warningToast: vi.fn(), - infoToast: vi.fn() - }); - (useRaindexClient as Mock).mockReturnValue({ - getVaults: mockGetVaults, - getTokens: mockGetTokens, - getUniqueChainIds: vi.fn(() => ({ - value: [1], - error: undefined - })), - getAllNetworks: vi.fn(() => ({ - value: new Map([[1, { name: 'Ethereum', id: 1 }]]), - error: undefined - })), - getAllAccounts: vi.fn(() => ({ - value: new Map(), - error: undefined - })), - getAllRaindexes: vi.fn(() => ({ - value: new Map([ - [ - 'raindex1', - { - key: 'raindex1', - address: '0x1111111111111111111111111111111111111111', - network: { chainId: 1 } - } - ] - ]), - error: undefined - })) - }); - mockGetVaults.mockResolvedValue({ value: { items: [] }, error: undefined }); - mockGetTokens.mockResolvedValue({ value: [], error: undefined }); - }); - it('displays vault information correctly', async () => { - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [mockVaultsList] }, - status: 'success', - isFetching: false, - isFetched: true - }); - return { unsubscribe: () => {} }; - } - })) as Mock; - render(VaultsListTable, defaultProps as unknown as VaultsListTableProps); - expect(screen.getByTestId('vault-network')).toHaveTextContent('Ethereum'); - - const addressesCell = screen.getByTestId('vaultAddresses'); - expect(addressesCell).toBeInTheDocument(); - expect(addressesCell).toHaveTextContent('Vault:'); - expect(addressesCell).toHaveTextContent('Raindex:'); - expect(addressesCell).toHaveTextContent('Owner:'); - - // Token column now contains both token name and balance - const tokenCell = screen.getByTestId('vault-token'); - expect(tokenCell).toHaveTextContent('Mock Token'); - expect(tokenCell).toHaveTextContent('1 MTK'); - }); - - it('shows deposit/withdraw buttons when handlers are provided', async () => { - mockMatchesAccount.mockReturnValue(true); - const handleDepositModal = vi.fn(); - const handleWithdrawModal = vi.fn(); - - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [mockVaultsList] }, - status: 'success', - isFetching: false, - isFetched: true - }); - return { unsubscribe: () => {} }; - } - })) as Mock; - render(VaultsListTable, { - ...defaultProps, - handleDepositModal, - handleWithdrawModal - } as unknown as VaultsListTableProps); - - await waitFor(() => { - const menuButton = screen.getByTestId('vault-menu'); - userEvent.click(menuButton); - expect(screen.getByTestId('deposit-button')).toBeInTheDocument(); - expect(screen.getByTestId('withdraw-button')).toBeInTheDocument(); - }); - }); - - it('handles deposit action', async () => { - mockMatchesAccount.mockReturnValue(true); - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [mockVaultsList] }, - status: 'success', - isFetching: false, - isFetched: true - }); - return { unsubscribe: () => {} }; - } - })) as Mock; - const handleDepositModal = vi.fn(); - const handleWithdrawModal = vi.fn(); - - render(VaultsListTable, { - ...defaultProps, - handleDepositModal, - handleWithdrawModal - } as unknown as VaultsListTableProps); - - const menuButton = screen.getByTestId('vault-menu'); - await userEvent.click(menuButton); - - const depositButton = screen.getByTestId('deposit-button'); - await userEvent.click(depositButton); - - expect(handleDepositModal).toHaveBeenCalledWith(mockVault, undefined, new Map()); - }); - - it('hides action buttons when user is not the vault owner', () => { - mockMatchesAccount.mockReturnValue(false); - render(VaultsListTable, { - ...defaultProps - } as unknown as VaultsListTableProps); - - expect(screen.queryByTestId('vault-menu')).not.toBeInTheDocument(); - }); - - it('displays empty state when no vaults are found', async () => { - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [{ items: [] }] }, - status: 'success', - isFetching: false, - isFetched: true - }); - return { unsubscribe: () => {} }; - } - })) as Mock; - - render(VaultsListTable, defaultProps as unknown as VaultsListTableProps); - expect(screen.getByText('No Vaults Found')).toBeInTheDocument(); - }); - - it('disables selection across different networks and shows tooltip', async () => { - mockMatchesAccount.mockReturnValue(true); - - // Create vaults on different chains - const vault1 = { ...mockVault, chainId: 1, id: 'vault1' }; - const vault2 = { ...mockVault, chainId: 137, id: 'vault2' }; // Different chainId - const mockVaultsListMixed = { - items: [vault1, vault2], - pickByIds: vi.fn((ids: string[]) => ({ - error: undefined, - value: { items: [vault1, vault2].filter((v) => ids.includes(v.id)) } - })) - } as unknown as RaindexVaultsList; - - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - mockQuery.createInfiniteQuery = vi.fn(() => ({ - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [mockVaultsListMixed] }, - status: 'success', - isFetching: false, - isFetched: true - }); - return { unsubscribe: () => {} }; - } - })) as Mock; - - render(VaultsListTable, defaultProps as unknown as VaultsListTableProps); - - // Wait for component to render - await waitFor(() => { - expect(screen.getByText('Input For')).toBeInTheDocument(); - }); - - // Check that both vaults are displayed (different networks) - const networkElements = screen.getAllByTestId('vault-network'); - expect(networkElements).toHaveLength(2); - expect(networkElements[0]).toHaveTextContent('Ethereum'); // chainId 1 - - const vaultCheckboxes = screen.getAllByTestId('vault-checkbox'); - expect(vaultCheckboxes).toHaveLength(2); - - // Select first vault to test basic selection functionality - await userEvent.click(vaultCheckboxes[0]); - expect(vaultCheckboxes[0]).toBeChecked(); - // Second checkbox should be disabled (different network) and show tooltip on hover - await waitFor(() => expect(vaultCheckboxes[1]).toBeDisabled()); - await userEvent.hover(vaultCheckboxes[1]); - await waitFor(() => - expect(screen.getByText('This vault is on a different network')).toBeInTheDocument() - ); - }); - - it('disables selection for zero-balance vaults and shows tooltip', async () => { - mockMatchesAccount.mockReturnValue(true); - - // Create vault with zero balance - const zeroBalanceVault = { - ...mockVault, - balance: Float.parse('0').value, - formattedBalance: '0' - }; - const mockVaultsListZero = { - items: [zeroBalanceVault], - pickByIds: vi.fn((ids: string[]) => ({ - error: undefined, - value: { items: [zeroBalanceVault].filter((v) => ids.includes(v.id)) } - })) - } as unknown as RaindexVaultsList; - - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - mockQuery.createInfiniteQuery = vi.fn(() => ({ - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [mockVaultsListZero] }, - status: 'success', - isFetching: false, - isFetched: true - }); - return { unsubscribe: () => {} }; - } - })) as Mock; - - render(VaultsListTable, defaultProps as unknown as VaultsListTableProps); - - const vaultCheckboxes = screen.getAllByTestId('vault-checkbox'); - const firstCheckbox = vaultCheckboxes[0]; - // Wait for vault table checkbox to render and be disabled - await waitFor(() => { - expect(firstCheckbox).toBeDisabled(); - }); - - // Hover over disabled checkbox to verify tooltip - await userEvent.hover(firstCheckbox!); - await waitFor(() => { - expect(screen.getByText('This vault has a zero balance')).toBeInTheDocument(); - }); - }); - - it('calls onWithdrawAll with only selected vaults', async () => { - mockMatchesAccount.mockReturnValue(true); - const onWithdrawAll = vi.fn(); - - // Create multiple vaults on same chain - const vault1 = { ...mockVault, id: 'vault1', chainId: 1 }; - const vault2 = { ...mockVault, id: 'vault2', chainId: 1 }; - const vault3 = { ...mockVault, id: 'vault3', chainId: 1 }; - - const mockPickByIds = vi.fn((ids: string[]) => ({ - error: undefined, - value: { - items: [vault1, vault2, vault3].filter((v) => ids.includes(v.id)), - concat: vi.fn(() => ({ - error: undefined, - value: mockVaultsListMultiple - })) - } - })); - - const mockVaultsListMultiple = { - items: [vault1, vault2, vault3], - pickByIds: mockPickByIds - } as unknown as RaindexVaultsList; - - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - mockQuery.createInfiniteQuery = vi.fn(() => ({ - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [mockVaultsListMultiple] }, - status: 'success', - isFetching: false, - isFetched: true - }); - return { unsubscribe: () => {} }; - } - })) as Mock; - - render(VaultsListTable, { - ...defaultProps, - onWithdrawAll - } as unknown as VaultsListTableProps); - - // Wait for vault table checkboxes to render - await waitFor(() => { - const vaultCheckboxes = screen.getAllByTestId('vault-checkbox'); - expect(vaultCheckboxes).toHaveLength(3); - }); - - const vaultCheckboxes = screen.getAllByTestId('vault-checkbox'); - - // Select first two vaults - await userEvent.click(vaultCheckboxes[0]); - await userEvent.click(vaultCheckboxes[1]); - - // Click "Withdraw selected" button - const withdrawButton = screen.getByTestId('withdraw-all-button'); - expect(withdrawButton).toHaveTextContent('Withdraw selected (2)'); - await userEvent.click(withdrawButton); - - // Verify onWithdrawAll was called - expect(onWithdrawAll).toHaveBeenCalledTimes(1); - - // Verify it was called with raindexClient and filtered vaultsList - const [clientArg, vaultsListArg] = onWithdrawAll.mock.calls[0]; - expect(clientArg).toBeDefined(); - expect(vaultsListArg).toBeDefined(); - - // Verify pickByIds was called with correct vault IDs - expect(mockPickByIds).toHaveBeenCalledWith(['vault1', 'vault2']); - }); - it('shows correct button text when no vaults are selected', async () => { - const onWithdrawAll = vi.fn(); - - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - mockQuery.createInfiniteQuery = vi.fn(() => ({ - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [mockVaultsList] }, - status: 'success', - isFetching: false, - isFetched: true - }); - return { unsubscribe: () => {} }; - } - })) as Mock; - - render(VaultsListTable, { - ...defaultProps, - onWithdrawAll - } as unknown as VaultsListTableProps); - - const withdrawButton = screen.getByTestId('withdraw-all-button'); - expect(withdrawButton).toHaveTextContent('Withdraw vaults'); - expect(withdrawButton).toBeDisabled(); - }); - - it('passes raindexAddresses filter to getVaults when raindexes are selected', async () => { - const raindexAddress = '0x1111111111111111111111111111111111111111'; - - mockActiveRaindexAddressesStore.mockSetSubscribeValue([raindexAddress]); - - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - mockQuery.createInfiniteQuery = vi.fn((options: any) => { - if (options.queryFn) { - options.queryFn({ pageParam: 0 }); - } - return { - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [{ items: [] }] }, - status: 'success', - isFetching: false, - isFetched: true - }); - return { unsubscribe: () => {} }; - } - }; - }) as Mock; - - render(VaultsListTable, defaultProps as unknown as VaultsListTableProps); - - await waitFor(() => { - expect(mockGetVaults).toHaveBeenCalledWith( - expect.anything(), - expect.objectContaining({ - raindexAddresses: [raindexAddress] - }), - expect.anything() - ); - }); - }); - - it('does not pass raindexAddresses filter when no raindexes are selected', async () => { - mockActiveRaindexAddressesStore.mockSetSubscribeValue([]); - - const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); - mockQuery.createInfiniteQuery = vi.fn((options: any) => { - if (options.queryFn) { - options.queryFn({ pageParam: 0 }); - } - return { - subscribe: (fn: (value: any) => void) => { - fn({ - data: { pages: [{ items: [] }] }, - status: 'success', - isFetching: false, - isFetched: true - }); - return { unsubscribe: () => {} }; - } - }; - }) as Mock; - - render(VaultsListTable, defaultProps as unknown as VaultsListTableProps); - - await waitFor(() => { - expect(mockGetVaults).toHaveBeenCalledWith( - expect.anything(), - expect.objectContaining({ - raindexAddresses: undefined - }), - expect.anything() - ); - }); - }); +describe("VaultsListTable", () => { + beforeEach(() => { + vi.clearAllMocks(); + (useAccount as Mock).mockReturnValue({ + matchesAccount: mockMatchesAccount, + account: mockAccountStore, + }); + (useToasts as Mock).mockReturnValue({ + errToast: vi.fn(), + successToast: vi.fn(), + warningToast: vi.fn(), + infoToast: vi.fn(), + }); + (useRaindexClient as Mock).mockReturnValue({ + getVaults: mockGetVaults, + getTokens: mockGetTokens, + getUniqueChainIds: vi.fn(() => ({ + value: [1], + error: undefined, + })), + getAllNetworks: vi.fn(() => ({ + value: new Map([[1, { name: "Ethereum", id: 1 }]]), + error: undefined, + })), + getAllAccounts: vi.fn(() => ({ + value: new Map(), + error: undefined, + })), + getAllRaindexes: vi.fn(() => ({ + value: new Map([ + [ + "raindex1", + { + key: "raindex1", + address: "0x1111111111111111111111111111111111111111", + network: { chainId: 1 }, + }, + ], + ]), + error: undefined, + })), + }); + mockGetVaults.mockResolvedValue({ value: { items: [] }, error: undefined }); + mockGetTokens.mockResolvedValue({ value: [], error: undefined }); + }); + it("displays vault information correctly", async () => { + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ + subscribe: (fn: (value: any) => void) => { + fn({ + data: { pages: [mockVaultsList] }, + status: "success", + isFetching: false, + isFetched: true, + }); + return { unsubscribe: () => {} }; + }, + })) as Mock; + render(VaultsListTable, defaultProps as unknown as VaultsListTableProps); + expect(screen.getByTestId("vault-network")).toHaveTextContent("Ethereum"); + + const addressesCell = screen.getByTestId("vaultAddresses"); + expect(addressesCell).toBeInTheDocument(); + expect(addressesCell).toHaveTextContent("Vault:"); + expect(addressesCell).toHaveTextContent("Raindex:"); + expect(addressesCell).toHaveTextContent("Owner:"); + + // Token column now contains both token name and balance + const tokenCell = screen.getByTestId("vault-token"); + expect(tokenCell).toHaveTextContent("Mock Token"); + expect(tokenCell).toHaveTextContent("1 MTK"); + }); + + it("shows deposit/withdraw buttons when handlers are provided", async () => { + mockMatchesAccount.mockReturnValue(true); + const handleDepositModal = vi.fn(); + const handleWithdrawModal = vi.fn(); + + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ + subscribe: (fn: (value: any) => void) => { + fn({ + data: { pages: [mockVaultsList] }, + status: "success", + isFetching: false, + isFetched: true, + }); + return { unsubscribe: () => {} }; + }, + })) as Mock; + render(VaultsListTable, { + ...defaultProps, + handleDepositModal, + handleWithdrawModal, + } as unknown as VaultsListTableProps); + + await waitFor(() => { + const menuButton = screen.getByTestId("vault-menu"); + userEvent.click(menuButton); + expect(screen.getByTestId("deposit-button")).toBeInTheDocument(); + expect(screen.getByTestId("withdraw-button")).toBeInTheDocument(); + }); + }); + + it("handles deposit action", async () => { + mockMatchesAccount.mockReturnValue(true); + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ + subscribe: (fn: (value: any) => void) => { + fn({ + data: { pages: [mockVaultsList] }, + status: "success", + isFetching: false, + isFetched: true, + }); + return { unsubscribe: () => {} }; + }, + })) as Mock; + const handleDepositModal = vi.fn(); + const handleWithdrawModal = vi.fn(); + + render(VaultsListTable, { + ...defaultProps, + handleDepositModal, + handleWithdrawModal, + } as unknown as VaultsListTableProps); + + const menuButton = screen.getByTestId("vault-menu"); + await userEvent.click(menuButton); + + const depositButton = screen.getByTestId("deposit-button"); + await userEvent.click(depositButton); + + expect(handleDepositModal).toHaveBeenCalledWith( + mockVault, + undefined, + new Map(), + ); + }); + + it("hides action buttons when user is not the vault owner", () => { + mockMatchesAccount.mockReturnValue(false); + render(VaultsListTable, { + ...defaultProps, + } as unknown as VaultsListTableProps); + + expect(screen.queryByTestId("vault-menu")).not.toBeInTheDocument(); + }); + + it("displays empty state when no vaults are found", async () => { + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({ + subscribe: (fn: (value: any) => void) => { + fn({ + data: { pages: [{ items: [] }] }, + status: "success", + isFetching: false, + isFetched: true, + }); + return { unsubscribe: () => {} }; + }, + })) as Mock; + + render(VaultsListTable, defaultProps as unknown as VaultsListTableProps); + expect(screen.getByText("No Vaults Found")).toBeInTheDocument(); + }); + + it("disables selection across different networks and shows tooltip", async () => { + mockMatchesAccount.mockReturnValue(true); + + // Create vaults on different chains + const vault1 = { ...mockVault, chainId: 1, id: "vault1" }; + const vault2 = { ...mockVault, chainId: 137, id: "vault2" }; // Different chainId + const mockVaultsListMixed = { + items: [vault1, vault2], + pickByIds: vi.fn((ids: string[]) => ({ + error: undefined, + value: { items: [vault1, vault2].filter((v) => ids.includes(v.id)) }, + })), + } as unknown as RaindexVaultsList; + + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + mockQuery.createInfiniteQuery = vi.fn(() => ({ + subscribe: (fn: (value: any) => void) => { + fn({ + data: { pages: [mockVaultsListMixed] }, + status: "success", + isFetching: false, + isFetched: true, + }); + return { unsubscribe: () => {} }; + }, + })) as Mock; + + render(VaultsListTable, defaultProps as unknown as VaultsListTableProps); + + // Wait for component to render + await waitFor(() => { + expect(screen.getByText("Input For")).toBeInTheDocument(); + }); + + // Check that both vaults are displayed (different networks) + const networkElements = screen.getAllByTestId("vault-network"); + expect(networkElements).toHaveLength(2); + expect(networkElements[0]).toHaveTextContent("Ethereum"); // chainId 1 + + const vaultCheckboxes = screen.getAllByTestId("vault-checkbox"); + expect(vaultCheckboxes).toHaveLength(2); + + // Select first vault to test basic selection functionality + await userEvent.click(vaultCheckboxes[0]); + expect(vaultCheckboxes[0]).toBeChecked(); + // Second checkbox should be disabled (different network) and show tooltip on hover + await waitFor(() => expect(vaultCheckboxes[1]).toBeDisabled()); + await userEvent.hover(vaultCheckboxes[1]); + await waitFor(() => + expect( + screen.getByText("This vault is on a different network"), + ).toBeInTheDocument(), + ); + }); + + it("disables selection for zero-balance vaults and shows tooltip", async () => { + mockMatchesAccount.mockReturnValue(true); + + // Create vault with zero balance + const zeroBalanceVault = { + ...mockVault, + balance: Float.parse("0").value, + formattedBalance: "0", + }; + const mockVaultsListZero = { + items: [zeroBalanceVault], + pickByIds: vi.fn((ids: string[]) => ({ + error: undefined, + value: { items: [zeroBalanceVault].filter((v) => ids.includes(v.id)) }, + })), + } as unknown as RaindexVaultsList; + + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + mockQuery.createInfiniteQuery = vi.fn(() => ({ + subscribe: (fn: (value: any) => void) => { + fn({ + data: { pages: [mockVaultsListZero] }, + status: "success", + isFetching: false, + isFetched: true, + }); + return { unsubscribe: () => {} }; + }, + })) as Mock; + + render(VaultsListTable, defaultProps as unknown as VaultsListTableProps); + + const vaultCheckboxes = screen.getAllByTestId("vault-checkbox"); + const firstCheckbox = vaultCheckboxes[0]; + // Wait for vault table checkbox to render and be disabled + await waitFor(() => { + expect(firstCheckbox).toBeDisabled(); + }); + + // Hover over disabled checkbox to verify tooltip + await userEvent.hover(firstCheckbox!); + await waitFor(() => { + expect( + screen.getByText("This vault has a zero balance"), + ).toBeInTheDocument(); + }); + }); + + it("calls onWithdrawAll with only selected vaults", async () => { + mockMatchesAccount.mockReturnValue(true); + const onWithdrawAll = vi.fn(); + + // Create multiple vaults on same chain + const vault1 = { ...mockVault, id: "vault1", chainId: 1 }; + const vault2 = { ...mockVault, id: "vault2", chainId: 1 }; + const vault3 = { ...mockVault, id: "vault3", chainId: 1 }; + + const mockPickByIds = vi.fn((ids: string[]) => ({ + error: undefined, + value: { + items: [vault1, vault2, vault3].filter((v) => ids.includes(v.id)), + concat: vi.fn(() => ({ + error: undefined, + value: mockVaultsListMultiple, + })), + }, + })); + + const mockVaultsListMultiple = { + items: [vault1, vault2, vault3], + pickByIds: mockPickByIds, + } as unknown as RaindexVaultsList; + + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + mockQuery.createInfiniteQuery = vi.fn(() => ({ + subscribe: (fn: (value: any) => void) => { + fn({ + data: { pages: [mockVaultsListMultiple] }, + status: "success", + isFetching: false, + isFetched: true, + }); + return { unsubscribe: () => {} }; + }, + })) as Mock; + + render(VaultsListTable, { + ...defaultProps, + onWithdrawAll, + } as unknown as VaultsListTableProps); + + // Wait for vault table checkboxes to render + await waitFor(() => { + const vaultCheckboxes = screen.getAllByTestId("vault-checkbox"); + expect(vaultCheckboxes).toHaveLength(3); + }); + + const vaultCheckboxes = screen.getAllByTestId("vault-checkbox"); + + // Select first two vaults + await userEvent.click(vaultCheckboxes[0]); + await userEvent.click(vaultCheckboxes[1]); + + // Click "Withdraw selected" button + const withdrawButton = screen.getByTestId("withdraw-all-button"); + expect(withdrawButton).toHaveTextContent("Withdraw selected (2)"); + await userEvent.click(withdrawButton); + + // Verify onWithdrawAll was called + expect(onWithdrawAll).toHaveBeenCalledTimes(1); + + // Verify it was called with raindexClient and filtered vaultsList + const [clientArg, vaultsListArg] = onWithdrawAll.mock.calls[0]; + expect(clientArg).toBeDefined(); + expect(vaultsListArg).toBeDefined(); + + // Verify pickByIds was called with correct vault IDs + expect(mockPickByIds).toHaveBeenCalledWith(["vault1", "vault2"]); + }); + it("shows correct button text when no vaults are selected", async () => { + const onWithdrawAll = vi.fn(); + + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + mockQuery.createInfiniteQuery = vi.fn(() => ({ + subscribe: (fn: (value: any) => void) => { + fn({ + data: { pages: [mockVaultsList] }, + status: "success", + isFetching: false, + isFetched: true, + }); + return { unsubscribe: () => {} }; + }, + })) as Mock; + + render(VaultsListTable, { + ...defaultProps, + onWithdrawAll, + } as unknown as VaultsListTableProps); + + const withdrawButton = screen.getByTestId("withdraw-all-button"); + expect(withdrawButton).toHaveTextContent("Withdraw vaults"); + expect(withdrawButton).toBeDisabled(); + }); + + it("passes raindexAddresses filter to getVaults when raindexes are selected", async () => { + const raindexAddress = "0x1111111111111111111111111111111111111111"; + + mockActiveRaindexAddressesStore.mockSetSubscribeValue([raindexAddress]); + + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + mockQuery.createInfiniteQuery = vi.fn((options: any) => { + if (options.queryFn) { + options.queryFn({ pageParam: 0 }); + } + return { + subscribe: (fn: (value: any) => void) => { + fn({ + data: { pages: [{ items: [] }] }, + status: "success", + isFetching: false, + isFetched: true, + }); + return { unsubscribe: () => {} }; + }, + }; + }) as Mock; + + render(VaultsListTable, defaultProps as unknown as VaultsListTableProps); + + await waitFor(() => { + expect(mockGetVaults).toHaveBeenCalledWith( + expect.anything(), + expect.objectContaining({ + raindexAddresses: [raindexAddress], + }), + expect.anything(), + ); + }); + }); + + it("does not pass raindexAddresses filter when no raindexes are selected", async () => { + mockActiveRaindexAddressesStore.mockSetSubscribeValue([]); + + const mockQuery = vi.mocked(await import("@tanstack/svelte-query")); + mockQuery.createInfiniteQuery = vi.fn((options: any) => { + if (options.queryFn) { + options.queryFn({ pageParam: 0 }); + } + return { + subscribe: (fn: (value: any) => void) => { + fn({ + data: { pages: [{ items: [] }] }, + status: "success", + isFetching: false, + isFetched: true, + }); + return { unsubscribe: () => {} }; + }, + }; + }) as Mock; + + render(VaultsListTable, defaultProps as unknown as VaultsListTableProps); + + await waitFor(() => { + expect(mockGetVaults).toHaveBeenCalledWith( + expect.anything(), + expect.objectContaining({ + raindexAddresses: undefined, + }), + expect.anything(), + ); + }); + }); }); diff --git a/packages/ui-components/src/__tests__/WalletConnect.test.ts b/packages/ui-components/src/__tests__/WalletConnect.test.ts index e2dcba1d04..9c9514826c 100644 --- a/packages/ui-components/src/__tests__/WalletConnect.test.ts +++ b/packages/ui-components/src/__tests__/WalletConnect.test.ts @@ -1,59 +1,61 @@ -import { render, screen } from '@testing-library/svelte'; -import WalletConnect from '../lib/components/wallet/WalletConnect.svelte'; -import { describe, it, vi, beforeEach, expect } from 'vitest'; -import { writable, type Writable } from 'svelte/store'; -import type { AppKit } from '@reown/appkit'; -import truncateEthAddress from 'truncate-eth-address'; -import { useAccount } from '$lib/providers/wallet/useAccount'; - -const { mockConnectedStore } = await vi.hoisted(() => import('$lib/__mocks__/stores')); - -vi.mock('$lib/providers/wallet/useAccount', () => ({ - useAccount: vi.fn() +import { render, screen } from "@testing-library/svelte"; +import WalletConnect from "../lib/components/wallet/WalletConnect.svelte"; +import { describe, it, vi, beforeEach, expect } from "vitest"; +import { writable, type Writable } from "svelte/store"; +import type { AppKit } from "@reown/appkit"; +import truncateEthAddress from "truncate-eth-address"; +import { useAccount } from "$lib/providers/wallet/useAccount"; + +const { mockConnectedStore } = await vi.hoisted( + () => import("$lib/__mocks__/stores"), +); + +vi.mock("$lib/providers/wallet/useAccount", () => ({ + useAccount: vi.fn(), })); -vi.mock('$lib/stores/wagmi', async (importOriginal) => { - const original = (await importOriginal()) as object; - return { - ...original, - appKitModal: writable({} as AppKit), - connected: mockConnectedStore - }; +vi.mock("$lib/stores/wagmi", async (importOriginal) => { + const original = (await importOriginal()) as object; + return { + ...original, + appKitModal: writable({} as AppKit), + connected: mockConnectedStore, + }; }); -describe('WalletConnect component', () => { - beforeEach(() => { - vi.clearAllMocks(); - vi.resetAllMocks(); - }); - - it('displays "Connect" with red icon when wallet is not connected or wrong network', () => { - vi.mocked(useAccount).mockReturnValue({ - account: writable(null), - matchesAccount: vi.fn() - }); - mockConnectedStore.mockSetSubscribeValue(false); - - render(WalletConnect); - - const connectButton = screen.getByTestId('wallet-connect'); - expect(connectButton).toBeInTheDocument(); - }); - - it('displays truncated address when wallet is connected', () => { - vi.mocked(useAccount).mockReturnValue({ - account: writable('0x123'), - matchesAccount: vi.fn() - }); - mockConnectedStore.mockSetSubscribeValue(true); - - render(WalletConnect, { - props: { - connected: mockConnectedStore as Writable, - appKitModal: writable({} as AppKit) - } - }); - - expect(screen.getByText(truncateEthAddress('0x123'))).toBeInTheDocument(); - }); +describe("WalletConnect component", () => { + beforeEach(() => { + vi.clearAllMocks(); + vi.resetAllMocks(); + }); + + it('displays "Connect" with red icon when wallet is not connected or wrong network', () => { + vi.mocked(useAccount).mockReturnValue({ + account: writable(null), + matchesAccount: vi.fn(), + }); + mockConnectedStore.mockSetSubscribeValue(false); + + render(WalletConnect); + + const connectButton = screen.getByTestId("wallet-connect"); + expect(connectButton).toBeInTheDocument(); + }); + + it("displays truncated address when wallet is connected", () => { + vi.mocked(useAccount).mockReturnValue({ + account: writable("0x123"), + matchesAccount: vi.fn(), + }); + mockConnectedStore.mockSetSubscribeValue(true); + + render(WalletConnect, { + props: { + connected: mockConnectedStore as Writable, + appKitModal: writable({} as AppKit), + }, + }); + + expect(screen.getByText(truncateEthAddress("0x123"))).toBeInTheDocument(); + }); }); diff --git a/packages/ui-components/src/__tests__/WalletProvider.test.ts b/packages/ui-components/src/__tests__/WalletProvider.test.ts index af158e76f3..fce99b4b4f 100644 --- a/packages/ui-components/src/__tests__/WalletProvider.test.ts +++ b/packages/ui-components/src/__tests__/WalletProvider.test.ts @@ -1,43 +1,43 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import { render } from '@testing-library/svelte'; -import WalletProvider from '../lib/providers/wallet/WalletProvider.svelte'; -import { readable } from 'svelte/store'; -import type { Account } from '$lib/types/account'; - -vi.mock('../lib/providers/wallet/context', () => ({ - setAccountContext: vi.fn() +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { render } from "@testing-library/svelte"; +import WalletProvider from "../lib/providers/wallet/WalletProvider.svelte"; +import { readable } from "svelte/store"; +import type { Account } from "$lib/types/account"; + +vi.mock("../lib/providers/wallet/context", () => ({ + setAccountContext: vi.fn(), })); -import { setAccountContext } from '../lib/providers/wallet/context'; +import { setAccountContext } from "../lib/providers/wallet/context"; -describe('WalletProvider', () => { - beforeEach(() => { - vi.clearAllMocks(); - }); +describe("WalletProvider", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); - it('should call setAccountContext with the account prop', () => { - const mockAccount = readable('0x123') as Account; + it("should call setAccountContext with the account prop", () => { + const mockAccount = readable("0x123") as Account; - render(WalletProvider, { - props: { - account: mockAccount - } - }); + render(WalletProvider, { + props: { + account: mockAccount, + }, + }); - expect(setAccountContext).toHaveBeenCalledWith(mockAccount); - }); + expect(setAccountContext).toHaveBeenCalledWith(mockAccount); + }); - it('should use default null account when no account is provided', () => { - render(WalletProvider); + it("should use default null account when no account is provided", () => { + render(WalletProvider); - expect(setAccountContext).toHaveBeenCalled(); - const accountArg = vi.mocked(setAccountContext).mock.calls[0][0]; - expect(accountArg).toBeDefined(); + expect(setAccountContext).toHaveBeenCalled(); + const accountArg = vi.mocked(setAccountContext).mock.calls[0][0]; + expect(accountArg).toBeDefined(); - let value; - accountArg.subscribe((v) => { - value = v; - })(); - expect(value).toBeNull(); - }); + let value; + accountArg.subscribe((v) => { + value = v; + })(); + expect(value).toBeNull(); + }); }); diff --git a/packages/ui-components/src/__tests__/awaitTransactionIndexing.test.ts b/packages/ui-components/src/__tests__/awaitTransactionIndexing.test.ts index 2c336b2b83..293e3e317a 100644 --- a/packages/ui-components/src/__tests__/awaitTransactionIndexing.test.ts +++ b/packages/ui-components/src/__tests__/awaitTransactionIndexing.test.ts @@ -1,148 +1,152 @@ -import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; -import type { RaindexOrder, RaindexTransaction } from '@rainlanguage/raindex'; -import { awaitSubgraphIndexing } from '$lib/services/awaitTransactionIndexing'; -import { TransactionStoreErrorMessage } from '$lib/types/transaction'; - -describe('subgraphIndexing', () => { - const mockFetchData = vi.fn(); - - beforeEach(() => { - vi.resetAllMocks(); - vi.useFakeTimers(); - }); - - afterEach(() => { - vi.useRealTimers(); - vi.clearAllMocks(); - }); - - it('should resolve with value when data is successfully fetched', async () => { - const mockData = { id: '0x0123' } as unknown as RaindexTransaction; - mockFetchData.mockResolvedValue({ value: mockData }); - - const resultPromise = awaitSubgraphIndexing({ - chainId: 1, - raindex: '0x123', - txHash: '0x0234', - successMessage: 'Transaction confirmed', - fetchEntityFn: mockFetchData, - isSuccess: (data: RaindexTransaction) => !!data.id - }); - - await vi.advanceTimersByTimeAsync(1000); - - const result = await resultPromise; - - expect(result.value).toBeDefined(); - expect(result.error).toBeUndefined(); - expect(result.value?.txHash).toBe('0x0234'); - expect(result.value?.successMessage).toBe('Transaction confirmed'); - expect(result.value?.data).toEqual(mockData); - - expect(mockFetchData).toHaveBeenCalledWith(1, '0x123', '0x0234'); - expect(mockFetchData).toHaveBeenCalledTimes(1); - }); - - it('should extract order hash from array data', async () => { - const mockOrderData = [ - { - orderHash: 'order123' - } - ] as unknown as RaindexOrder[]; - - mockFetchData.mockResolvedValue({ value: mockOrderData }); - - const resultPromise = awaitSubgraphIndexing({ - chainId: 1, - raindex: '0x123', - txHash: '0x0234', - successMessage: 'Order confirmed', - fetchEntityFn: mockFetchData, - isSuccess: (data: RaindexOrder[]) => data.length > 0 - }); - - await vi.advanceTimersByTimeAsync(1000); - - const result = await resultPromise; - - expect(result.value).toBeDefined(); - expect(result.value?.orderHash).toBe('order123'); - }); - - it('should retry fetching data until maxAttempts is reached', async () => { - mockFetchData.mockResolvedValue({ value: null }); - - const resultPromise = awaitSubgraphIndexing({ - chainId: 1, - raindex: '0x123', - txHash: '0x0234', - successMessage: 'Transaction confirmed', - maxAttempts: 5, - interval: 500, - fetchEntityFn: mockFetchData, - isSuccess: () => false - }); - - for (let i = 0; i < 5; i++) { - await vi.advanceTimersByTimeAsync(500); - } - - const result = await resultPromise; - - expect(result.error).toBeDefined(); - expect(result.value).toBeUndefined(); - expect(result.error).toBe(TransactionStoreErrorMessage.SUBGRAPH_TIMEOUT_ERROR); - expect(mockFetchData).toHaveBeenCalledTimes(5); - }); - - it('should handle fetch errors gracefully', async () => { - mockFetchData.mockResolvedValue({ error: 'error' }); - - const resultPromise = awaitSubgraphIndexing({ - chainId: 1, - raindex: '0x123', - txHash: '0x0234', - successMessage: 'Transaction confirmed', - maxAttempts: 3, - interval: 500, - fetchEntityFn: mockFetchData, - isSuccess: () => true - }); - - for (let i = 0; i < 3; i++) { - await vi.advanceTimersByTimeAsync(500); - } - - const result = await resultPromise; - - expect(result.error).toBeDefined(); - expect(result.value).toBeUndefined(); - expect(result.error).toBe(TransactionStoreErrorMessage.SUBGRAPH_TIMEOUT_ERROR); - }); - - it('should resolve immediately when successful data is found', async () => { - mockFetchData - .mockResolvedValueOnce({ value: null }) - .mockResolvedValueOnce({ value: { id: '0x0123' } as unknown as RaindexTransaction }); - - const resultPromise = awaitSubgraphIndexing({ - chainId: 1, - raindex: '0x123', - txHash: '0x0234', - successMessage: 'Transaction confirmed', - maxAttempts: 5, - interval: 500, - fetchEntityFn: mockFetchData, - isSuccess: (data: RaindexTransaction) => !!data?.id - }); - - await vi.advanceTimersByTimeAsync(500); - await vi.advanceTimersByTimeAsync(500); - - const result = await resultPromise; - - expect(result.value).toBeDefined(); - expect(result.error).toBeUndefined(); - expect(mockFetchData).toHaveBeenCalledTimes(2); - }); +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; +import type { RaindexOrder, RaindexTransaction } from "@rainlanguage/raindex"; +import { awaitSubgraphIndexing } from "$lib/services/awaitTransactionIndexing"; +import { TransactionStoreErrorMessage } from "$lib/types/transaction"; + +describe("subgraphIndexing", () => { + const mockFetchData = vi.fn(); + + beforeEach(() => { + vi.resetAllMocks(); + vi.useFakeTimers(); + }); + + afterEach(() => { + vi.useRealTimers(); + vi.clearAllMocks(); + }); + + it("should resolve with value when data is successfully fetched", async () => { + const mockData = { id: "0x0123" } as unknown as RaindexTransaction; + mockFetchData.mockResolvedValue({ value: mockData }); + + const resultPromise = awaitSubgraphIndexing({ + chainId: 1, + raindex: "0x123", + txHash: "0x0234", + successMessage: "Transaction confirmed", + fetchEntityFn: mockFetchData, + isSuccess: (data: RaindexTransaction) => !!data.id, + }); + + await vi.advanceTimersByTimeAsync(1000); + + const result = await resultPromise; + + expect(result.value).toBeDefined(); + expect(result.error).toBeUndefined(); + expect(result.value?.txHash).toBe("0x0234"); + expect(result.value?.successMessage).toBe("Transaction confirmed"); + expect(result.value?.data).toEqual(mockData); + + expect(mockFetchData).toHaveBeenCalledWith(1, "0x123", "0x0234"); + expect(mockFetchData).toHaveBeenCalledTimes(1); + }); + + it("should extract order hash from array data", async () => { + const mockOrderData = [ + { + orderHash: "order123", + }, + ] as unknown as RaindexOrder[]; + + mockFetchData.mockResolvedValue({ value: mockOrderData }); + + const resultPromise = awaitSubgraphIndexing({ + chainId: 1, + raindex: "0x123", + txHash: "0x0234", + successMessage: "Order confirmed", + fetchEntityFn: mockFetchData, + isSuccess: (data: RaindexOrder[]) => data.length > 0, + }); + + await vi.advanceTimersByTimeAsync(1000); + + const result = await resultPromise; + + expect(result.value).toBeDefined(); + expect(result.value?.orderHash).toBe("order123"); + }); + + it("should retry fetching data until maxAttempts is reached", async () => { + mockFetchData.mockResolvedValue({ value: null }); + + const resultPromise = awaitSubgraphIndexing({ + chainId: 1, + raindex: "0x123", + txHash: "0x0234", + successMessage: "Transaction confirmed", + maxAttempts: 5, + interval: 500, + fetchEntityFn: mockFetchData, + isSuccess: () => false, + }); + + for (let i = 0; i < 5; i++) { + await vi.advanceTimersByTimeAsync(500); + } + + const result = await resultPromise; + + expect(result.error).toBeDefined(); + expect(result.value).toBeUndefined(); + expect(result.error).toBe( + TransactionStoreErrorMessage.SUBGRAPH_TIMEOUT_ERROR, + ); + expect(mockFetchData).toHaveBeenCalledTimes(5); + }); + + it("should handle fetch errors gracefully", async () => { + mockFetchData.mockResolvedValue({ error: "error" }); + + const resultPromise = awaitSubgraphIndexing({ + chainId: 1, + raindex: "0x123", + txHash: "0x0234", + successMessage: "Transaction confirmed", + maxAttempts: 3, + interval: 500, + fetchEntityFn: mockFetchData, + isSuccess: () => true, + }); + + for (let i = 0; i < 3; i++) { + await vi.advanceTimersByTimeAsync(500); + } + + const result = await resultPromise; + + expect(result.error).toBeDefined(); + expect(result.value).toBeUndefined(); + expect(result.error).toBe( + TransactionStoreErrorMessage.SUBGRAPH_TIMEOUT_ERROR, + ); + }); + + it("should resolve immediately when successful data is found", async () => { + mockFetchData.mockResolvedValueOnce({ value: null }).mockResolvedValueOnce({ + value: { id: "0x0123" } as unknown as RaindexTransaction, + }); + + const resultPromise = awaitSubgraphIndexing({ + chainId: 1, + raindex: "0x123", + txHash: "0x0234", + successMessage: "Transaction confirmed", + maxAttempts: 5, + interval: 500, + fetchEntityFn: mockFetchData, + isSuccess: (data: RaindexTransaction) => !!data?.id, + }); + + await vi.advanceTimersByTimeAsync(500); + await vi.advanceTimersByTimeAsync(500); + + const result = await resultPromise; + + expect(result.value).toBeDefined(); + expect(result.error).toBeUndefined(); + expect(mockFetchData).toHaveBeenCalledTimes(2); + }); }); diff --git a/packages/ui-components/src/__tests__/breadcrumbs.test.ts b/packages/ui-components/src/__tests__/breadcrumbs.test.ts index 5b021f3537..17aab1a3d0 100644 --- a/packages/ui-components/src/__tests__/breadcrumbs.test.ts +++ b/packages/ui-components/src/__tests__/breadcrumbs.test.ts @@ -1,29 +1,29 @@ -import { expect, test } from 'vitest'; -import { generateBreadcrumbs } from '../lib/utils/breadcrumbs'; +import { expect, test } from "vitest"; +import { generateBreadcrumbs } from "../lib/utils/breadcrumbs"; -test('generateBreadcrumbs splits a path into segments, excluding current page, with uppercase labels', () => { - const path = '/my/cool/path/12345/abc/$$$az'; - const crumbs = generateBreadcrumbs(path); +test("generateBreadcrumbs splits a path into segments, excluding current page, with uppercase labels", () => { + const path = "/my/cool/path/12345/abc/$$$az"; + const crumbs = generateBreadcrumbs(path); - expect(crumbs.length).toEqual(5); - expect(crumbs[0]).toEqual({ - label: 'my', - href: '/my' - }); - expect(crumbs[1]).toEqual({ - label: 'cool', - href: '/my/cool' - }); - expect(crumbs[2]).toEqual({ - label: 'path', - href: '/my/cool/path' - }); - expect(crumbs[3]).toEqual({ - label: '12345', - href: '/my/cool/path/12345' - }); - expect(crumbs[4]).toEqual({ - label: 'abc', - href: '/my/cool/path/12345/abc' - }); + expect(crumbs.length).toEqual(5); + expect(crumbs[0]).toEqual({ + label: "my", + href: "/my", + }); + expect(crumbs[1]).toEqual({ + label: "cool", + href: "/my/cool", + }); + expect(crumbs[2]).toEqual({ + label: "path", + href: "/my/cool/path", + }); + expect(crumbs[3]).toEqual({ + label: "12345", + href: "/my/cool/path/12345", + }); + expect(crumbs[4]).toEqual({ + label: "abc", + href: "/my/cool/path/12345/abc", + }); }); diff --git a/packages/ui-components/src/__tests__/getExplorerLink.test.ts b/packages/ui-components/src/__tests__/getExplorerLink.test.ts index b63520eb08..65cc7032ab 100644 --- a/packages/ui-components/src/__tests__/getExplorerLink.test.ts +++ b/packages/ui-components/src/__tests__/getExplorerLink.test.ts @@ -1,21 +1,23 @@ -import { getExplorerLink } from '../lib/services/getExplorerLink'; +import { getExplorerLink } from "../lib/services/getExplorerLink"; -vi.mock('viem/chains', () => ({ - mainnet: { - id: 999, - blockExplorers: { - default: { - url: 'https://etherscan.io' - } - } - } +vi.mock("viem/chains", () => ({ + mainnet: { + id: 999, + blockExplorers: { + default: { + url: "https://etherscan.io", + }, + }, + }, })); -describe('getExplorerLink', () => { - it('should return the explorer link', () => { - expect(getExplorerLink('0x123', 999, 'tx')).toBe('https://etherscan.io/tx/0x123'); - }); - it('should return an empty string if the chain is not found', () => { - expect(getExplorerLink('0x123', 1, 'tx')).toBe(''); - }); +describe("getExplorerLink", () => { + it("should return the explorer link", () => { + expect(getExplorerLink("0x123", 999, "tx")).toBe( + "https://etherscan.io/tx/0x123", + ); + }); + it("should return an empty string if the chain is not found", () => { + expect(getExplorerLink("0x123", 1, "tx")).toBe(""); + }); }); diff --git a/packages/ui-components/src/__tests__/handleShareChoices.test.ts b/packages/ui-components/src/__tests__/handleShareChoices.test.ts index 5c8d7983bd..aeea95698c 100644 --- a/packages/ui-components/src/__tests__/handleShareChoices.test.ts +++ b/packages/ui-components/src/__tests__/handleShareChoices.test.ts @@ -1,52 +1,54 @@ -import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; -import { handleShareChoices } from '../lib/services/handleShareChoices'; -import { RaindexOrderBuilder } from '@rainlanguage/raindex'; +import { describe, it, expect, vi, beforeEach, type Mock } from "vitest"; +import { handleShareChoices } from "../lib/services/handleShareChoices"; +import { RaindexOrderBuilder } from "@rainlanguage/raindex"; -vi.mock('@rainlanguage/raindex', () => ({ - RaindexOrderBuilder: vi.fn() +vi.mock("@rainlanguage/raindex", () => ({ + RaindexOrderBuilder: vi.fn(), })); -describe('handleShareChoices', () => { - let builderInstance: RaindexOrderBuilder; - const mockRegistryUrl = 'https://example.com/registry'; - - beforeEach(() => { - builderInstance = { - serializeState: vi.fn() - } as unknown as RaindexOrderBuilder; - - Object.assign(navigator, { - clipboard: { - writeText: vi.fn() - } - }); - vi.mock('$app/stores', () => ({ - page: { - subscribe: vi.fn((fn) => { - fn({ url: new URL('http://example.com') }); - return () => {}; - }) - } - })); - }); - - it('should share the choices with state and registry', async () => { - (builderInstance.serializeState as Mock).mockReturnValue({ value: 'mockState123' }); - - await handleShareChoices(builderInstance, mockRegistryUrl); - - expect(navigator.clipboard.writeText).toHaveBeenCalledWith( - 'http://example.com/?state=mockState123®istry=https%3A%2F%2Fexample.com%2Fregistry' - ); - }); - - it('should handle null state', async () => { - (builderInstance.serializeState as Mock).mockReturnValue({ value: null }); - - await handleShareChoices(builderInstance, mockRegistryUrl); - - expect(navigator.clipboard.writeText).toHaveBeenCalledWith( - 'http://example.com/?state=®istry=https%3A%2F%2Fexample.com%2Fregistry' - ); - }); +describe("handleShareChoices", () => { + let builderInstance: RaindexOrderBuilder; + const mockRegistryUrl = "https://example.com/registry"; + + beforeEach(() => { + builderInstance = { + serializeState: vi.fn(), + } as unknown as RaindexOrderBuilder; + + Object.assign(navigator, { + clipboard: { + writeText: vi.fn(), + }, + }); + vi.mock("$app/stores", () => ({ + page: { + subscribe: vi.fn((fn) => { + fn({ url: new URL("http://example.com") }); + return () => {}; + }), + }, + })); + }); + + it("should share the choices with state and registry", async () => { + (builderInstance.serializeState as Mock).mockReturnValue({ + value: "mockState123", + }); + + await handleShareChoices(builderInstance, mockRegistryUrl); + + expect(navigator.clipboard.writeText).toHaveBeenCalledWith( + "http://example.com/?state=mockState123®istry=https%3A%2F%2Fexample.com%2Fregistry", + ); + }); + + it("should handle null state", async () => { + (builderInstance.serializeState as Mock).mockReturnValue({ value: null }); + + await handleShareChoices(builderInstance, mockRegistryUrl); + + expect(navigator.clipboard.writeText).toHaveBeenCalledWith( + "http://example.com/?state=®istry=https%3A%2F%2Fexample.com%2Fregistry", + ); + }); }); diff --git a/packages/ui-components/src/__tests__/hex.test.ts b/packages/ui-components/src/__tests__/hex.test.ts index 2f41e74a71..5af2d21470 100644 --- a/packages/ui-components/src/__tests__/hex.test.ts +++ b/packages/ui-components/src/__tests__/hex.test.ts @@ -1,47 +1,47 @@ -import { expect, test } from 'vitest'; -import { HEX_INPUT_REGEX } from '../lib/utils/hex'; +import { expect, test } from "vitest"; +import { HEX_INPUT_REGEX } from "../lib/utils/hex"; -test('HEX_INPUT_REGEX matches user typing hex input', () => { - expect(HEX_INPUT_REGEX.test('a')).toBeTruthy(); - expect(HEX_INPUT_REGEX.test('ab')).toBeTruthy(); - expect(HEX_INPUT_REGEX.test('abc')).toBeTruthy(); - expect(HEX_INPUT_REGEX.test('abcdef1234567890')).toBeTruthy(); - expect(HEX_INPUT_REGEX.test('1')).toBeTruthy(); - expect(HEX_INPUT_REGEX.test('12')).toBeTruthy(); - expect(HEX_INPUT_REGEX.test('123')).toBeTruthy(); - expect(HEX_INPUT_REGEX.test('1234567890abcdef')).toBeTruthy(); +test("HEX_INPUT_REGEX matches user typing hex input", () => { + expect(HEX_INPUT_REGEX.test("a")).toBeTruthy(); + expect(HEX_INPUT_REGEX.test("ab")).toBeTruthy(); + expect(HEX_INPUT_REGEX.test("abc")).toBeTruthy(); + expect(HEX_INPUT_REGEX.test("abcdef1234567890")).toBeTruthy(); + expect(HEX_INPUT_REGEX.test("1")).toBeTruthy(); + expect(HEX_INPUT_REGEX.test("12")).toBeTruthy(); + expect(HEX_INPUT_REGEX.test("123")).toBeTruthy(); + expect(HEX_INPUT_REGEX.test("1234567890abcdef")).toBeTruthy(); }); test('HEX_INPUT_REGEX matches user typing hex input prefixed by "0x"', () => { - expect(HEX_INPUT_REGEX.test('0')).toBeTruthy(); - expect(HEX_INPUT_REGEX.test('0x')).toBeTruthy(); - expect(HEX_INPUT_REGEX.test('0xa')).toBeTruthy(); - expect(HEX_INPUT_REGEX.test('0xab')).toBeTruthy(); - expect(HEX_INPUT_REGEX.test('0xabc')).toBeTruthy(); - expect(HEX_INPUT_REGEX.test('0xabcdef1234567890')).toBeTruthy(); - expect(HEX_INPUT_REGEX.test('0x1')).toBeTruthy(); - expect(HEX_INPUT_REGEX.test('0x12')).toBeTruthy(); - expect(HEX_INPUT_REGEX.test('0x123')).toBeTruthy(); - expect(HEX_INPUT_REGEX.test('0x1234567890abcdef')).toBeTruthy(); + expect(HEX_INPUT_REGEX.test("0")).toBeTruthy(); + expect(HEX_INPUT_REGEX.test("0x")).toBeTruthy(); + expect(HEX_INPUT_REGEX.test("0xa")).toBeTruthy(); + expect(HEX_INPUT_REGEX.test("0xab")).toBeTruthy(); + expect(HEX_INPUT_REGEX.test("0xabc")).toBeTruthy(); + expect(HEX_INPUT_REGEX.test("0xabcdef1234567890")).toBeTruthy(); + expect(HEX_INPUT_REGEX.test("0x1")).toBeTruthy(); + expect(HEX_INPUT_REGEX.test("0x12")).toBeTruthy(); + expect(HEX_INPUT_REGEX.test("0x123")).toBeTruthy(); + expect(HEX_INPUT_REGEX.test("0x1234567890abcdef")).toBeTruthy(); }); -test('HEX_INPUT_REGEX does not match user typing invalid hex input', () => { - expect(HEX_INPUT_REGEX.test('0xx')).toBeFalsy(); - expect(HEX_INPUT_REGEX.test('0xg')).toBeFalsy(); - expect(HEX_INPUT_REGEX.test('0xag')).toBeFalsy(); - expect(HEX_INPUT_REGEX.test('0xabg')).toBeFalsy(); - expect(HEX_INPUT_REGEX.test('0xabcdef1234567890g')).toBeFalsy(); - expect(HEX_INPUT_REGEX.test('0x1g')).toBeFalsy(); - expect(HEX_INPUT_REGEX.test('0x12g')).toBeFalsy(); - expect(HEX_INPUT_REGEX.test('0x123g')).toBeFalsy(); - expect(HEX_INPUT_REGEX.test('0x1234567890abcdefg')).toBeFalsy(); +test("HEX_INPUT_REGEX does not match user typing invalid hex input", () => { + expect(HEX_INPUT_REGEX.test("0xx")).toBeFalsy(); + expect(HEX_INPUT_REGEX.test("0xg")).toBeFalsy(); + expect(HEX_INPUT_REGEX.test("0xag")).toBeFalsy(); + expect(HEX_INPUT_REGEX.test("0xabg")).toBeFalsy(); + expect(HEX_INPUT_REGEX.test("0xabcdef1234567890g")).toBeFalsy(); + expect(HEX_INPUT_REGEX.test("0x1g")).toBeFalsy(); + expect(HEX_INPUT_REGEX.test("0x12g")).toBeFalsy(); + expect(HEX_INPUT_REGEX.test("0x123g")).toBeFalsy(); + expect(HEX_INPUT_REGEX.test("0x1234567890abcdefg")).toBeFalsy(); - expect(HEX_INPUT_REGEX.test('g')).toBeFalsy(); - expect(HEX_INPUT_REGEX.test('ag')).toBeFalsy(); - expect(HEX_INPUT_REGEX.test('abg')).toBeFalsy(); - expect(HEX_INPUT_REGEX.test('abcdef1234567890g')).toBeFalsy(); - expect(HEX_INPUT_REGEX.test('1g')).toBeFalsy(); - expect(HEX_INPUT_REGEX.test('12g')).toBeFalsy(); - expect(HEX_INPUT_REGEX.test('123g')).toBeFalsy(); - expect(HEX_INPUT_REGEX.test('1234567890abcdefg')).toBeFalsy(); + expect(HEX_INPUT_REGEX.test("g")).toBeFalsy(); + expect(HEX_INPUT_REGEX.test("ag")).toBeFalsy(); + expect(HEX_INPUT_REGEX.test("abg")).toBeFalsy(); + expect(HEX_INPUT_REGEX.test("abcdef1234567890g")).toBeFalsy(); + expect(HEX_INPUT_REGEX.test("1g")).toBeFalsy(); + expect(HEX_INPUT_REGEX.test("12g")).toBeFalsy(); + expect(HEX_INPUT_REGEX.test("123g")).toBeFalsy(); + expect(HEX_INPUT_REGEX.test("1234567890abcdefg")).toBeFalsy(); }); diff --git a/packages/ui-components/src/__tests__/loadRegistryUrl.test.ts b/packages/ui-components/src/__tests__/loadRegistryUrl.test.ts index e2aec3925b..52f7586c5d 100644 --- a/packages/ui-components/src/__tests__/loadRegistryUrl.test.ts +++ b/packages/ui-components/src/__tests__/loadRegistryUrl.test.ts @@ -1,78 +1,87 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import type { Mock } from 'vitest'; -import { loadRegistryUrl } from '../lib/services/loadRegistryUrl'; -import { RegistryManager } from '../lib/providers/registry/RegistryManager'; -import { initialRegistry } from '../__fixtures__/RegistryManager'; -import { DotrainRegistry } from '@rainlanguage/raindex'; +import { describe, it, expect, vi, beforeEach } from "vitest"; +import type { Mock } from "vitest"; +import { loadRegistryUrl } from "../lib/services/loadRegistryUrl"; +import { RegistryManager } from "../lib/providers/registry/RegistryManager"; +import { initialRegistry } from "../__fixtures__/RegistryManager"; +import { DotrainRegistry } from "@rainlanguage/raindex"; // Mock dependencies -vi.mock('@rainlanguage/raindex', () => ({ - DotrainRegistry: { - validate: vi.fn() - } +vi.mock("@rainlanguage/raindex", () => ({ + DotrainRegistry: { + validate: vi.fn(), + }, })); -describe('loadRegistryUrl', () => { - beforeEach(() => { - vi.resetAllMocks(); - const originalLocation = window.location; - const mockLocation = { ...originalLocation, reload: vi.fn() }; - Object.defineProperty(window, 'location', { - writable: true, - value: mockLocation - }); - }); +describe("loadRegistryUrl", () => { + beforeEach(() => { + vi.resetAllMocks(); + const originalLocation = window.location; + const mockLocation = { ...originalLocation, reload: vi.fn() }; + Object.defineProperty(window, "location", { + writable: true, + value: mockLocation, + }); + }); - it('should throw an error if no URL is provided', async () => { - const mockRegistryManager = initialRegistry as RegistryManager; - await expect(loadRegistryUrl('', mockRegistryManager)).rejects.toThrow('No URL provided'); - }); + it("should throw an error if no URL is provided", async () => { + const mockRegistryManager = initialRegistry as RegistryManager; + await expect(loadRegistryUrl("", mockRegistryManager)).rejects.toThrow( + "No URL provided", + ); + }); - it('should throw an error if no registry manager is provided', async () => { - await expect( - loadRegistryUrl('https://example.com/registry', null as unknown as RegistryManager) - ).rejects.toThrow('Registry manager is required'); - }); + it("should throw an error if no registry manager is provided", async () => { + await expect( + loadRegistryUrl( + "https://example.com/registry", + null as unknown as RegistryManager, + ), + ).rejects.toThrow("Registry manager is required"); + }); - it('should successfully load registry URL and reload the page', async () => { - const testUrl = 'https://example.com/registry'; - const mockRegistryManager = initialRegistry as RegistryManager; + it("should successfully load registry URL and reload the page", async () => { + const testUrl = "https://example.com/registry"; + const mockRegistryManager = initialRegistry as RegistryManager; - (DotrainRegistry.validate as Mock).mockResolvedValueOnce({ value: {} }); - await loadRegistryUrl(testUrl, mockRegistryManager); - expect(DotrainRegistry.validate).toHaveBeenCalledWith(testUrl); - expect(mockRegistryManager.setRegistry).toHaveBeenCalledWith(testUrl); - expect(window.location.reload).toHaveBeenCalled(); - }); + (DotrainRegistry.validate as Mock).mockResolvedValueOnce({ value: {} }); + await loadRegistryUrl(testUrl, mockRegistryManager); + expect(DotrainRegistry.validate).toHaveBeenCalledWith(testUrl); + expect(mockRegistryManager.setRegistry).toHaveBeenCalledWith(testUrl); + expect(window.location.reload).toHaveBeenCalled(); + }); - it('should throw an error if fetching registry fails', async () => { - const testUrl = 'https://example.com/registry'; - const errorMessage = 'Fetch failed'; - const mockRegistryManager = { - setRegistry: vi.fn() - } as unknown as RegistryManager; + it("should throw an error if fetching registry fails", async () => { + const testUrl = "https://example.com/registry"; + const errorMessage = "Fetch failed"; + const mockRegistryManager = { + setRegistry: vi.fn(), + } as unknown as RegistryManager; - (DotrainRegistry.validate as Mock).mockRejectedValueOnce(new Error(errorMessage)); + (DotrainRegistry.validate as Mock).mockRejectedValueOnce( + new Error(errorMessage), + ); - await expect(loadRegistryUrl(testUrl, mockRegistryManager)).rejects.toThrow(errorMessage); + await expect(loadRegistryUrl(testUrl, mockRegistryManager)).rejects.toThrow( + errorMessage, + ); - expect(mockRegistryManager.setRegistry).not.toHaveBeenCalled(); - expect(window.location.reload).not.toHaveBeenCalled(); - }); + expect(mockRegistryManager.setRegistry).not.toHaveBeenCalled(); + expect(window.location.reload).not.toHaveBeenCalled(); + }); - it('should handle non-Error exception during registry fetch', async () => { - const testUrl = 'https://example.com/registry'; - const mockRegistryManager = { - setRegistry: vi.fn() - } as unknown as RegistryManager; + it("should handle non-Error exception during registry fetch", async () => { + const testUrl = "https://example.com/registry"; + const mockRegistryManager = { + setRegistry: vi.fn(), + } as unknown as RegistryManager; - (DotrainRegistry.validate as Mock).mockRejectedValueOnce('String error'); + (DotrainRegistry.validate as Mock).mockRejectedValueOnce("String error"); - await expect(loadRegistryUrl(testUrl, mockRegistryManager)).rejects.toThrow( - 'Failed to update registry URL' - ); + await expect(loadRegistryUrl(testUrl, mockRegistryManager)).rejects.toThrow( + "Failed to update registry URL", + ); - expect(mockRegistryManager.setRegistry).not.toHaveBeenCalled(); - expect(window.location.reload).not.toHaveBeenCalled(); - }); + expect(mockRegistryManager.setRegistry).not.toHaveBeenCalled(); + expect(window.location.reload).not.toHaveBeenCalled(); + }); }); diff --git a/packages/ui-components/src/__tests__/pairTradesChartData.test.ts b/packages/ui-components/src/__tests__/pairTradesChartData.test.ts index 9c1c8da243..178fce852b 100644 --- a/packages/ui-components/src/__tests__/pairTradesChartData.test.ts +++ b/packages/ui-components/src/__tests__/pairTradesChartData.test.ts @@ -1,417 +1,491 @@ -import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; -import type { RaindexTrade, RaindexVaultToken } from '@rainlanguage/raindex'; +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; +import type { RaindexTrade, RaindexVaultToken } from "@rainlanguage/raindex"; import { - extractPairsFromTrades, - getDefaultPair, - getTokenLabel, - transformPairTrades, - getBucketSecondsForTimeDelta, - pairsAreEqual, - findPairIndex, - flipTradingPair, - formatChartTimestamp, - BUCKET_SECONDS_24_HOURS, - BUCKET_SECONDS_7_DAYS, - BUCKET_SECONDS_30_DAYS, - BUCKET_SECONDS_1_YEAR -} from '../lib/services/pairTradesChartData'; + extractPairsFromTrades, + getDefaultPair, + getTokenLabel, + transformPairTrades, + getBucketSecondsForTimeDelta, + pairsAreEqual, + findPairIndex, + flipTradingPair, + formatChartTimestamp, + BUCKET_SECONDS_24_HOURS, + BUCKET_SECONDS_7_DAYS, + BUCKET_SECONDS_30_DAYS, + BUCKET_SECONDS_1_YEAR, +} from "../lib/services/pairTradesChartData"; import { - TIME_DELTA_24_HOURS, - TIME_DELTA_7_DAYS, - TIME_DELTA_30_DAYS, - TIME_DELTA_1_YEAR -} from '../lib/services/time'; - -function createMockToken(address: string, symbol?: string, name?: string): RaindexVaultToken { - return { - id: address, - address, - symbol: symbol ?? '', - name: name ?? '', - decimals: BigInt(18), - chainId: 1, - free: false - } as unknown as RaindexVaultToken; + TIME_DELTA_24_HOURS, + TIME_DELTA_7_DAYS, + TIME_DELTA_30_DAYS, + TIME_DELTA_1_YEAR, +} from "../lib/services/time"; + +function createMockToken( + address: string, + symbol?: string, + name?: string, +): RaindexVaultToken { + return { + id: address, + address, + symbol: symbol ?? "", + name: name ?? "", + decimals: BigInt(18), + chainId: 1, + free: false, + } as unknown as RaindexVaultToken; } function createMockTrade( - id: string, - timestamp: number, - inTokenAddress: string, - outTokenAddress: string, - inAmount: number, - outAmount: number, - inSymbol?: string, - outSymbol?: string + id: string, + timestamp: number, + inTokenAddress: string, + outTokenAddress: string, + inAmount: number, + outAmount: number, + inSymbol?: string, + outSymbol?: string, ): RaindexTrade { - return { - id, - timestamp: BigInt(timestamp), - inputVaultBalanceChange: { - token: createMockToken(inTokenAddress, inSymbol), - amount: BigInt(inAmount), - formattedAmount: String(inAmount), - vaultId: BigInt(1) - }, - outputVaultBalanceChange: { - token: createMockToken(outTokenAddress, outSymbol), - amount: BigInt(-outAmount), - formattedAmount: String(-outAmount), - vaultId: BigInt(2) - }, - transaction: { - id: 'tx-' + id, - from: '0x1234567890abcdef1234567890abcdef12345678', - timestamp: BigInt(timestamp), - blockNumber: BigInt(12345) - }, - orderHash: '0xorderhash', - raindex: '0xraindex' - } as unknown as RaindexTrade; + return { + id, + timestamp: BigInt(timestamp), + inputVaultBalanceChange: { + token: createMockToken(inTokenAddress, inSymbol), + amount: BigInt(inAmount), + formattedAmount: String(inAmount), + vaultId: BigInt(1), + }, + outputVaultBalanceChange: { + token: createMockToken(outTokenAddress, outSymbol), + amount: BigInt(-outAmount), + formattedAmount: String(-outAmount), + vaultId: BigInt(2), + }, + transaction: { + id: "tx-" + id, + from: "0x1234567890abcdef1234567890abcdef12345678", + timestamp: BigInt(timestamp), + blockNumber: BigInt(12345), + }, + orderHash: "0xorderhash", + raindex: "0xraindex", + } as unknown as RaindexTrade; } -describe('getBucketSecondsForTimeDelta', () => { - it('returns correct bucket size for 24h', () => { - expect(getBucketSecondsForTimeDelta(TIME_DELTA_24_HOURS)).toBe(BUCKET_SECONDS_24_HOURS); - }); - - it('returns correct bucket size for 7d', () => { - expect(getBucketSecondsForTimeDelta(TIME_DELTA_7_DAYS)).toBe(BUCKET_SECONDS_7_DAYS); - }); - - it('returns correct bucket size for 30d', () => { - expect(getBucketSecondsForTimeDelta(TIME_DELTA_30_DAYS)).toBe(BUCKET_SECONDS_30_DAYS); - }); - - it('returns correct bucket size for 1y', () => { - expect(getBucketSecondsForTimeDelta(TIME_DELTA_1_YEAR)).toBe(BUCKET_SECONDS_1_YEAR); - }); +describe("getBucketSecondsForTimeDelta", () => { + it("returns correct bucket size for 24h", () => { + expect(getBucketSecondsForTimeDelta(TIME_DELTA_24_HOURS)).toBe( + BUCKET_SECONDS_24_HOURS, + ); + }); + + it("returns correct bucket size for 7d", () => { + expect(getBucketSecondsForTimeDelta(TIME_DELTA_7_DAYS)).toBe( + BUCKET_SECONDS_7_DAYS, + ); + }); + + it("returns correct bucket size for 30d", () => { + expect(getBucketSecondsForTimeDelta(TIME_DELTA_30_DAYS)).toBe( + BUCKET_SECONDS_30_DAYS, + ); + }); + + it("returns correct bucket size for 1y", () => { + expect(getBucketSecondsForTimeDelta(TIME_DELTA_1_YEAR)).toBe( + BUCKET_SECONDS_1_YEAR, + ); + }); }); -describe('extractPairsFromTrades', () => { - it('returns empty array for no trades', () => { - const result = extractPairsFromTrades([]); - expect(result).toEqual([]); - }); - - it('extracts single pair from trades', () => { - const trades = [ - createMockTrade('1', 1000, '0xAAA', '0xBBB', 100, 200, 'AAA', 'BBB'), - createMockTrade('2', 2000, '0xAAA', '0xBBB', 50, 100, 'AAA', 'BBB') - ]; - - const result = extractPairsFromTrades(trades); - expect(result).toHaveLength(1); - expect(result[0].baseToken.address.toLowerCase()).toBe('0xaaa'); - expect(result[0].quoteToken.address.toLowerCase()).toBe('0xbbb'); - }); - - it('extracts multiple pairs from trades', () => { - const trades = [ - createMockTrade('1', 1000, '0xAAA', '0xBBB', 100, 200), - createMockTrade('2', 2000, '0xCCC', '0xDDD', 50, 100) - ]; - - const result = extractPairsFromTrades(trades); - expect(result).toHaveLength(2); - }); - - it('handles reversed pair order (same pair different direction)', () => { - const trades = [ - createMockTrade('1', 1000, '0xAAA', '0xBBB', 100, 200), - createMockTrade('2', 2000, '0xBBB', '0xAAA', 50, 100) - ]; - - const result = extractPairsFromTrades(trades); - expect(result).toHaveLength(1); - }); +describe("extractPairsFromTrades", () => { + it("returns empty array for no trades", () => { + const result = extractPairsFromTrades([]); + expect(result).toEqual([]); + }); + + it("extracts single pair from trades", () => { + const trades = [ + createMockTrade("1", 1000, "0xAAA", "0xBBB", 100, 200, "AAA", "BBB"), + createMockTrade("2", 2000, "0xAAA", "0xBBB", 50, 100, "AAA", "BBB"), + ]; + + const result = extractPairsFromTrades(trades); + expect(result).toHaveLength(1); + expect(result[0].baseToken.address.toLowerCase()).toBe("0xaaa"); + expect(result[0].quoteToken.address.toLowerCase()).toBe("0xbbb"); + }); + + it("extracts multiple pairs from trades", () => { + const trades = [ + createMockTrade("1", 1000, "0xAAA", "0xBBB", 100, 200), + createMockTrade("2", 2000, "0xCCC", "0xDDD", 50, 100), + ]; + + const result = extractPairsFromTrades(trades); + expect(result).toHaveLength(2); + }); + + it("handles reversed pair order (same pair different direction)", () => { + const trades = [ + createMockTrade("1", 1000, "0xAAA", "0xBBB", 100, 200), + createMockTrade("2", 2000, "0xBBB", "0xAAA", 50, 100), + ]; + + const result = extractPairsFromTrades(trades); + expect(result).toHaveLength(1); + }); }); -describe('getDefaultPair', () => { - it('returns null for empty trades', () => { - expect(getDefaultPair([])).toBeNull(); - }); - - it('returns pair from oldest trade', () => { - const trades = [ - createMockTrade('1', 2000, '0xAAA', '0xBBB', 100, 200, 'AAA', 'BBB'), - createMockTrade('2', 1000, '0xCCC', '0xDDD', 50, 100, 'CCC', 'DDD') - ]; - - const result = getDefaultPair(trades); - expect(result).not.toBeNull(); - expect(result!.baseToken.address.toLowerCase()).toBe('0xccc'); - expect(result!.quoteToken.address.toLowerCase()).toBe('0xddd'); - }); +describe("getDefaultPair", () => { + it("returns null for empty trades", () => { + expect(getDefaultPair([])).toBeNull(); + }); + + it("returns pair from oldest trade", () => { + const trades = [ + createMockTrade("1", 2000, "0xAAA", "0xBBB", 100, 200, "AAA", "BBB"), + createMockTrade("2", 1000, "0xCCC", "0xDDD", 50, 100, "CCC", "DDD"), + ]; + + const result = getDefaultPair(trades); + expect(result).not.toBeNull(); + expect(result!.baseToken.address.toLowerCase()).toBe("0xccc"); + expect(result!.quoteToken.address.toLowerCase()).toBe("0xddd"); + }); }); -describe('getTokenLabel', () => { - it('returns symbol when available', () => { - const token = createMockToken('0x1234567890123456789012345678901234567890', 'ETH'); - expect(getTokenLabel(token)).toBe('ETH'); - }); - - it('returns short address when no symbol', () => { - const token = createMockToken('0x1234567890123456789012345678901234567890', ''); - expect(getTokenLabel(token)).toBe('0x1234...7890'); - }); - - it('returns full address if too short', () => { - const token = createMockToken('0x1234', ''); - expect(getTokenLabel(token)).toBe('0x1234'); - }); +describe("getTokenLabel", () => { + it("returns symbol when available", () => { + const token = createMockToken( + "0x1234567890123456789012345678901234567890", + "ETH", + ); + expect(getTokenLabel(token)).toBe("ETH"); + }); + + it("returns short address when no symbol", () => { + const token = createMockToken( + "0x1234567890123456789012345678901234567890", + "", + ); + expect(getTokenLabel(token)).toBe("0x1234...7890"); + }); + + it("returns full address if too short", () => { + const token = createMockToken("0x1234", ""); + expect(getTokenLabel(token)).toBe("0x1234"); + }); }); -describe('transformPairTrades', () => { - beforeEach(() => { - vi.useFakeTimers(); - vi.setSystemTime(new Date(1700000000 * 1000)); - }); - - afterEach(() => { - vi.useRealTimers(); - }); - - it('returns empty data when no trades match the pair', () => { - const trades = [createMockTrade('1', 1699990000, '0xAAA', '0xBBB', 100, 200)]; - - const result = transformPairTrades({ - trades, - baseTokenAddress: '0xCCC', - quoteTokenAddress: '0xDDD', - timeDeltaSeconds: TIME_DELTA_24_HOURS - }); - - expect(result.pricePoints).toHaveLength(0); - expect(result.buyVolumePoints).toHaveLength(0); - expect(result.sellVolumePoints).toHaveLength(0); - }); - - it('filters trades outside time window', () => { - const trades = [ - createMockTrade('1', 1699990000, '0xAAA', '0xBBB', 100, 200), - createMockTrade('2', 1600000000, '0xAAA', '0xBBB', 50, 100) - ]; - - const result = transformPairTrades({ - trades, - baseTokenAddress: '0xAAA', - quoteTokenAddress: '0xBBB', - timeDeltaSeconds: TIME_DELTA_24_HOURS - }); - - expect(result.pricePoints).toHaveLength(1); - }); - - it('correctly identifies BUY trades (order received base)', () => { - const trades = [createMockTrade('1', 1699990000, '0xAAA', '0xBBB', 100, 200)]; - - const result = transformPairTrades({ - trades, - baseTokenAddress: '0xAAA', - quoteTokenAddress: '0xBBB', - timeDeltaSeconds: TIME_DELTA_24_HOURS - }); - - expect(result.buyVolumePoints).toHaveLength(1); - expect(result.sellVolumePoints).toHaveLength(0); - }); - - it('correctly identifies SELL trades (order gave base)', () => { - const trades = [createMockTrade('1', 1699990000, '0xBBB', '0xAAA', 200, 100)]; - - const result = transformPairTrades({ - trades, - baseTokenAddress: '0xAAA', - quoteTokenAddress: '0xBBB', - timeDeltaSeconds: TIME_DELTA_24_HOURS - }); - - expect(result.buyVolumePoints).toHaveLength(0); - expect(result.sellVolumePoints).toHaveLength(1); - }); - - it('calculates price as quote/base', () => { - const trades = [createMockTrade('1', 1699990000, '0xAAA', '0xBBB', 100, 200)]; - - const result = transformPairTrades({ - trades, - baseTokenAddress: '0xAAA', - quoteTokenAddress: '0xBBB', - timeDeltaSeconds: TIME_DELTA_24_HOURS - }); - - expect(result.pricePoints).toHaveLength(1); - expect(result.pricePoints[0].value).toBe(2); - }); - - it('merges trades with same timestamp', () => { - const trades = [ - createMockTrade('1', 1699990000, '0xAAA', '0xBBB', 100, 200), - createMockTrade('2', 1699990000, '0xAAA', '0xBBB', 100, 200) - ]; - - const result = transformPairTrades({ - trades, - baseTokenAddress: '0xAAA', - quoteTokenAddress: '0xBBB', - timeDeltaSeconds: TIME_DELTA_24_HOURS - }); - - expect(result.pricePoints).toHaveLength(1); - }); - - it('aggregates volume into buckets', () => { - const bucketSeconds = BUCKET_SECONDS_24_HOURS; - const bucketStart = Math.floor(1699990000 / bucketSeconds) * bucketSeconds; - - const trades = [ - createMockTrade('1', bucketStart + 100, '0xAAA', '0xBBB', 100, 200), - createMockTrade('2', bucketStart + 200, '0xAAA', '0xBBB', 50, 100) - ]; - - const result = transformPairTrades({ - trades, - baseTokenAddress: '0xAAA', - quoteTokenAddress: '0xBBB', - timeDeltaSeconds: TIME_DELTA_24_HOURS - }); - - expect(result.buyVolumePoints).toHaveLength(1); - expect(result.buyVolumePoints[0].value).toBe(150); - }); - - it('sell volume is negative (bars go down)', () => { - const trades = [createMockTrade('1', 1699990000, '0xBBB', '0xAAA', 200, 100)]; - - const result = transformPairTrades({ - trades, - baseTokenAddress: '0xAAA', - quoteTokenAddress: '0xBBB', - timeDeltaSeconds: TIME_DELTA_24_HOURS - }); - - expect(result.sellVolumePoints).toHaveLength(1); - expect(result.sellVolumePoints[0].value).toBeLessThan(0); - }); - - it('sorts price points by time', () => { - const trades = [ - createMockTrade('1', 1699995000, '0xAAA', '0xBBB', 100, 200), - createMockTrade('2', 1699990000, '0xAAA', '0xBBB', 50, 100) - ]; - - const result = transformPairTrades({ - trades, - baseTokenAddress: '0xAAA', - quoteTokenAddress: '0xBBB', - timeDeltaSeconds: TIME_DELTA_24_HOURS - }); - - expect(result.pricePoints[0].time).toBeLessThan(result.pricePoints[1].time); - }); +describe("transformPairTrades", () => { + beforeEach(() => { + vi.useFakeTimers(); + vi.setSystemTime(new Date(1700000000 * 1000)); + }); + + afterEach(() => { + vi.useRealTimers(); + }); + + it("returns empty data when no trades match the pair", () => { + const trades = [ + createMockTrade("1", 1699990000, "0xAAA", "0xBBB", 100, 200), + ]; + + const result = transformPairTrades({ + trades, + baseTokenAddress: "0xCCC", + quoteTokenAddress: "0xDDD", + timeDeltaSeconds: TIME_DELTA_24_HOURS, + }); + + expect(result.pricePoints).toHaveLength(0); + expect(result.buyVolumePoints).toHaveLength(0); + expect(result.sellVolumePoints).toHaveLength(0); + }); + + it("filters trades outside time window", () => { + const trades = [ + createMockTrade("1", 1699990000, "0xAAA", "0xBBB", 100, 200), + createMockTrade("2", 1600000000, "0xAAA", "0xBBB", 50, 100), + ]; + + const result = transformPairTrades({ + trades, + baseTokenAddress: "0xAAA", + quoteTokenAddress: "0xBBB", + timeDeltaSeconds: TIME_DELTA_24_HOURS, + }); + + expect(result.pricePoints).toHaveLength(1); + }); + + it("correctly identifies BUY trades (order received base)", () => { + const trades = [ + createMockTrade("1", 1699990000, "0xAAA", "0xBBB", 100, 200), + ]; + + const result = transformPairTrades({ + trades, + baseTokenAddress: "0xAAA", + quoteTokenAddress: "0xBBB", + timeDeltaSeconds: TIME_DELTA_24_HOURS, + }); + + expect(result.buyVolumePoints).toHaveLength(1); + expect(result.sellVolumePoints).toHaveLength(0); + }); + + it("correctly identifies SELL trades (order gave base)", () => { + const trades = [ + createMockTrade("1", 1699990000, "0xBBB", "0xAAA", 200, 100), + ]; + + const result = transformPairTrades({ + trades, + baseTokenAddress: "0xAAA", + quoteTokenAddress: "0xBBB", + timeDeltaSeconds: TIME_DELTA_24_HOURS, + }); + + expect(result.buyVolumePoints).toHaveLength(0); + expect(result.sellVolumePoints).toHaveLength(1); + }); + + it("calculates price as quote/base", () => { + const trades = [ + createMockTrade("1", 1699990000, "0xAAA", "0xBBB", 100, 200), + ]; + + const result = transformPairTrades({ + trades, + baseTokenAddress: "0xAAA", + quoteTokenAddress: "0xBBB", + timeDeltaSeconds: TIME_DELTA_24_HOURS, + }); + + expect(result.pricePoints).toHaveLength(1); + expect(result.pricePoints[0].value).toBe(2); + }); + + it("merges trades with same timestamp", () => { + const trades = [ + createMockTrade("1", 1699990000, "0xAAA", "0xBBB", 100, 200), + createMockTrade("2", 1699990000, "0xAAA", "0xBBB", 100, 200), + ]; + + const result = transformPairTrades({ + trades, + baseTokenAddress: "0xAAA", + quoteTokenAddress: "0xBBB", + timeDeltaSeconds: TIME_DELTA_24_HOURS, + }); + + expect(result.pricePoints).toHaveLength(1); + }); + + it("aggregates volume into buckets", () => { + const bucketSeconds = BUCKET_SECONDS_24_HOURS; + const bucketStart = Math.floor(1699990000 / bucketSeconds) * bucketSeconds; + + const trades = [ + createMockTrade("1", bucketStart + 100, "0xAAA", "0xBBB", 100, 200), + createMockTrade("2", bucketStart + 200, "0xAAA", "0xBBB", 50, 100), + ]; + + const result = transformPairTrades({ + trades, + baseTokenAddress: "0xAAA", + quoteTokenAddress: "0xBBB", + timeDeltaSeconds: TIME_DELTA_24_HOURS, + }); + + expect(result.buyVolumePoints).toHaveLength(1); + expect(result.buyVolumePoints[0].value).toBe(150); + }); + + it("sell volume is negative (bars go down)", () => { + const trades = [ + createMockTrade("1", 1699990000, "0xBBB", "0xAAA", 200, 100), + ]; + + const result = transformPairTrades({ + trades, + baseTokenAddress: "0xAAA", + quoteTokenAddress: "0xBBB", + timeDeltaSeconds: TIME_DELTA_24_HOURS, + }); + + expect(result.sellVolumePoints).toHaveLength(1); + expect(result.sellVolumePoints[0].value).toBeLessThan(0); + }); + + it("sorts price points by time", () => { + const trades = [ + createMockTrade("1", 1699995000, "0xAAA", "0xBBB", 100, 200), + createMockTrade("2", 1699990000, "0xAAA", "0xBBB", 50, 100), + ]; + + const result = transformPairTrades({ + trades, + baseTokenAddress: "0xAAA", + quoteTokenAddress: "0xBBB", + timeDeltaSeconds: TIME_DELTA_24_HOURS, + }); + + expect(result.pricePoints[0].time).toBeLessThan(result.pricePoints[1].time); + }); }); -describe('pairsAreEqual', () => { - it('returns true for identical pairs', () => { - const pair = { baseToken: createMockToken('0xAAA'), quoteToken: createMockToken('0xBBB') }; - expect(pairsAreEqual(pair, pair)).toBe(true); - }); - - it('returns true for case-insensitive address match', () => { - const pair1 = { baseToken: createMockToken('0xAAA'), quoteToken: createMockToken('0xBBB') }; - const pair2 = { baseToken: createMockToken('0xaaa'), quoteToken: createMockToken('0xbbb') }; - expect(pairsAreEqual(pair1, pair2)).toBe(true); - }); - - it('returns false for different pairs', () => { - const pair1 = { baseToken: createMockToken('0xAAA'), quoteToken: createMockToken('0xBBB') }; - const pair2 = { baseToken: createMockToken('0xCCC'), quoteToken: createMockToken('0xDDD') }; - expect(pairsAreEqual(pair1, pair2)).toBe(false); - }); - - it('returns false for swapped base/quote (order matters)', () => { - const pair1 = { baseToken: createMockToken('0xAAA'), quoteToken: createMockToken('0xBBB') }; - const pair2 = { baseToken: createMockToken('0xBBB'), quoteToken: createMockToken('0xAAA') }; - expect(pairsAreEqual(pair1, pair2)).toBe(false); - }); +describe("pairsAreEqual", () => { + it("returns true for identical pairs", () => { + const pair = { + baseToken: createMockToken("0xAAA"), + quoteToken: createMockToken("0xBBB"), + }; + expect(pairsAreEqual(pair, pair)).toBe(true); + }); + + it("returns true for case-insensitive address match", () => { + const pair1 = { + baseToken: createMockToken("0xAAA"), + quoteToken: createMockToken("0xBBB"), + }; + const pair2 = { + baseToken: createMockToken("0xaaa"), + quoteToken: createMockToken("0xbbb"), + }; + expect(pairsAreEqual(pair1, pair2)).toBe(true); + }); + + it("returns false for different pairs", () => { + const pair1 = { + baseToken: createMockToken("0xAAA"), + quoteToken: createMockToken("0xBBB"), + }; + const pair2 = { + baseToken: createMockToken("0xCCC"), + quoteToken: createMockToken("0xDDD"), + }; + expect(pairsAreEqual(pair1, pair2)).toBe(false); + }); + + it("returns false for swapped base/quote (order matters)", () => { + const pair1 = { + baseToken: createMockToken("0xAAA"), + quoteToken: createMockToken("0xBBB"), + }; + const pair2 = { + baseToken: createMockToken("0xBBB"), + quoteToken: createMockToken("0xAAA"), + }; + expect(pairsAreEqual(pair1, pair2)).toBe(false); + }); }); -describe('findPairIndex', () => { - it('returns index when pair exists', () => { - const pairs = [ - { baseToken: createMockToken('0xAAA'), quoteToken: createMockToken('0xBBB') }, - { baseToken: createMockToken('0xCCC'), quoteToken: createMockToken('0xDDD') } - ]; - expect(findPairIndex(pairs, pairs[1])).toBe(1); - }); - - it('returns -1 when pair not found', () => { - const pairs = [{ baseToken: createMockToken('0xAAA'), quoteToken: createMockToken('0xBBB') }]; - const target = { baseToken: createMockToken('0xCCC'), quoteToken: createMockToken('0xDDD') }; - expect(findPairIndex(pairs, target)).toBe(-1); - }); - - it('finds pair with case-insensitive match', () => { - const pairs = [{ baseToken: createMockToken('0xAAA'), quoteToken: createMockToken('0xBBB') }]; - const target = { baseToken: createMockToken('0xaaa'), quoteToken: createMockToken('0xbbb') }; - expect(findPairIndex(pairs, target)).toBe(0); - }); +describe("findPairIndex", () => { + it("returns index when pair exists", () => { + const pairs = [ + { + baseToken: createMockToken("0xAAA"), + quoteToken: createMockToken("0xBBB"), + }, + { + baseToken: createMockToken("0xCCC"), + quoteToken: createMockToken("0xDDD"), + }, + ]; + expect(findPairIndex(pairs, pairs[1])).toBe(1); + }); + + it("returns -1 when pair not found", () => { + const pairs = [ + { + baseToken: createMockToken("0xAAA"), + quoteToken: createMockToken("0xBBB"), + }, + ]; + const target = { + baseToken: createMockToken("0xCCC"), + quoteToken: createMockToken("0xDDD"), + }; + expect(findPairIndex(pairs, target)).toBe(-1); + }); + + it("finds pair with case-insensitive match", () => { + const pairs = [ + { + baseToken: createMockToken("0xAAA"), + quoteToken: createMockToken("0xBBB"), + }, + ]; + const target = { + baseToken: createMockToken("0xaaa"), + quoteToken: createMockToken("0xbbb"), + }; + expect(findPairIndex(pairs, target)).toBe(0); + }); }); -describe('flipTradingPair', () => { - it('swaps base and quote tokens', () => { - const base = createMockToken('0xAAA', 'AAA'); - const quote = createMockToken('0xBBB', 'BBB'); - const result = flipTradingPair({ baseToken: base, quoteToken: quote }); - expect(result.baseToken.address).toBe('0xBBB'); - expect(result.quoteToken.address).toBe('0xAAA'); - }); - - it('double flip returns equivalent pair', () => { - const pair = { baseToken: createMockToken('0xAAA'), quoteToken: createMockToken('0xBBB') }; - const flippedTwice = flipTradingPair(flipTradingPair(pair)); - expect(pairsAreEqual(pair, flippedTwice)).toBe(true); - }); - - it('does not mutate original pair', () => { - const base = createMockToken('0xAAA'); - const quote = createMockToken('0xBBB'); - const original = { baseToken: base, quoteToken: quote }; - flipTradingPair(original); - expect(original.baseToken.address).toBe('0xAAA'); - expect(original.quoteToken.address).toBe('0xBBB'); - }); +describe("flipTradingPair", () => { + it("swaps base and quote tokens", () => { + const base = createMockToken("0xAAA", "AAA"); + const quote = createMockToken("0xBBB", "BBB"); + const result = flipTradingPair({ baseToken: base, quoteToken: quote }); + expect(result.baseToken.address).toBe("0xBBB"); + expect(result.quoteToken.address).toBe("0xAAA"); + }); + + it("double flip returns equivalent pair", () => { + const pair = { + baseToken: createMockToken("0xAAA"), + quoteToken: createMockToken("0xBBB"), + }; + const flippedTwice = flipTradingPair(flipTradingPair(pair)); + expect(pairsAreEqual(pair, flippedTwice)).toBe(true); + }); + + it("does not mutate original pair", () => { + const base = createMockToken("0xAAA"); + const quote = createMockToken("0xBBB"); + const original = { baseToken: base, quoteToken: quote }; + flipTradingPair(original); + expect(original.baseToken.address).toBe("0xAAA"); + expect(original.quoteToken.address).toBe("0xBBB"); + }); }); -describe('formatChartTimestamp', () => { - it('formats with minutes for 24h delta', () => { - const ts = new Date(2024, 0, 15, 14, 30).getTime() / 1000; - const result = formatChartTimestamp(ts, TIME_DELTA_24_HOURS); - expect(result).toBe('Jan 15 14:30'); - }); - - it('formats with hour precision for 7d delta', () => { - const ts = new Date(2024, 0, 15, 14, 30).getTime() / 1000; - const result = formatChartTimestamp(ts, TIME_DELTA_7_DAYS); - expect(result).toBe('Jan 15 14:00'); - }); - - it('formats with day only for 30d delta', () => { - const ts = new Date(2024, 0, 15, 14, 30).getTime() / 1000; - const result = formatChartTimestamp(ts, TIME_DELTA_30_DAYS); - expect(result).toBe('Jan 15'); - }); - - it('formats with day only for 1y delta', () => { - const ts = new Date(2024, 0, 15, 14, 30).getTime() / 1000; - const result = formatChartTimestamp(ts, TIME_DELTA_1_YEAR); - expect(result).toBe('Jan 15'); - }); - - it('pads single-digit hours and minutes', () => { - const ts = new Date(2024, 0, 5, 9, 5).getTime() / 1000; - const result = formatChartTimestamp(ts, TIME_DELTA_24_HOURS); - expect(result).toBe('Jan 5 09:05'); - }); +describe("formatChartTimestamp", () => { + it("formats with minutes for 24h delta", () => { + const ts = new Date(2024, 0, 15, 14, 30).getTime() / 1000; + const result = formatChartTimestamp(ts, TIME_DELTA_24_HOURS); + expect(result).toBe("Jan 15 14:30"); + }); + + it("formats with hour precision for 7d delta", () => { + const ts = new Date(2024, 0, 15, 14, 30).getTime() / 1000; + const result = formatChartTimestamp(ts, TIME_DELTA_7_DAYS); + expect(result).toBe("Jan 15 14:00"); + }); + + it("formats with day only for 30d delta", () => { + const ts = new Date(2024, 0, 15, 14, 30).getTime() / 1000; + const result = formatChartTimestamp(ts, TIME_DELTA_30_DAYS); + expect(result).toBe("Jan 15"); + }); + + it("formats with day only for 1y delta", () => { + const ts = new Date(2024, 0, 15, 14, 30).getTime() / 1000; + const result = formatChartTimestamp(ts, TIME_DELTA_1_YEAR); + expect(result).toBe("Jan 15"); + }); + + it("pads single-digit hours and minutes", () => { + const ts = new Date(2024, 0, 5, 9, 5).getTime() / 1000; + const result = formatChartTimestamp(ts, TIME_DELTA_24_HOURS); + expect(result).toBe("Jan 5 09:05"); + }); }); diff --git a/packages/ui-components/src/__tests__/queryClient.test.ts b/packages/ui-components/src/__tests__/queryClient.test.ts index 4eaf3297c0..4d385c8f5d 100644 --- a/packages/ui-components/src/__tests__/queryClient.test.ts +++ b/packages/ui-components/src/__tests__/queryClient.test.ts @@ -1,154 +1,161 @@ -import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; -import { queryClient, invalidateTanstackQueries } from '../lib/queries/queryClient'; -import { QueryClient } from '@tanstack/svelte-query'; - -describe('queryClient module', () => { - describe('queryClient instance', () => { - it('creates a QueryClient instance with correct configuration', () => { - expect(queryClient).toBeInstanceOf(QueryClient); - }); - }); - - describe('invalidateTanstackQueries', () => { - let testQueryClient: QueryClient; - - beforeEach(() => { - testQueryClient = new QueryClient(); - vi.spyOn(testQueryClient, 'invalidateQueries'); - }); - - afterEach(() => { - vi.restoreAllMocks(); - }); - - it('calls invalidateQueries with the correct parameters', async () => { - const queryKey = ['test', 'query']; - - await invalidateTanstackQueries(testQueryClient, queryKey); - - expect(testQueryClient.invalidateQueries).toHaveBeenCalledTimes(1); - expect(testQueryClient.invalidateQueries).toHaveBeenCalledWith({ - queryKey, - refetchType: 'all', - exact: false - }); - }); - - it('works with nested query keys', async () => { - const queryKey = ['orders', 'details', '123']; - - await invalidateTanstackQueries(testQueryClient, queryKey); - - expect(testQueryClient.invalidateQueries).toHaveBeenCalledWith({ - queryKey, - refetchType: 'all', - exact: false - }); - }); - - it('works with single-item query keys', async () => { - const queryKey = ['globalData']; - - await invalidateTanstackQueries(testQueryClient, queryKey); - - expect(testQueryClient.invalidateQueries).toHaveBeenCalledWith({ - queryKey, - refetchType: 'all', - exact: false - }); - }); - - it('invalidates all matching queries due to exact: false', async () => { - // Setup some test queries - const parentKey = ['orders']; - const childKey1 = ['orders', '123']; - const childKey2 = ['orders', '456']; - const unrelatedKey = ['products']; - - vi.spyOn(testQueryClient, 'refetchQueries'); - - await testQueryClient.prefetchQuery({ - queryKey: parentKey, - queryFn: () => 'parent data' - }); - - await testQueryClient.prefetchQuery({ - queryKey: childKey1, - queryFn: () => 'child1 data' - }); - - await testQueryClient.prefetchQuery({ - queryKey: childKey2, - queryFn: () => 'child2 data' - }); - - await testQueryClient.prefetchQuery({ - queryKey: unrelatedKey, - queryFn: () => 'unrelated data' - }); - - const unrelatedQueryStateBefore = testQueryClient.getQueryState(unrelatedKey); - - await invalidateTanstackQueries(testQueryClient, parentKey); - - expect(testQueryClient.invalidateQueries).toHaveBeenCalledWith({ - queryKey: parentKey, - refetchType: 'all', - exact: false - }); - - expect(testQueryClient.refetchQueries).toHaveBeenCalled(); - - const unrelatedQueryStateAfter = testQueryClient.getQueryState(unrelatedKey); - expect(unrelatedQueryStateAfter?.dataUpdatedAt).toBe( - unrelatedQueryStateBefore?.dataUpdatedAt - ); - }); - - it('handles potential errors gracefully', async () => { - const queryKey = ['errorTest']; - vi.spyOn(testQueryClient, 'invalidateQueries').mockImplementationOnce(() => { - throw new Error('Simulated invalidateQueries error'); - }); - - await expect(invalidateTanstackQueries(testQueryClient, queryKey)).rejects.toThrow( - 'Failed to refresh data.' - ); - expect(testQueryClient.invalidateQueries).toHaveBeenCalledWith({ - queryKey, - refetchType: 'all', - exact: false - }); - }); - - it('handles empty query key array', async () => { - const queryKey: string[] = []; - await invalidateTanstackQueries(testQueryClient, queryKey); - expect(testQueryClient.invalidateQueries).toHaveBeenCalledWith({ - queryKey, - refetchType: 'all', - exact: false - }); - }); - - it('handles query key with undefined or null values', async () => { - const queryKey = ['test', undefined, 'key']; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - await invalidateTanstackQueries(testQueryClient, queryKey as any); - expect(testQueryClient.invalidateQueries).toHaveBeenCalledWith({ - queryKey: queryKey, - refetchType: 'all', - exact: false - }); - - const queryKeyWithNull = ['test', null, 'key']; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - await invalidateTanstackQueries(testQueryClient, queryKeyWithNull as any); - expect(testQueryClient.invalidateQueries).toHaveBeenCalledWith({ - queryKey: queryKeyWithNull, - refetchType: 'all', - exact: false - }); - }); - }); +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; +import { + queryClient, + invalidateTanstackQueries, +} from "../lib/queries/queryClient"; +import { QueryClient } from "@tanstack/svelte-query"; + +describe("queryClient module", () => { + describe("queryClient instance", () => { + it("creates a QueryClient instance with correct configuration", () => { + expect(queryClient).toBeInstanceOf(QueryClient); + }); + }); + + describe("invalidateTanstackQueries", () => { + let testQueryClient: QueryClient; + + beforeEach(() => { + testQueryClient = new QueryClient(); + vi.spyOn(testQueryClient, "invalidateQueries"); + }); + + afterEach(() => { + vi.restoreAllMocks(); + }); + + it("calls invalidateQueries with the correct parameters", async () => { + const queryKey = ["test", "query"]; + + await invalidateTanstackQueries(testQueryClient, queryKey); + + expect(testQueryClient.invalidateQueries).toHaveBeenCalledTimes(1); + expect(testQueryClient.invalidateQueries).toHaveBeenCalledWith({ + queryKey, + refetchType: "all", + exact: false, + }); + }); + + it("works with nested query keys", async () => { + const queryKey = ["orders", "details", "123"]; + + await invalidateTanstackQueries(testQueryClient, queryKey); + + expect(testQueryClient.invalidateQueries).toHaveBeenCalledWith({ + queryKey, + refetchType: "all", + exact: false, + }); + }); + + it("works with single-item query keys", async () => { + const queryKey = ["globalData"]; + + await invalidateTanstackQueries(testQueryClient, queryKey); + + expect(testQueryClient.invalidateQueries).toHaveBeenCalledWith({ + queryKey, + refetchType: "all", + exact: false, + }); + }); + + it("invalidates all matching queries due to exact: false", async () => { + // Setup some test queries + const parentKey = ["orders"]; + const childKey1 = ["orders", "123"]; + const childKey2 = ["orders", "456"]; + const unrelatedKey = ["products"]; + + vi.spyOn(testQueryClient, "refetchQueries"); + + await testQueryClient.prefetchQuery({ + queryKey: parentKey, + queryFn: () => "parent data", + }); + + await testQueryClient.prefetchQuery({ + queryKey: childKey1, + queryFn: () => "child1 data", + }); + + await testQueryClient.prefetchQuery({ + queryKey: childKey2, + queryFn: () => "child2 data", + }); + + await testQueryClient.prefetchQuery({ + queryKey: unrelatedKey, + queryFn: () => "unrelated data", + }); + + const unrelatedQueryStateBefore = + testQueryClient.getQueryState(unrelatedKey); + + await invalidateTanstackQueries(testQueryClient, parentKey); + + expect(testQueryClient.invalidateQueries).toHaveBeenCalledWith({ + queryKey: parentKey, + refetchType: "all", + exact: false, + }); + + expect(testQueryClient.refetchQueries).toHaveBeenCalled(); + + const unrelatedQueryStateAfter = + testQueryClient.getQueryState(unrelatedKey); + expect(unrelatedQueryStateAfter?.dataUpdatedAt).toBe( + unrelatedQueryStateBefore?.dataUpdatedAt, + ); + }); + + it("handles potential errors gracefully", async () => { + const queryKey = ["errorTest"]; + vi.spyOn(testQueryClient, "invalidateQueries").mockImplementationOnce( + () => { + throw new Error("Simulated invalidateQueries error"); + }, + ); + + await expect( + invalidateTanstackQueries(testQueryClient, queryKey), + ).rejects.toThrow("Failed to refresh data."); + expect(testQueryClient.invalidateQueries).toHaveBeenCalledWith({ + queryKey, + refetchType: "all", + exact: false, + }); + }); + + it("handles empty query key array", async () => { + const queryKey: string[] = []; + await invalidateTanstackQueries(testQueryClient, queryKey); + expect(testQueryClient.invalidateQueries).toHaveBeenCalledWith({ + queryKey, + refetchType: "all", + exact: false, + }); + }); + + it("handles query key with undefined or null values", async () => { + const queryKey = ["test", undefined, "key"]; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + await invalidateTanstackQueries(testQueryClient, queryKey as any); + expect(testQueryClient.invalidateQueries).toHaveBeenCalledWith({ + queryKey: queryKey, + refetchType: "all", + exact: false, + }); + + const queryKeyWithNull = ["test", null, "key"]; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + await invalidateTanstackQueries(testQueryClient, queryKeyWithNull as any); + expect(testQueryClient.invalidateQueries).toHaveBeenCalledWith({ + queryKey: queryKeyWithNull, + refetchType: "all", + exact: false, + }); + }); + }); }); diff --git a/packages/ui-components/src/__tests__/registry.test.ts b/packages/ui-components/src/__tests__/registry.test.ts index de5a8ba06b..94e41508b8 100644 --- a/packages/ui-components/src/__tests__/registry.test.ts +++ b/packages/ui-components/src/__tests__/registry.test.ts @@ -1,253 +1,265 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { describe, it, expect, vi, beforeEach } from "vitest"; import { - fetchParseRegistry, - fetchRegistryDotrains, - validateOrders -} from '../lib/services/registry'; -import { RaindexOrderBuilder } from '@rainlanguage/raindex'; -import type { Mock } from 'vitest'; + fetchParseRegistry, + fetchRegistryDotrains, + validateOrders, +} from "../lib/services/registry"; +import { RaindexOrderBuilder } from "@rainlanguage/raindex"; +import type { Mock } from "vitest"; // Mock the RaindexOrderBuilder dependency -vi.mock('@rainlanguage/raindex', () => ({ - RaindexOrderBuilder: { - getOrderDetails: vi.fn() - } +vi.mock("@rainlanguage/raindex", () => ({ + RaindexOrderBuilder: { + getOrderDetails: vi.fn(), + }, })); -describe('fetchParseRegistry', () => { - it('should parse registry file content correctly', async () => { - const mockResponse = `file1.js https://example.com/file1.js +describe("fetchParseRegistry", () => { + it("should parse registry file content correctly", async () => { + const mockResponse = `file1.js https://example.com/file1.js file2.js https://example.com/file2.js`; - global.fetch = vi.fn().mockResolvedValue({ - ok: true, - text: () => Promise.resolve(mockResponse) - }); - - const result = await fetchParseRegistry('https://example.com/registry'); - expect(result).toEqual([ - { name: 'file1.js', url: 'https://example.com/file1.js' }, - { name: 'file2.js', url: 'https://example.com/file2.js' } - ]); - }); - - it('should handle failed fetch response', async () => { - global.fetch = vi.fn().mockResolvedValue({ - ok: false - }); - - await expect(fetchParseRegistry('https://example.com/registry')).rejects.toThrow( - 'Failed to fetch registry' - ); - }); - - it('should handle network errors', async () => { - global.fetch = vi.fn().mockRejectedValue(new Error('Network error')); - - await expect(fetchParseRegistry('https://example.com/registry')).rejects.toThrow( - 'Network error' - ); - }); + global.fetch = vi.fn().mockResolvedValue({ + ok: true, + text: () => Promise.resolve(mockResponse), + }); + + const result = await fetchParseRegistry("https://example.com/registry"); + expect(result).toEqual([ + { name: "file1.js", url: "https://example.com/file1.js" }, + { name: "file2.js", url: "https://example.com/file2.js" }, + ]); + }); + + it("should handle failed fetch response", async () => { + global.fetch = vi.fn().mockResolvedValue({ + ok: false, + }); + + await expect( + fetchParseRegistry("https://example.com/registry"), + ).rejects.toThrow("Failed to fetch registry"); + }); + + it("should handle network errors", async () => { + global.fetch = vi.fn().mockRejectedValue(new Error("Network error")); + + await expect( + fetchParseRegistry("https://example.com/registry"), + ).rejects.toThrow("Network error"); + }); }); -describe('fetchRegistryDotrains', () => { - it('should fetch and parse dotrains correctly', async () => { - const mockRegistry = `file1.rain https://example.com/file1.rain +describe("fetchRegistryDotrains", () => { + it("should fetch and parse dotrains correctly", async () => { + const mockRegistry = `file1.rain https://example.com/file1.rain file2.rain https://example.com/file2.rain`; - const mockDotrain1 = 'content of file1'; - const mockDotrain2 = 'content of file2'; - - global.fetch = vi - .fn() - .mockResolvedValueOnce({ - ok: true, - text: () => Promise.resolve(mockRegistry) - }) - .mockResolvedValueOnce({ - ok: true, - text: () => Promise.resolve(mockDotrain1) - }) - .mockResolvedValueOnce({ - ok: true, - text: () => Promise.resolve(mockDotrain2) - }); - - const result = await fetchRegistryDotrains('https://example.com/registry'); - expect(result).toEqual([ - { name: 'file1.rain', dotrain: mockDotrain1 }, - { name: 'file2.rain', dotrain: mockDotrain2 } - ]); - }); - - it('should handle failed dotrain fetch', async () => { - const mockRegistry = `file1.rain https://example.com/file1.rain`; - - global.fetch = vi - .fn() - .mockResolvedValueOnce({ - ok: true, - text: () => Promise.resolve(mockRegistry) - }) - .mockResolvedValueOnce({ - ok: false - }); - - await expect(fetchRegistryDotrains('https://example.com/registry')).rejects.toThrow( - 'Failed to fetch dotrain for file1.rain' - ); - }); - - it('should handle network errors during dotrain fetch', async () => { - const mockRegistry = `file1.rain https://example.com/file1.rain`; - - global.fetch = vi - .fn() - .mockResolvedValueOnce({ - ok: true, - text: () => Promise.resolve(mockRegistry) - }) - .mockRejectedValueOnce(new Error('Network error')); - - await expect(fetchRegistryDotrains('https://example.com/registry')).rejects.toThrow( - 'Error fetching dotrain for file1.rain: Network error' - ); - }); + const mockDotrain1 = "content of file1"; + const mockDotrain2 = "content of file2"; + + global.fetch = vi + .fn() + .mockResolvedValueOnce({ + ok: true, + text: () => Promise.resolve(mockRegistry), + }) + .mockResolvedValueOnce({ + ok: true, + text: () => Promise.resolve(mockDotrain1), + }) + .mockResolvedValueOnce({ + ok: true, + text: () => Promise.resolve(mockDotrain2), + }); + + const result = await fetchRegistryDotrains("https://example.com/registry"); + expect(result).toEqual([ + { name: "file1.rain", dotrain: mockDotrain1 }, + { name: "file2.rain", dotrain: mockDotrain2 }, + ]); + }); + + it("should handle failed dotrain fetch", async () => { + const mockRegistry = `file1.rain https://example.com/file1.rain`; + + global.fetch = vi + .fn() + .mockResolvedValueOnce({ + ok: true, + text: () => Promise.resolve(mockRegistry), + }) + .mockResolvedValueOnce({ + ok: false, + }); + + await expect( + fetchRegistryDotrains("https://example.com/registry"), + ).rejects.toThrow("Failed to fetch dotrain for file1.rain"); + }); + + it("should handle network errors during dotrain fetch", async () => { + const mockRegistry = `file1.rain https://example.com/file1.rain`; + + global.fetch = vi + .fn() + .mockResolvedValueOnce({ + ok: true, + text: () => Promise.resolve(mockRegistry), + }) + .mockRejectedValueOnce(new Error("Network error")); + + await expect( + fetchRegistryDotrains("https://example.com/registry"), + ).rejects.toThrow("Error fetching dotrain for file1.rain: Network error"); + }); }); -describe('validateOrders', () => { - beforeEach(() => { - vi.resetAllMocks(); - }); - - it('should validate orders and categorize them properly', async () => { - // Input data - const registryDotrains = [ - { name: 'valid.rain', dotrain: 'valid dotrain content' }, - { name: 'invalid.rain', dotrain: 'invalid dotrain content' }, - { name: 'another-valid.rain', dotrain: 'another valid content' } - ]; - - // Set up mock responses for the RaindexOrderBuilder - (RaindexOrderBuilder.getOrderDetails as Mock) - .mockResolvedValueOnce({ - value: { name: 'Valid Order', description: 'A valid order' }, - error: null - }) - .mockResolvedValueOnce({ - error: { msg: 'Invalid syntax' }, - value: null - }) - .mockResolvedValueOnce({ - value: { name: 'Another Valid', description: 'Another valid order' }, - error: null - }); - - // Call the function with our test data - const result = await validateOrders(registryDotrains); - - // Verify RaindexOrderBuilder was called correctly - expect(RaindexOrderBuilder.getOrderDetails).toHaveBeenCalledTimes(3); - expect(RaindexOrderBuilder.getOrderDetails).toHaveBeenCalledWith('valid dotrain content'); - expect(RaindexOrderBuilder.getOrderDetails).toHaveBeenCalledWith('invalid dotrain content'); - expect(RaindexOrderBuilder.getOrderDetails).toHaveBeenCalledWith('another valid content'); - - // Verify the valid orders are processed correctly - expect(result.validOrders).toHaveLength(2); - expect(result.validOrders[0].name).toBe('valid.rain'); - expect(result.validOrders[0].dotrain).toBe('valid dotrain content'); - expect(result.validOrders[0].details).toEqual({ - name: 'Valid Order', - description: 'A valid order' - }); - - // Verify the invalid orders are processed correctly - expect(result.invalidOrders).toHaveLength(1); - expect(result.invalidOrders[0].name).toBe('invalid.rain'); - expect(result.invalidOrders[0].error).toBe('Invalid syntax'); - }); - - it('should handle exceptions thrown during order validation', async () => { - // Input data - const registryDotrains = [{ name: 'error.rain', dotrain: 'will throw error' }]; - - // Mock the RaindexOrderBuilder to throw an exception - (RaindexOrderBuilder.getOrderDetails as Mock).mockRejectedValueOnce( - new Error('Unexpected parsing error') - ); - - // Call the function - const result = await validateOrders(registryDotrains); - - // Verify results - expect(result.validOrders).toHaveLength(0); - expect(result.invalidOrders).toHaveLength(1); - expect(result.invalidOrders[0].name).toBe('error.rain'); - expect(result.invalidOrders[0].error).toBe('Unexpected parsing error'); - }); - - it('should handle non-Error objects being thrown', async () => { - // Input data - const registryDotrains = [{ name: 'string-error.rain', dotrain: 'will throw string' }]; - - // Mock the RaindexOrderBuilder to throw a string instead of an Error - (RaindexOrderBuilder.getOrderDetails as Mock).mockRejectedValueOnce('String error message'); - - // Call the function - const result = await validateOrders(registryDotrains); - - // Verify results - expect(result.validOrders).toHaveLength(0); - expect(result.invalidOrders).toHaveLength(1); - expect(result.invalidOrders[0].name).toBe('string-error.rain'); - expect(result.invalidOrders[0].error).toBe('String error message'); - }); - - it('should process an empty array of orders', async () => { - const result = await validateOrders([]); - - expect(result.validOrders).toEqual([]); - expect(result.invalidOrders).toEqual([]); - expect(RaindexOrderBuilder.getOrderDetails).not.toHaveBeenCalled(); - }); - - it('should handle mixed validation results correctly', async () => { - // Create a mix of scenarios - const registryDotrains = [ - { name: 'valid1.rain', dotrain: 'valid content 1' }, - { name: 'error.rain', dotrain: 'will throw error' }, - { name: 'valid2.rain', dotrain: 'valid content 2' }, - { name: 'invalid.rain', dotrain: 'invalid content' } - ]; - - // Set up mock responses - (RaindexOrderBuilder.getOrderDetails as Mock) - .mockResolvedValueOnce({ - value: { orderName: 'Order 1', description: 'Description 1' }, - error: null - }) - .mockRejectedValueOnce(new Error('Processing error')) - .mockResolvedValueOnce({ - value: { orderName: 'Order 2', description: 'Description 2' }, - error: null - }) - .mockResolvedValueOnce({ - error: { msg: 'Validation failed' }, - value: null - }); - - // Call the function - const result = await validateOrders(registryDotrains); - - // Verify results - expect(result.validOrders).toHaveLength(2); - expect(result.validOrders[0].name).toBe('valid1.rain'); - expect(result.validOrders[1].name).toBe('valid2.rain'); - - expect(result.invalidOrders).toHaveLength(2); - expect(result.invalidOrders[0].name).toBe('error.rain'); - expect(result.invalidOrders[0].error).toBe('Processing error'); - expect(result.invalidOrders[1].name).toBe('invalid.rain'); - expect(result.invalidOrders[1].error).toBe('Validation failed'); - }); +describe("validateOrders", () => { + beforeEach(() => { + vi.resetAllMocks(); + }); + + it("should validate orders and categorize them properly", async () => { + // Input data + const registryDotrains = [ + { name: "valid.rain", dotrain: "valid dotrain content" }, + { name: "invalid.rain", dotrain: "invalid dotrain content" }, + { name: "another-valid.rain", dotrain: "another valid content" }, + ]; + + // Set up mock responses for the RaindexOrderBuilder + (RaindexOrderBuilder.getOrderDetails as Mock) + .mockResolvedValueOnce({ + value: { name: "Valid Order", description: "A valid order" }, + error: null, + }) + .mockResolvedValueOnce({ + error: { msg: "Invalid syntax" }, + value: null, + }) + .mockResolvedValueOnce({ + value: { name: "Another Valid", description: "Another valid order" }, + error: null, + }); + + // Call the function with our test data + const result = await validateOrders(registryDotrains); + + // Verify RaindexOrderBuilder was called correctly + expect(RaindexOrderBuilder.getOrderDetails).toHaveBeenCalledTimes(3); + expect(RaindexOrderBuilder.getOrderDetails).toHaveBeenCalledWith( + "valid dotrain content", + ); + expect(RaindexOrderBuilder.getOrderDetails).toHaveBeenCalledWith( + "invalid dotrain content", + ); + expect(RaindexOrderBuilder.getOrderDetails).toHaveBeenCalledWith( + "another valid content", + ); + + // Verify the valid orders are processed correctly + expect(result.validOrders).toHaveLength(2); + expect(result.validOrders[0].name).toBe("valid.rain"); + expect(result.validOrders[0].dotrain).toBe("valid dotrain content"); + expect(result.validOrders[0].details).toEqual({ + name: "Valid Order", + description: "A valid order", + }); + + // Verify the invalid orders are processed correctly + expect(result.invalidOrders).toHaveLength(1); + expect(result.invalidOrders[0].name).toBe("invalid.rain"); + expect(result.invalidOrders[0].error).toBe("Invalid syntax"); + }); + + it("should handle exceptions thrown during order validation", async () => { + // Input data + const registryDotrains = [ + { name: "error.rain", dotrain: "will throw error" }, + ]; + + // Mock the RaindexOrderBuilder to throw an exception + (RaindexOrderBuilder.getOrderDetails as Mock).mockRejectedValueOnce( + new Error("Unexpected parsing error"), + ); + + // Call the function + const result = await validateOrders(registryDotrains); + + // Verify results + expect(result.validOrders).toHaveLength(0); + expect(result.invalidOrders).toHaveLength(1); + expect(result.invalidOrders[0].name).toBe("error.rain"); + expect(result.invalidOrders[0].error).toBe("Unexpected parsing error"); + }); + + it("should handle non-Error objects being thrown", async () => { + // Input data + const registryDotrains = [ + { name: "string-error.rain", dotrain: "will throw string" }, + ]; + + // Mock the RaindexOrderBuilder to throw a string instead of an Error + (RaindexOrderBuilder.getOrderDetails as Mock).mockRejectedValueOnce( + "String error message", + ); + + // Call the function + const result = await validateOrders(registryDotrains); + + // Verify results + expect(result.validOrders).toHaveLength(0); + expect(result.invalidOrders).toHaveLength(1); + expect(result.invalidOrders[0].name).toBe("string-error.rain"); + expect(result.invalidOrders[0].error).toBe("String error message"); + }); + + it("should process an empty array of orders", async () => { + const result = await validateOrders([]); + + expect(result.validOrders).toEqual([]); + expect(result.invalidOrders).toEqual([]); + expect(RaindexOrderBuilder.getOrderDetails).not.toHaveBeenCalled(); + }); + + it("should handle mixed validation results correctly", async () => { + // Create a mix of scenarios + const registryDotrains = [ + { name: "valid1.rain", dotrain: "valid content 1" }, + { name: "error.rain", dotrain: "will throw error" }, + { name: "valid2.rain", dotrain: "valid content 2" }, + { name: "invalid.rain", dotrain: "invalid content" }, + ]; + + // Set up mock responses + (RaindexOrderBuilder.getOrderDetails as Mock) + .mockResolvedValueOnce({ + value: { orderName: "Order 1", description: "Description 1" }, + error: null, + }) + .mockRejectedValueOnce(new Error("Processing error")) + .mockResolvedValueOnce({ + value: { orderName: "Order 2", description: "Description 2" }, + error: null, + }) + .mockResolvedValueOnce({ + error: { msg: "Validation failed" }, + value: null, + }); + + // Call the function + const result = await validateOrders(registryDotrains); + + // Verify results + expect(result.validOrders).toHaveLength(2); + expect(result.validOrders[0].name).toBe("valid1.rain"); + expect(result.validOrders[1].name).toBe("valid2.rain"); + + expect(result.invalidOrders).toHaveLength(2); + expect(result.invalidOrders[0].name).toBe("error.rain"); + expect(result.invalidOrders[0].error).toBe("Processing error"); + expect(result.invalidOrders[1].name).toBe("invalid.rain"); + expect(result.invalidOrders[1].error).toBe("Validation failed"); + }); }); diff --git a/packages/ui-components/src/__tests__/useToasts.test.ts b/packages/ui-components/src/__tests__/useToasts.test.ts index 5808a6d983..1e19979935 100644 --- a/packages/ui-components/src/__tests__/useToasts.test.ts +++ b/packages/ui-components/src/__tests__/useToasts.test.ts @@ -1,171 +1,171 @@ -import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; -import { writable } from 'svelte/store'; -import { useToasts } from '$lib/providers/toasts/useToasts'; -import type { ToastProps } from '$lib/types/toast'; -import { getToastsContext } from '$lib/providers/toasts/context'; - -vi.mock('$lib/providers/toasts/context', () => ({ - getToastsContext: vi.fn() +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; +import { writable } from "svelte/store"; +import { useToasts } from "$lib/providers/toasts/useToasts"; +import type { ToastProps } from "$lib/types/toast"; +import { getToastsContext } from "$lib/providers/toasts/context"; + +vi.mock("$lib/providers/toasts/context", () => ({ + getToastsContext: vi.fn(), })); -describe('useToasts', () => { - let toastsStore: ReturnType>; - - const getStoreValue = () => { - let value: ToastProps[] = []; - toastsStore.subscribe((val) => { - value = val; - }); - return value; - }; - - beforeEach(() => { - toastsStore = writable([]); - vi.mocked(getToastsContext).mockReturnValue(toastsStore); - }); - - afterEach(() => { - vi.clearAllMocks(); - }); - - it('should return the toasts store and functions', () => { - const result = useToasts(); - - expect(result.toasts).toBe(toastsStore); - expect(typeof result.addToast).toBe('function'); - expect(typeof result.removeToast).toBe('function'); - expect(typeof result.errToast).toBe('function'); - }); - - describe('errToast', () => { - it('should add an error toast with the given message', () => { - const { errToast } = useToasts(); - const message = 'Test error message'; - errToast(message); - - expect(getStoreValue()).toEqual([ - { - message, - type: 'error', - color: 'red' - } - ]); - }); - - it('should add an error toast with the given message and detail', () => { - const { errToast } = useToasts(); - const message = 'Test error message with detail'; - const detail = 'This is some extra detail.'; - errToast(message, detail); - - expect(getStoreValue()).toEqual([ - { - message, - detail, - type: 'error', - color: 'red' - } - ]); - }); - - it('should add an error toast with the given message and undefined detail', () => { - const { errToast } = useToasts(); - const message = 'Test error message with undefined detail'; - errToast(message, undefined); - - expect(getStoreValue()).toEqual([ - { - message, - detail: undefined, - type: 'error', - color: 'red' - } - ]); - }); - }); - - describe('addToast', () => { - it('should add a toast to the store', () => { - const { addToast } = useToasts(); - const testToast: ToastProps = { - message: 'Test Toast', - type: 'info', - color: 'green', - links: [] - }; - - addToast(testToast); - expect(getStoreValue()).toEqual([testToast]); - }); - - it('should add multiple toasts in sequence', () => { - const { addToast } = useToasts(); - const toast1: ToastProps = { - message: 'Toast 1', - type: 'info', - color: 'green', - links: [] - }; - const toast2: ToastProps = { - message: 'Toast 2', - type: 'success', - color: 'blue', - links: [] - }; - - addToast(toast1); - addToast(toast2); - - expect(getStoreValue()).toEqual([toast1, toast2]); - }); - - it('should add a toast with minimal properties', () => { - const { addToast } = useToasts(); - const minimalToast: ToastProps = { - message: 'Minimal Toast', - type: 'warning', - color: 'yellow' - }; - - addToast(minimalToast); - expect(getStoreValue()).toEqual([minimalToast]); - }); - }); - - describe('removeToast', () => { - it('should remove a toast at the specified index', () => { - const { addToast, removeToast } = useToasts(); - const toast1: ToastProps = { - message: 'Toast 1', - type: 'info', - color: 'green' - }; - const toast2: ToastProps = { - message: 'Toast 2', - type: 'success', - color: 'blue' - }; - - addToast(toast1); - addToast(toast2); - removeToast(0); - - expect(getStoreValue()).toEqual([toast2]); - }); - - it('should not modify the store when removing with an invalid index', () => { - const { addToast, removeToast } = useToasts(); - const toast: ToastProps = { - message: 'Test Toast', - type: 'info', - color: 'green' - }; - - addToast(toast); - removeToast(-1); - removeToast(1); - - expect(getStoreValue()).toEqual([toast]); - }); - }); +describe("useToasts", () => { + let toastsStore: ReturnType>; + + const getStoreValue = () => { + let value: ToastProps[] = []; + toastsStore.subscribe((val) => { + value = val; + }); + return value; + }; + + beforeEach(() => { + toastsStore = writable([]); + vi.mocked(getToastsContext).mockReturnValue(toastsStore); + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + it("should return the toasts store and functions", () => { + const result = useToasts(); + + expect(result.toasts).toBe(toastsStore); + expect(typeof result.addToast).toBe("function"); + expect(typeof result.removeToast).toBe("function"); + expect(typeof result.errToast).toBe("function"); + }); + + describe("errToast", () => { + it("should add an error toast with the given message", () => { + const { errToast } = useToasts(); + const message = "Test error message"; + errToast(message); + + expect(getStoreValue()).toEqual([ + { + message, + type: "error", + color: "red", + }, + ]); + }); + + it("should add an error toast with the given message and detail", () => { + const { errToast } = useToasts(); + const message = "Test error message with detail"; + const detail = "This is some extra detail."; + errToast(message, detail); + + expect(getStoreValue()).toEqual([ + { + message, + detail, + type: "error", + color: "red", + }, + ]); + }); + + it("should add an error toast with the given message and undefined detail", () => { + const { errToast } = useToasts(); + const message = "Test error message with undefined detail"; + errToast(message, undefined); + + expect(getStoreValue()).toEqual([ + { + message, + detail: undefined, + type: "error", + color: "red", + }, + ]); + }); + }); + + describe("addToast", () => { + it("should add a toast to the store", () => { + const { addToast } = useToasts(); + const testToast: ToastProps = { + message: "Test Toast", + type: "info", + color: "green", + links: [], + }; + + addToast(testToast); + expect(getStoreValue()).toEqual([testToast]); + }); + + it("should add multiple toasts in sequence", () => { + const { addToast } = useToasts(); + const toast1: ToastProps = { + message: "Toast 1", + type: "info", + color: "green", + links: [], + }; + const toast2: ToastProps = { + message: "Toast 2", + type: "success", + color: "blue", + links: [], + }; + + addToast(toast1); + addToast(toast2); + + expect(getStoreValue()).toEqual([toast1, toast2]); + }); + + it("should add a toast with minimal properties", () => { + const { addToast } = useToasts(); + const minimalToast: ToastProps = { + message: "Minimal Toast", + type: "warning", + color: "yellow", + }; + + addToast(minimalToast); + expect(getStoreValue()).toEqual([minimalToast]); + }); + }); + + describe("removeToast", () => { + it("should remove a toast at the specified index", () => { + const { addToast, removeToast } = useToasts(); + const toast1: ToastProps = { + message: "Toast 1", + type: "info", + color: "green", + }; + const toast2: ToastProps = { + message: "Toast 2", + type: "success", + color: "blue", + }; + + addToast(toast1); + addToast(toast2); + removeToast(0); + + expect(getStoreValue()).toEqual([toast2]); + }); + + it("should not modify the store when removing with an invalid index", () => { + const { addToast, removeToast } = useToasts(); + const toast: ToastProps = { + message: "Test Toast", + type: "info", + color: "green", + }; + + addToast(toast); + removeToast(-1); + removeToast(1); + + expect(getStoreValue()).toEqual([toast]); + }); + }); }); diff --git a/packages/ui-components/src/additional-svelte-typings.d.ts b/packages/ui-components/src/additional-svelte-typings.d.ts index cc18f8751f..dc4a3ea6cb 100644 --- a/packages/ui-components/src/additional-svelte-typings.d.ts +++ b/packages/ui-components/src/additional-svelte-typings.d.ts @@ -1,7 +1,7 @@ declare namespace svelteHTML { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - interface HTMLAttributes { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - 'on:complete'?: (event: any) => any; - } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + interface HTMLAttributes { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + "on:complete"?: (event: any) => any; + } } diff --git a/packages/ui-components/src/app.d.ts b/packages/ui-components/src/app.d.ts index da08e6da59..520c4217a1 100644 --- a/packages/ui-components/src/app.d.ts +++ b/packages/ui-components/src/app.d.ts @@ -1,13 +1,13 @@ // See https://svelte.dev/docs/kit/types#app.d.ts // for information about these interfaces declare global { - namespace App { - // interface Error {} - // interface Locals {} - // interface PageData {} - // interface PageState {} - // interface Platform {} - } + namespace App { + // interface Error {} + // interface Locals {} + // interface PageData {} + // interface PageState {} + // interface Platform {} + } } export {}; diff --git a/packages/ui-components/src/app.html b/packages/ui-components/src/app.html index f22aeaad5e..b37687a19f 100644 --- a/packages/ui-components/src/app.html +++ b/packages/ui-components/src/app.html @@ -1,12 +1,12 @@ - - - - - %sveltekit.head% - - -
    %sveltekit.body%
    - + + + + + %sveltekit.head% + + +
    %sveltekit.body%
    + diff --git a/packages/ui-components/src/lib/__mocks__/MockComponent.ts b/packages/ui-components/src/lib/__mocks__/MockComponent.ts index eb2e74c0df..987f8fbaa3 100644 --- a/packages/ui-components/src/lib/__mocks__/MockComponent.ts +++ b/packages/ui-components/src/lib/__mocks__/MockComponent.ts @@ -1,3 +1,3 @@ -import { writable } from 'svelte/store'; +import { writable } from "svelte/store"; export const props = writable(); diff --git a/packages/ui-components/src/lib/__mocks__/mockWeb3Config.ts b/packages/ui-components/src/lib/__mocks__/mockWeb3Config.ts index 61062fd4d5..bea5561d33 100644 --- a/packages/ui-components/src/lib/__mocks__/mockWeb3Config.ts +++ b/packages/ui-components/src/lib/__mocks__/mockWeb3Config.ts @@ -1,16 +1,19 @@ -import { createConfig, http, fallback, type Config } from '@wagmi/core'; -import { mock } from '@wagmi/connectors'; -import { polygonAmoy } from '@wagmi/core/chains'; +import { createConfig, http, fallback, type Config } from "@wagmi/core"; +import { mock } from "@wagmi/connectors"; +import { polygonAmoy } from "@wagmi/core/chains"; export const mockWeb3Config: Config = createConfig({ - multiInjectedProviderDiscovery: true, - chains: [polygonAmoy], - connectors: [ - mock({ - accounts: ['0xf08bcbce72f62c95dcb7c07dcb5ed26acfcfbc11'] - }) - ], - transports: { - [polygonAmoy.id]: fallback([http(), http('https://rpc-amoy.polygon.technology')]) - } + multiInjectedProviderDiscovery: true, + chains: [polygonAmoy], + connectors: [ + mock({ + accounts: ["0xf08bcbce72f62c95dcb7c07dcb5ed26acfcfbc11"], + }), + ], + transports: { + [polygonAmoy.id]: fallback([ + http(), + http("https://rpc-amoy.polygon.technology"), + ]), + }, }); diff --git a/packages/ui-components/src/lib/__mocks__/queries.ts b/packages/ui-components/src/lib/__mocks__/queries.ts index cb41d08a9b..de0ea455e5 100644 --- a/packages/ui-components/src/lib/__mocks__/queries.ts +++ b/packages/ui-components/src/lib/__mocks__/queries.ts @@ -1,89 +1,98 @@ -import { QueryClient, createInfiniteQuery, createQuery } from '@tanstack/svelte-query'; +import { + QueryClient, + createInfiniteQuery, + createQuery, +} from "@tanstack/svelte-query"; // A helper function to create a resolvable mock query. // This gives us more control over when each query resolves. -export const createResolvableMockQuery = (queryFn: (() => T) | ((pageParam: number) => T)) => { - const resolveQueue: Array<() => void> = []; - let currentPromise: Promise; +export const createResolvableMockQuery = ( + queryFn: (() => T) | ((pageParam: number) => T), +) => { + const resolveQueue: Array<() => void> = []; + let currentPromise: Promise; - const createNewPromise = () => { - currentPromise = new Promise((res) => { - resolveQueue.push(res); - }); - }; + const createNewPromise = () => { + currentPromise = new Promise((res) => { + resolveQueue.push(res); + }); + }; - createNewPromise(); // Initialize the first promise + createNewPromise(); // Initialize the first promise - const resolvableQuery = async (pageParam?: number) => { - const mockData = queryFn(pageParam as number); - await currentPromise; - createNewPromise(); // Create a new promise for the next call - return mockData; - }; + const resolvableQuery = async (pageParam?: number) => { + const mockData = queryFn(pageParam as number); + await currentPromise; + createNewPromise(); // Create a new promise for the next call + return mockData; + }; - const resolve = () => { - const resolver = resolveQueue.shift(); - if (resolver) { - resolver(); - } - }; + const resolve = () => { + const resolver = resolveQueue.shift(); + if (resolver) { + resolver(); + } + }; - return { queryFn: resolvableQuery, resolve }; + return { queryFn: resolvableQuery, resolve }; }; // A helper function to create an infinite Tanstack query that resolves when you call // the `resolve` function. export const createResolvableInfiniteQuery = ( - _queryFn: (pageParam: number) => unknown, - getNextPageParam: ( - _lastPage: unknown, - _allPages: unknown[], - lastPageParam: number - ) => number | undefined = (_lastPage: unknown, _allPages: unknown[], lastPageParam: number) => - lastPageParam + 1 + _queryFn: (pageParam: number) => unknown, + getNextPageParam: ( + _lastPage: unknown, + _allPages: unknown[], + lastPageParam: number, + ) => number | undefined = ( + _lastPage: unknown, + _allPages: unknown[], + lastPageParam: number, + ) => lastPageParam + 1, ) => { - const { queryFn, resolve } = createResolvableMockQuery(_queryFn); - const refetch = vi.fn(); - const query = createInfiniteQuery( - { - queryKey: [], - queryFn: ({ pageParam }) => { - return queryFn(pageParam); - }, - initialPageParam: 0, - getNextPageParam - }, - new QueryClient({ - defaultOptions: { - queries: { - staleTime: Infinity - } - } - }) - ); + const { queryFn, resolve } = createResolvableMockQuery(_queryFn); + const refetch = vi.fn(); + const query = createInfiniteQuery( + { + queryKey: [], + queryFn: ({ pageParam }) => { + return queryFn(pageParam); + }, + initialPageParam: 0, + getNextPageParam, + }, + new QueryClient({ + defaultOptions: { + queries: { + staleTime: Infinity, + }, + }, + }), + ); - return { query, resolve, refetch }; + return { query, resolve, refetch }; }; // A helper function to create a regular Tanstack query that resolves when you call resolve export const createResolvableQuery = (_queryFn: () => T) => { - const { queryFn, resolve } = createResolvableMockQuery(_queryFn); + const { queryFn, resolve } = createResolvableMockQuery(_queryFn); - const query = createQuery( - { - queryKey: [], - queryFn: () => { - return queryFn(); - } - }, - new QueryClient({ - defaultOptions: { - queries: { - staleTime: Infinity - } - } - }) - ); + const query = createQuery( + { + queryKey: [], + queryFn: () => { + return queryFn(); + }, + }, + new QueryClient({ + defaultOptions: { + queries: { + staleTime: Infinity, + }, + }, + }), + ); - return { query, resolve }; + return { query, resolve }; }; diff --git a/packages/ui-components/src/lib/__mocks__/stores.ts b/packages/ui-components/src/lib/__mocks__/stores.ts index b910df51b4..a768bd0519 100644 --- a/packages/ui-components/src/lib/__mocks__/stores.ts +++ b/packages/ui-components/src/lib/__mocks__/stores.ts @@ -1,165 +1,183 @@ -import { writable } from 'svelte/store'; -import type { Address } from '@rainlanguage/raindex'; -import { type Config } from '@wagmi/core'; -import { mockWeb3Config } from './mockWeb3Config'; +import { writable } from "svelte/store"; +import type { Address } from "@rainlanguage/raindex"; +import { type Config } from "@wagmi/core"; +import { mockWeb3Config } from "./mockWeb3Config"; -type MockDeployment = { key: string; name?: string; description?: string } | null; +type MockDeployment = { + key: string; + name?: string; + description?: string; +} | null; type MockPageState = { - data: Record & { deployment: MockDeployment }; - url: URL; - params: Record; - form: Record; - status: number; - error: unknown; - route: { - id: string | null; - }; + data: Record & { deployment: MockDeployment }; + url: URL; + params: Record; + form: Record; + status: number; + error: unknown; + route: { + id: string | null; + }; }; if (import.meta.vitest) { - vi.mock(import('@rainlanguage/raindex'), async (importOriginal) => { - const actual = await importOriginal(); - return { - ...actual - }; - }); + vi.mock(import("@rainlanguage/raindex"), async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + }; + }); } const initialPageState: MockPageState = { - data: { - dotrain: 'some dotrain content', - deployment: { key: 'deploy-key', name: '', description: '' }, - orderDetail: {} - }, - url: new URL('http://localhost:3000/deploy'), - params: {}, - form: {}, - status: 200, - error: null, - route: { - id: null - } + data: { + dotrain: "some dotrain content", + deployment: { key: "deploy-key", name: "", description: "" }, + orderDetail: {}, + }, + url: new URL("http://localhost:3000/deploy"), + params: {}, + form: {}, + status: 200, + error: null, + route: { + id: null, + }, }; const mockPageWritable = writable(initialPageState); const mockShowInactiveOrdersWritable = writable(true); -const mockOrderHashWritable = writable(''); +const mockOrderHashWritable = writable(""); const mockHideZeroBalanceVaultsWritable = writable(false); const mockHideInactiveOrdersVaultsWritable = writable(false); -const mockActiveNetworkRefWritable = writable(''); -const mockActiveRaindexRefWritable = writable(''); +const mockActiveNetworkRefWritable = writable(""); +const mockActiveRaindexRefWritable = writable(""); const mockActiveAccountsWritable = writable>({}); -const mockSubgraphUrlWritable = writable(''); +const mockSubgraphUrlWritable = writable(""); const mockChainIdWritable = writable(0); const mockConnectedWritable = writable(true); const mockWagmiConfigWritable = writable(mockWeb3Config); const mockSelectedChainIdsWritable = writable([]); const mockActiveTokensWritable = writable([]); const mockActiveRaindexAddressesWritable = writable([]); -const mockOwnerFilterWritable = writable
    ('' as Address); +const mockOwnerFilterWritable = writable
    ("" as Address); export const mockShowInactiveOrdersStore = { - subscribe: mockShowInactiveOrdersWritable.subscribe, - set: mockShowInactiveOrdersWritable.set, - mockSetSubscribeValue: (value: boolean): void => mockShowInactiveOrdersWritable.set(value) + subscribe: mockShowInactiveOrdersWritable.subscribe, + set: mockShowInactiveOrdersWritable.set, + mockSetSubscribeValue: (value: boolean): void => + mockShowInactiveOrdersWritable.set(value), }; export const mockOrderHashStore = { - subscribe: mockOrderHashWritable.subscribe, - set: mockOrderHashWritable.set, - mockSetSubscribeValue: (value: string): void => mockOrderHashWritable.set(value) + subscribe: mockOrderHashWritable.subscribe, + set: mockOrderHashWritable.set, + mockSetSubscribeValue: (value: string): void => + mockOrderHashWritable.set(value), }; export const mockHideZeroBalanceVaultsStore = { - subscribe: mockHideZeroBalanceVaultsWritable.subscribe, - set: mockHideZeroBalanceVaultsWritable.set, - mockSetSubscribeValue: (value: boolean): void => mockHideZeroBalanceVaultsWritable.set(value) + subscribe: mockHideZeroBalanceVaultsWritable.subscribe, + set: mockHideZeroBalanceVaultsWritable.set, + mockSetSubscribeValue: (value: boolean): void => + mockHideZeroBalanceVaultsWritable.set(value), }; export const mockHideInactiveOrdersVaultsStore = { - subscribe: mockHideInactiveOrdersVaultsWritable.subscribe, - set: mockHideInactiveOrdersVaultsWritable.set, - mockSetSubscribeValue: (value: boolean): void => mockHideInactiveOrdersVaultsWritable.set(value) + subscribe: mockHideInactiveOrdersVaultsWritable.subscribe, + set: mockHideInactiveOrdersVaultsWritable.set, + mockSetSubscribeValue: (value: boolean): void => + mockHideInactiveOrdersVaultsWritable.set(value), }; export const mockActiveNetworkRefStore = { - subscribe: mockActiveNetworkRefWritable.subscribe, - set: mockActiveNetworkRefWritable.set, - mockSetSubscribeValue: (value: string): void => mockActiveNetworkRefWritable.set(value) + subscribe: mockActiveNetworkRefWritable.subscribe, + set: mockActiveNetworkRefWritable.set, + mockSetSubscribeValue: (value: string): void => + mockActiveNetworkRefWritable.set(value), }; export const mockActiveRaindexRefStore = { - subscribe: mockActiveRaindexRefWritable.subscribe, - set: mockActiveRaindexRefWritable.set, - mockSetSubscribeValue: (value: string): void => mockActiveRaindexRefWritable.set(value) + subscribe: mockActiveRaindexRefWritable.subscribe, + set: mockActiveRaindexRefWritable.set, + mockSetSubscribeValue: (value: string): void => + mockActiveRaindexRefWritable.set(value), }; export const mockActiveAccountsStore = { - subscribe: mockActiveAccountsWritable.subscribe, - set: mockActiveAccountsWritable.set, - mockSetSubscribeValue: (value: Record): void => - mockActiveAccountsWritable.set(value) + subscribe: mockActiveAccountsWritable.subscribe, + set: mockActiveAccountsWritable.set, + mockSetSubscribeValue: (value: Record): void => + mockActiveAccountsWritable.set(value), }; export const mockSubgraphUrlStore = { - subscribe: mockSubgraphUrlWritable.subscribe, - set: mockSubgraphUrlWritable.set, - mockSetSubscribeValue: (value: string): void => mockSubgraphUrlWritable.set(value) + subscribe: mockSubgraphUrlWritable.subscribe, + set: mockSubgraphUrlWritable.set, + mockSetSubscribeValue: (value: string): void => + mockSubgraphUrlWritable.set(value), }; export const mockChainIdStore = { - subscribe: mockChainIdWritable.subscribe, - set: mockChainIdWritable.set, - mockSetSubscribeValue: (value: number): void => mockChainIdWritable.set(value) + subscribe: mockChainIdWritable.subscribe, + set: mockChainIdWritable.set, + mockSetSubscribeValue: (value: number): void => + mockChainIdWritable.set(value), }; export const mockConnectedStore = { - subscribe: mockConnectedWritable.subscribe, - set: mockConnectedWritable.set, - update: mockConnectedWritable.update, - mockSetSubscribeValue: (value: boolean): void => mockConnectedWritable.set(value) + subscribe: mockConnectedWritable.subscribe, + set: mockConnectedWritable.set, + update: mockConnectedWritable.update, + mockSetSubscribeValue: (value: boolean): void => + mockConnectedWritable.set(value), }; export const mockWagmiConfigStore = { - subscribe: mockWagmiConfigWritable.subscribe, - set: mockWagmiConfigWritable.set, - update: mockWagmiConfigWritable.update, - mockSetSubscribeValue: (value: Config): void => mockWagmiConfigWritable.set(value) + subscribe: mockWagmiConfigWritable.subscribe, + set: mockWagmiConfigWritable.set, + update: mockWagmiConfigWritable.update, + mockSetSubscribeValue: (value: Config): void => + mockWagmiConfigWritable.set(value), }; export const mockSelectedChainIdsStore = { - subscribe: mockSelectedChainIdsWritable.subscribe, - set: mockSelectedChainIdsWritable.set, - mockSetSubscribeValue: (value: number[]): void => mockSelectedChainIdsWritable.set(value) + subscribe: mockSelectedChainIdsWritable.subscribe, + set: mockSelectedChainIdsWritable.set, + mockSetSubscribeValue: (value: number[]): void => + mockSelectedChainIdsWritable.set(value), }; export const mockPageStore = { - subscribe: mockPageWritable.subscribe, - set: mockPageWritable.set, - mockSetSubscribeValue: (newValue: Partial): void => { - mockPageWritable.update((currentValue) => ({ - ...currentValue, - ...newValue - })); - }, - reset: () => mockPageWritable.set(initialPageState) + subscribe: mockPageWritable.subscribe, + set: mockPageWritable.set, + mockSetSubscribeValue: (newValue: Partial): void => { + mockPageWritable.update((currentValue) => ({ + ...currentValue, + ...newValue, + })); + }, + reset: () => mockPageWritable.set(initialPageState), }; export const mockActiveTokensStore = { - subscribe: mockActiveTokensWritable.subscribe, - set: mockActiveTokensWritable.set, - mockSetSubscribeValue: (value: string[]): void => mockActiveTokensWritable.set(value) + subscribe: mockActiveTokensWritable.subscribe, + set: mockActiveTokensWritable.set, + mockSetSubscribeValue: (value: string[]): void => + mockActiveTokensWritable.set(value), }; export const mockActiveRaindexAddressesStore = { - subscribe: mockActiveRaindexAddressesWritable.subscribe, - set: mockActiveRaindexAddressesWritable.set, - mockSetSubscribeValue: (value: string[]): void => mockActiveRaindexAddressesWritable.set(value) + subscribe: mockActiveRaindexAddressesWritable.subscribe, + set: mockActiveRaindexAddressesWritable.set, + mockSetSubscribeValue: (value: string[]): void => + mockActiveRaindexAddressesWritable.set(value), }; export const mockOwnerFilterStore = { - subscribe: mockOwnerFilterWritable.subscribe, - set: mockOwnerFilterWritable.set, - mockSetSubscribeValue: (value: Address): void => mockOwnerFilterWritable.set(value) + subscribe: mockOwnerFilterWritable.subscribe, + set: mockOwnerFilterWritable.set, + mockSetSubscribeValue: (value: Address): void => + mockOwnerFilterWritable.set(value), }; diff --git a/packages/ui-components/src/lib/app.css b/packages/ui-components/src/lib/app.css index a31e444117..76fcadcc01 100644 --- a/packages/ui-components/src/lib/app.css +++ b/packages/ui-components/src/lib/app.css @@ -1,3 +1,3 @@ -@import 'tailwindcss/base'; -@import 'tailwindcss/components'; -@import 'tailwindcss/utilities'; +@import "tailwindcss/base"; +@import "tailwindcss/components"; +@import "tailwindcss/utilities"; diff --git a/packages/ui-components/src/lib/components/charts/transformAndSortData.ts b/packages/ui-components/src/lib/components/charts/transformAndSortData.ts index d2378b4fcf..4c674cb512 100644 --- a/packages/ui-components/src/lib/components/charts/transformAndSortData.ts +++ b/packages/ui-components/src/lib/components/charts/transformAndSortData.ts @@ -1,5 +1,5 @@ -import { sortBy } from 'lodash'; -import type { UTCTimestamp } from 'lightweight-charts'; +import { sortBy } from "lodash"; +import type { UTCTimestamp } from "lightweight-charts"; /** * Filters out data points with duplicate timestamps, keeping only the first occurrence. @@ -7,18 +7,20 @@ import type { UTCTimestamp } from 'lightweight-charts'; * @param data Array of data points with time and value properties * @returns A new array with only unique timestamps */ -export const deduplicateByTime = (data: T[]): T[] => { - const uniqueData: T[] = []; - const seenTimes = new Set(); - - for (const dataPoint of data) { - if (!seenTimes.has(dataPoint.time)) { - uniqueData.push(dataPoint); - seenTimes.add(dataPoint.time); - } - } - - return uniqueData; +export const deduplicateByTime = ( + data: T[], +): T[] => { + const uniqueData: T[] = []; + const seenTimes = new Set(); + + for (const dataPoint of data) { + if (!seenTimes.has(dataPoint.time)) { + uniqueData.push(dataPoint); + seenTimes.add(dataPoint.time); + } + } + + return uniqueData; }; /** @@ -29,115 +31,115 @@ export const deduplicateByTime = (data: T[]): * @returns Transformed, sorted, and deduplicated data */ export const transformAndSortData = ( - data: T[], - options: { - valueTransform: (item: T) => number; - timeTransform: (item: T) => UTCTimestamp; - } + data: T[], + options: { + valueTransform: (item: T) => number; + timeTransform: (item: T) => UTCTimestamp; + }, ): Array<{ value: number; time: UTCTimestamp }> => { - const { valueTransform, timeTransform } = options; + const { valueTransform, timeTransform } = options; - const transformedData = data.map((d) => ({ - value: valueTransform(d), - time: timeTransform(d) - })); + const transformedData = data.map((d) => ({ + value: valueTransform(d), + time: timeTransform(d), + })); - const sortedData = sortBy(transformedData, (d) => d.time); + const sortedData = sortBy(transformedData, (d) => d.time); - return deduplicateByTime(sortedData); + return deduplicateByTime(sortedData); }; if (import.meta.vitest) { - const { it, expect, describe } = import.meta.vitest; - - describe('deduplicateByTime', () => { - it('should remove entries with duplicate timestamps', () => { - const data = [ - { time: 100 as UTCTimestamp, value: 10 }, - { time: 200 as UTCTimestamp, value: 20 }, - { time: 200 as UTCTimestamp, value: 25 }, // Duplicate timestamp - { time: 300 as UTCTimestamp, value: 30 } - ]; - - const result = deduplicateByTime(data); - const expected = [ - { time: 100 as UTCTimestamp, value: 10 }, - { time: 200 as UTCTimestamp, value: 20 }, // First occurrence kept - { time: 300 as UTCTimestamp, value: 30 } - ]; - - expect(result).toEqual(expected); - }); - - it('should handle multiple duplicate timestamps', () => { - const data = [ - { time: 100 as UTCTimestamp, value: 10 }, - { time: 100 as UTCTimestamp, value: 15 }, // Duplicate - { time: 100 as UTCTimestamp, value: 18 }, // Duplicate - { time: 200 as UTCTimestamp, value: 20 } - ]; - - const result = deduplicateByTime(data); - const expected = [ - { time: 100 as UTCTimestamp, value: 10 }, // Only first one kept - { time: 200 as UTCTimestamp, value: 20 } - ]; - - expect(result).toEqual(expected); - }); - - it('should return original array if no duplicates', () => { - const data = [ - { time: 100 as UTCTimestamp, value: 10 }, - { time: 200 as UTCTimestamp, value: 20 }, - { time: 300 as UTCTimestamp, value: 30 } - ]; - - const result = deduplicateByTime(data); - expect(result).toEqual(data); - - expect(result).not.toBe(data); - }); - - it('should handle empty array', () => { - const data: Array<{ time: UTCTimestamp; value: number }> = []; - const result = deduplicateByTime(data); - expect(result).toEqual([]); - }); - }); - - describe('transformAndSortData', () => { - it('should transform, sort, and deduplicate data', () => { - const rawData = [ - { timestamp: 3000, price: 300 }, - { timestamp: 1000, price: 100 }, - { timestamp: 2000, price: 200 }, - { timestamp: 2000, price: 250 } // Duplicate timestamp - ]; - - const result = transformAndSortData(rawData, { - valueTransform: (item) => item.price, - timeTransform: (item) => item.timestamp as UTCTimestamp - }); - - const expected = [ - { time: 1000 as UTCTimestamp, value: 100 }, - { time: 2000 as UTCTimestamp, value: 200 }, // First occurrence kept after sorting - { time: 3000 as UTCTimestamp, value: 300 } - ]; - - expect(result).toEqual(expected); - }); - - it('should handle empty data array', () => { - const rawData: Array<{ timestamp: number; price: number }> = []; - - const result = transformAndSortData(rawData, { - valueTransform: (item) => item.price, - timeTransform: (item) => item.timestamp as UTCTimestamp - }); - - expect(result).toEqual([]); - }); - }); + const { it, expect, describe } = import.meta.vitest; + + describe("deduplicateByTime", () => { + it("should remove entries with duplicate timestamps", () => { + const data = [ + { time: 100 as UTCTimestamp, value: 10 }, + { time: 200 as UTCTimestamp, value: 20 }, + { time: 200 as UTCTimestamp, value: 25 }, // Duplicate timestamp + { time: 300 as UTCTimestamp, value: 30 }, + ]; + + const result = deduplicateByTime(data); + const expected = [ + { time: 100 as UTCTimestamp, value: 10 }, + { time: 200 as UTCTimestamp, value: 20 }, // First occurrence kept + { time: 300 as UTCTimestamp, value: 30 }, + ]; + + expect(result).toEqual(expected); + }); + + it("should handle multiple duplicate timestamps", () => { + const data = [ + { time: 100 as UTCTimestamp, value: 10 }, + { time: 100 as UTCTimestamp, value: 15 }, // Duplicate + { time: 100 as UTCTimestamp, value: 18 }, // Duplicate + { time: 200 as UTCTimestamp, value: 20 }, + ]; + + const result = deduplicateByTime(data); + const expected = [ + { time: 100 as UTCTimestamp, value: 10 }, // Only first one kept + { time: 200 as UTCTimestamp, value: 20 }, + ]; + + expect(result).toEqual(expected); + }); + + it("should return original array if no duplicates", () => { + const data = [ + { time: 100 as UTCTimestamp, value: 10 }, + { time: 200 as UTCTimestamp, value: 20 }, + { time: 300 as UTCTimestamp, value: 30 }, + ]; + + const result = deduplicateByTime(data); + expect(result).toEqual(data); + + expect(result).not.toBe(data); + }); + + it("should handle empty array", () => { + const data: Array<{ time: UTCTimestamp; value: number }> = []; + const result = deduplicateByTime(data); + expect(result).toEqual([]); + }); + }); + + describe("transformAndSortData", () => { + it("should transform, sort, and deduplicate data", () => { + const rawData = [ + { timestamp: 3000, price: 300 }, + { timestamp: 1000, price: 100 }, + { timestamp: 2000, price: 200 }, + { timestamp: 2000, price: 250 }, // Duplicate timestamp + ]; + + const result = transformAndSortData(rawData, { + valueTransform: (item) => item.price, + timeTransform: (item) => item.timestamp as UTCTimestamp, + }); + + const expected = [ + { time: 1000 as UTCTimestamp, value: 100 }, + { time: 2000 as UTCTimestamp, value: 200 }, // First occurrence kept after sorting + { time: 3000 as UTCTimestamp, value: 300 }, + ]; + + expect(result).toEqual(expected); + }); + + it("should handle empty data array", () => { + const rawData: Array<{ timestamp: number; price: number }> = []; + + const result = transformAndSortData(rawData, { + valueTransform: (item) => item.price, + timeTransform: (item) => item.timestamp as UTCTimestamp, + }); + + expect(result).toEqual([]); + }); + }); } diff --git a/packages/ui-components/src/lib/components/transactions/getStatusEmoji.ts b/packages/ui-components/src/lib/components/transactions/getStatusEmoji.ts index a07e54ccce..9c0084dd3d 100644 --- a/packages/ui-components/src/lib/components/transactions/getStatusEmoji.ts +++ b/packages/ui-components/src/lib/components/transactions/getStatusEmoji.ts @@ -1,22 +1,26 @@ -import { TransactionStatusMessage } from '$lib/types/transaction'; -import { match } from 'ts-pattern'; +import { TransactionStatusMessage } from "$lib/types/transaction"; +import { match } from "ts-pattern"; export function getStatusEmoji(status: TransactionStatusMessage): string { - return match(status) - .with(TransactionStatusMessage.PENDING_RECEIPT, () => 'šŸ”„') - .with(TransactionStatusMessage.PENDING_SUBGRAPH, () => 'šŸ“Š') - .with(TransactionStatusMessage.SUCCESS, () => 'āœ…') - .with(TransactionStatusMessage.ERROR, () => 'āŒ') - .otherwise(() => 'ā“'); + return match(status) + .with(TransactionStatusMessage.PENDING_RECEIPT, () => "šŸ”„") + .with(TransactionStatusMessage.PENDING_SUBGRAPH, () => "šŸ“Š") + .with(TransactionStatusMessage.SUCCESS, () => "āœ…") + .with(TransactionStatusMessage.ERROR, () => "āŒ") + .otherwise(() => "ā“"); } if (import.meta.vitest) { - describe('getStatusEmoji', () => { - it('should return the correct emoji for each status', () => { - expect(getStatusEmoji(TransactionStatusMessage.PENDING_RECEIPT)).toBe('šŸ”„'); - expect(getStatusEmoji(TransactionStatusMessage.PENDING_SUBGRAPH)).toBe('šŸ“Š'); - expect(getStatusEmoji(TransactionStatusMessage.SUCCESS)).toBe('āœ…'); - expect(getStatusEmoji(TransactionStatusMessage.ERROR)).toBe('āŒ'); - }); - }); + describe("getStatusEmoji", () => { + it("should return the correct emoji for each status", () => { + expect(getStatusEmoji(TransactionStatusMessage.PENDING_RECEIPT)).toBe( + "šŸ”„", + ); + expect(getStatusEmoji(TransactionStatusMessage.PENDING_SUBGRAPH)).toBe( + "šŸ“Š", + ); + expect(getStatusEmoji(TransactionStatusMessage.SUCCESS)).toBe("āœ…"); + expect(getStatusEmoji(TransactionStatusMessage.ERROR)).toBe("āŒ"); + }); + }); } diff --git a/packages/ui-components/src/lib/consts.ts b/packages/ui-components/src/lib/consts.ts index 670260033f..cd4691a217 100644 --- a/packages/ui-components/src/lib/consts.ts +++ b/packages/ui-components/src/lib/consts.ts @@ -1,2 +1,2 @@ export const LICENSE_URL = - 'https://raw.githubusercontent.com/rainlanguage/decentralicense/refs/heads/master/README.md'; + "https://raw.githubusercontent.com/rainlanguage/decentralicense/refs/heads/master/README.md"; diff --git a/packages/ui-components/src/lib/errors/DeploymentStepsError.ts b/packages/ui-components/src/lib/errors/DeploymentStepsError.ts index f808c33730..ad0cdd3d1e 100644 --- a/packages/ui-components/src/lib/errors/DeploymentStepsError.ts +++ b/packages/ui-components/src/lib/errors/DeploymentStepsError.ts @@ -1,58 +1,64 @@ -import { writable } from 'svelte/store'; +import { writable } from "svelte/store"; export enum DeploymentStepsErrorCode { - NO_BUILDER_PROVIDER = 'No builder provider found.', - NO_BUILDER = 'Error loading builder.', - NO_LOCAL_DB_PROVIDER = 'No Local DB provider found.', - NO_STRATEGY = 'No valid order exists at this URL', - NO_SELECT_TOKENS = 'Error loading tokens', - NO_TOKEN_INFO = 'Error loading token information', - NO_FIELD_DEFINITIONS = 'Error loading field definitions', - NO_DEPOSITS = 'Error loading deposits', - NO_TOKEN_INPUTS = 'Error loading token inputs', - NO_TOKEN_OUTPUTS = 'Error loading token outputs', - NO_BUILDER_DETAILS = 'Error getting builder details', - NO_CHAIN = 'Unsupported chain ID', - NO_NETWORK_KEY = 'No network key found', - NO_AVAILABLE_TOKENS = 'Error loading available tokens', - SERIALIZE_ERROR = 'Error serializing state', - ADD_ORDER_FAILED = 'Failed to add order', - NO_WALLET = 'No account address found', - NO_BUILDER_CONFIG = 'Error getting builder configuration', - NO_RAINDEX_CLIENT_PROVIDER = 'No Raindex client provider found' + NO_BUILDER_PROVIDER = "No builder provider found.", + NO_BUILDER = "Error loading builder.", + NO_LOCAL_DB_PROVIDER = "No Local DB provider found.", + NO_STRATEGY = "No valid order exists at this URL", + NO_SELECT_TOKENS = "Error loading tokens", + NO_TOKEN_INFO = "Error loading token information", + NO_FIELD_DEFINITIONS = "Error loading field definitions", + NO_DEPOSITS = "Error loading deposits", + NO_TOKEN_INPUTS = "Error loading token inputs", + NO_TOKEN_OUTPUTS = "Error loading token outputs", + NO_BUILDER_DETAILS = "Error getting builder details", + NO_CHAIN = "Unsupported chain ID", + NO_NETWORK_KEY = "No network key found", + NO_AVAILABLE_TOKENS = "Error loading available tokens", + SERIALIZE_ERROR = "Error serializing state", + ADD_ORDER_FAILED = "Failed to add order", + NO_WALLET = "No account address found", + NO_BUILDER_CONFIG = "Error getting builder configuration", + NO_RAINDEX_CLIENT_PROVIDER = "No Raindex client provider found", } export class DeploymentStepsError extends Error { - private static errorStore = writable(null); + private static errorStore = writable(null); - constructor( - public code: DeploymentStepsErrorCode, - public details?: string - ) { - super(code); - this.name = 'DeploymentStepsError'; - } + constructor( + public code: DeploymentStepsErrorCode, + public details?: string, + ) { + super(code); + this.name = "DeploymentStepsError"; + } - static get error() { - return this.errorStore; - } + static get error() { + return this.errorStore; + } - static throwIfNull(value: T | null | undefined, code: DeploymentStepsErrorCode): T { - if (value === null || value === undefined) { - throw new DeploymentStepsError(code); - } - return value; - } + static throwIfNull( + value: T | null | undefined, + code: DeploymentStepsErrorCode, + ): T { + if (value === null || value === undefined) { + throw new DeploymentStepsError(code); + } + return value; + } - static catch(e: unknown, code: DeploymentStepsErrorCode) { - const error = - e instanceof DeploymentStepsError - ? e - : new DeploymentStepsError(code, e instanceof Error ? e.message : 'Unknown error'); - this.errorStore.set(error); - } + static catch(e: unknown, code: DeploymentStepsErrorCode) { + const error = + e instanceof DeploymentStepsError + ? e + : new DeploymentStepsError( + code, + e instanceof Error ? e.message : "Unknown error", + ); + this.errorStore.set(error); + } - static clear() { - this.errorStore.set(null); - } + static clear() { + this.errorStore.set(null); + } } diff --git a/packages/ui-components/src/lib/errors/index.ts b/packages/ui-components/src/lib/errors/index.ts index ce56dac312..01595f6e94 100644 --- a/packages/ui-components/src/lib/errors/index.ts +++ b/packages/ui-components/src/lib/errors/index.ts @@ -1 +1 @@ -export * from './DeploymentStepsError'; +export * from "./DeploymentStepsError"; diff --git a/packages/ui-components/src/lib/hooks/useLocalDb.ts b/packages/ui-components/src/lib/hooks/useLocalDb.ts index afd3d09f64..1171e2a249 100644 --- a/packages/ui-components/src/lib/hooks/useLocalDb.ts +++ b/packages/ui-components/src/lib/hooks/useLocalDb.ts @@ -1,13 +1,19 @@ -import { getContext } from 'svelte'; -import type { SQLiteWasmDatabase } from '@rainlanguage/sqlite-web'; -import { DeploymentStepsError, DeploymentStepsErrorCode } from '../errors/DeploymentStepsError'; +import { getContext } from "svelte"; +import type { SQLiteWasmDatabase } from "@rainlanguage/sqlite-web"; +import { + DeploymentStepsError, + DeploymentStepsErrorCode, +} from "../errors/DeploymentStepsError"; -export const LOCAL_DB_CONTEXT_KEY = 'local-db-context'; +export const LOCAL_DB_CONTEXT_KEY = "local-db-context"; export function useLocalDb(): SQLiteWasmDatabase { - const db = getContext(LOCAL_DB_CONTEXT_KEY); - if (!db) { - DeploymentStepsError.catch(null, DeploymentStepsErrorCode.NO_LOCAL_DB_PROVIDER); - } - return db; + const db = getContext(LOCAL_DB_CONTEXT_KEY); + if (!db) { + DeploymentStepsError.catch( + null, + DeploymentStepsErrorCode.NO_LOCAL_DB_PROVIDER, + ); + } + return db; } diff --git a/packages/ui-components/src/lib/hooks/useRaindexClient.test.ts b/packages/ui-components/src/lib/hooks/useRaindexClient.test.ts index 1d490aa3b3..41ba0d06f6 100644 --- a/packages/ui-components/src/lib/hooks/useRaindexClient.test.ts +++ b/packages/ui-components/src/lib/hooks/useRaindexClient.test.ts @@ -1,45 +1,51 @@ -import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; -import { getContext } from 'svelte'; -import { useRaindexClient, RAINDEX_CLIENT_CONTEXT_KEY } from './useRaindexClient'; -import { DeploymentStepsError, DeploymentStepsErrorCode } from '../errors/DeploymentStepsError'; - -vi.mock('svelte', () => ({ - getContext: vi.fn() +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; +import { getContext } from "svelte"; +import { + useRaindexClient, + RAINDEX_CLIENT_CONTEXT_KEY, +} from "./useRaindexClient"; +import { + DeploymentStepsError, + DeploymentStepsErrorCode, +} from "../errors/DeploymentStepsError"; + +vi.mock("svelte", () => ({ + getContext: vi.fn(), })); -vi.spyOn(DeploymentStepsError, 'catch'); +vi.spyOn(DeploymentStepsError, "catch"); -describe('useRaindexClient hook', () => { - beforeEach(() => { - vi.clearAllMocks(); - }); +describe("useRaindexClient hook", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); - afterEach(() => { - vi.clearAllMocks(); - }); + afterEach(() => { + vi.clearAllMocks(); + }); - it('should return Raindex client when available', () => { - const mockRaindexClient = { - someMethod: vi.fn(), - someProperty: 'value' - }; + it("should return Raindex client when available", () => { + const mockRaindexClient = { + someMethod: vi.fn(), + someProperty: "value", + }; - vi.mocked(getContext).mockReturnValue(mockRaindexClient); + vi.mocked(getContext).mockReturnValue(mockRaindexClient); - const result = useRaindexClient(); + const result = useRaindexClient(); - expect(getContext).toHaveBeenCalledWith(RAINDEX_CLIENT_CONTEXT_KEY); - expect(result).toBe(mockRaindexClient); - }); + expect(getContext).toHaveBeenCalledWith(RAINDEX_CLIENT_CONTEXT_KEY); + expect(result).toBe(mockRaindexClient); + }); - it('should call DeploymentStepsError.catch when Raindex client context is not available', () => { - vi.mocked(getContext).mockReturnValue(null); + it("should call DeploymentStepsError.catch when Raindex client context is not available", () => { + vi.mocked(getContext).mockReturnValue(null); - useRaindexClient(); + useRaindexClient(); - expect(DeploymentStepsError.catch).toHaveBeenCalledWith( - null, - DeploymentStepsErrorCode.NO_RAINDEX_CLIENT_PROVIDER - ); - }); + expect(DeploymentStepsError.catch).toHaveBeenCalledWith( + null, + DeploymentStepsErrorCode.NO_RAINDEX_CLIENT_PROVIDER, + ); + }); }); diff --git a/packages/ui-components/src/lib/hooks/useRaindexClient.ts b/packages/ui-components/src/lib/hooks/useRaindexClient.ts index a84927e8de..1a57de11d2 100644 --- a/packages/ui-components/src/lib/hooks/useRaindexClient.ts +++ b/packages/ui-components/src/lib/hooks/useRaindexClient.ts @@ -1,12 +1,18 @@ -import { getContext } from 'svelte'; -import { RaindexClient } from '@rainlanguage/raindex'; -import { DeploymentStepsError, DeploymentStepsErrorCode } from '../errors/DeploymentStepsError'; -export const RAINDEX_CLIENT_CONTEXT_KEY = 'raindex-client-context'; +import { getContext } from "svelte"; +import { RaindexClient } from "@rainlanguage/raindex"; +import { + DeploymentStepsError, + DeploymentStepsErrorCode, +} from "../errors/DeploymentStepsError"; +export const RAINDEX_CLIENT_CONTEXT_KEY = "raindex-client-context"; export function useRaindexClient(): RaindexClient { - const raindexClient = getContext(RAINDEX_CLIENT_CONTEXT_KEY); - if (!raindexClient) { - DeploymentStepsError.catch(null, DeploymentStepsErrorCode.NO_RAINDEX_CLIENT_PROVIDER); - } - return raindexClient; + const raindexClient = getContext(RAINDEX_CLIENT_CONTEXT_KEY); + if (!raindexClient) { + DeploymentStepsError.catch( + null, + DeploymentStepsErrorCode.NO_RAINDEX_CLIENT_PROVIDER, + ); + } + return raindexClient; } diff --git a/packages/ui-components/src/lib/hooks/useRaindexOrderBuilder.test.ts b/packages/ui-components/src/lib/hooks/useRaindexOrderBuilder.test.ts index 1678adc0bc..defb1c355e 100644 --- a/packages/ui-components/src/lib/hooks/useRaindexOrderBuilder.test.ts +++ b/packages/ui-components/src/lib/hooks/useRaindexOrderBuilder.test.ts @@ -1,48 +1,51 @@ -import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; -import { getContext } from 'svelte'; +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; +import { getContext } from "svelte"; import { - useRaindexOrderBuilder, - RAINDEX_ORDER_BUILDER_CONTEXT_KEY -} from './useRaindexOrderBuilder'; -import { DeploymentStepsError, DeploymentStepsErrorCode } from '../errors/DeploymentStepsError'; + useRaindexOrderBuilder, + RAINDEX_ORDER_BUILDER_CONTEXT_KEY, +} from "./useRaindexOrderBuilder"; +import { + DeploymentStepsError, + DeploymentStepsErrorCode, +} from "../errors/DeploymentStepsError"; -vi.mock('svelte', () => ({ - getContext: vi.fn() +vi.mock("svelte", () => ({ + getContext: vi.fn(), })); -vi.spyOn(DeploymentStepsError, 'catch'); +vi.spyOn(DeploymentStepsError, "catch"); -describe('useRaindexOrderBuilder hook', () => { - beforeEach(() => { - vi.clearAllMocks(); - }); +describe("useRaindexOrderBuilder hook", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); - afterEach(() => { - vi.clearAllMocks(); - }); + afterEach(() => { + vi.clearAllMocks(); + }); - it('should return builder context when available', () => { - const mockBuilder = { - someMethod: vi.fn(), - someProperty: 'value' - }; + it("should return builder context when available", () => { + const mockBuilder = { + someMethod: vi.fn(), + someProperty: "value", + }; - vi.mocked(getContext).mockReturnValue(mockBuilder); + vi.mocked(getContext).mockReturnValue(mockBuilder); - const result = useRaindexOrderBuilder(); + const result = useRaindexOrderBuilder(); - expect(getContext).toHaveBeenCalledWith(RAINDEX_ORDER_BUILDER_CONTEXT_KEY); - expect(result).toBe(mockBuilder); - }); + expect(getContext).toHaveBeenCalledWith(RAINDEX_ORDER_BUILDER_CONTEXT_KEY); + expect(result).toBe(mockBuilder); + }); - it('should call DeploymentStepsError.catch when builder context is not available', () => { - vi.mocked(getContext).mockReturnValue(null); + it("should call DeploymentStepsError.catch when builder context is not available", () => { + vi.mocked(getContext).mockReturnValue(null); - useRaindexOrderBuilder(); + useRaindexOrderBuilder(); - expect(DeploymentStepsError.catch).toHaveBeenCalledWith( - null, - DeploymentStepsErrorCode.NO_BUILDER_PROVIDER - ); - }); + expect(DeploymentStepsError.catch).toHaveBeenCalledWith( + null, + DeploymentStepsErrorCode.NO_BUILDER_PROVIDER, + ); + }); }); diff --git a/packages/ui-components/src/lib/index.ts b/packages/ui-components/src/lib/index.ts index 4211283950..414fe8053c 100644 --- a/packages/ui-components/src/lib/index.ts +++ b/packages/ui-components/src/lib/index.ts @@ -1,164 +1,179 @@ // Components -export { default as CardProperty } from './components/CardProperty.svelte'; -export { default as Hash, HashType } from './components/Hash.svelte'; -export { default as TanstackAppTable } from './components/TanstackAppTable.svelte'; -export { default as DropdownCheckbox } from './components/dropdown/DropdownCheckbox.svelte'; -export { default as DropdownTokensFilter } from './components/dropdown/DropdownTokensFilter.svelte'; -export { default as DropdownRaindexesFilter } from './components/dropdown/DropdownRaindexesFilter.svelte'; -export { default as InputOwnerFilter } from './components/input/InputOwnerFilter.svelte'; -export { default as DropdownRadio } from './components/dropdown/DropdownRadio.svelte'; -export { default as Refresh } from './components/icon/Refresh.svelte'; -export { default as CheckboxActiveOrders } from './components/checkbox/CheckboxActiveOrders.svelte'; -export { default as InputOrderHash } from './components/input/InputOrderHash.svelte'; -export { default as CheckboxZeroBalanceVault } from './components/CheckboxZeroBalanceVault.svelte'; -export { default as CheckboxInactiveOrdersVault } from './components/CheckboxInactiveOrdersVault.svelte'; -export { default as ListViewRaindexFilters } from './components/ListViewRaindexFilters.svelte'; -export { default as OrdersListTable } from './components/tables/OrdersListTable.svelte'; -export { default as VaultsListTable } from './components/tables/VaultsListTable.svelte'; -export { default as PageHeader } from './components/PageHeader.svelte'; -export { default as CodeMirrorRainlang } from './components/CodeMirrorRainlang.svelte'; -export { default as BadgeActive } from './components/BadgeActive.svelte'; -export { default as ButtonVaultLink } from './components/ButtonVaultLink.svelte'; -export { default as ButtonTab } from './components/ButtonTab.svelte'; -export { default as ChartTimeFilters } from './components/charts/ChartTimeFilters.svelte'; -export { default as LightweightChart } from './components/charts/LightweightChart.svelte'; -export { default as TanstackLightweightChartLine } from './components/charts/TanstackLightweightChartLine.svelte'; -export { default as MockComponent } from './__mocks__/MockComponent.svelte'; -export { default as OrderTradesChart } from './components/charts/OrderTradesChart.svelte'; -export { default as TableTimeFilters } from './components/charts/TableTimeFilters.svelte'; -export { default as OrderTradesListTable } from './components/tables/OrderTradesListTable.svelte'; -export { default as Checkbox } from './components/checkbox/Checkbox.svelte'; -export { default as TanstackPageContentDetail } from './components/detail/TanstackPageContentDetail.svelte'; -export { default as TanstackOrderQuote } from './components/detail/TanstackOrderQuote.svelte'; -export { default as EditableSpan } from './components/EditableSpan.svelte'; -export { default as OrderVaultsVolTable } from './components/tables/OrderVaultsVolTable.svelte'; -export { default as OrderDetail } from './components/detail/OrderDetail.svelte'; -export { default as BlockQuote } from './components/BlockQuote.svelte'; -export { default as Heading } from './components/Heading.svelte'; -export { default as Text } from './components/Text.svelte'; -export { default as DropdownProperty } from './components/DropdownProperty.svelte'; -export { default as IconError } from './components/IconError.svelte'; -export { default as ButtonLoading } from './components/ButtonLoading.svelte'; -export { default as IconExternalLink } from './components/IconExternalLink.svelte'; -export { default as IconInfo } from './components/IconInfo.svelte'; -export { default as IconLedger } from './components/IconLedger.svelte'; -export { default as IconSuccess } from './components/IconSuccess.svelte'; -export { default as IconTelegram } from './components/IconTelegram.svelte'; -export { default as IconWalletConnect } from './components/IconWalletConnect.svelte'; -export { default as IconWarning } from './components/IconWarning.svelte'; -export { default as FieldDefinitionInput } from './components/deployment/FieldDefinitionInput.svelte'; -export { default as DepositInput } from './components/deployment/DepositInput.svelte'; -export { default as DeploymentSteps } from './components/deployment/DeploymentSteps.svelte'; -export { default as TokenIOInput } from './components/deployment/TokenIOInput.svelte'; -export { default as SelectToken } from './components/deployment/SelectToken.svelte'; -export { default as VaultBalanceChangesTable } from './components/tables/VaultBalanceChangesTable.svelte'; -export { default as VaultBalanceChangeTypeFilter } from './components/VaultBalanceChangeTypeFilter.svelte'; -export { default as VaultBalanceChart } from './components/charts/VaultBalanceChart.svelte'; -export { default as VaultDetail } from './components/detail/VaultDetail.svelte'; -export { default as InputToken } from './components/input/InputToken.svelte'; -export { default as CodeMirrorDotrain } from './components/CodeMirrorDotrain.svelte'; -export { default as OrderOrVaultHash } from './components/OrderOrVaultHash.svelte'; -export { default as License } from './components/License.svelte'; -export { default as ButtonDarkMode } from './components/ButtonDarkMode.svelte'; -export { default as OrderPage } from './components/deployment/OrderPage.svelte'; -export { default as InputHex } from './components/input/InputHex.svelte'; -export { default as InputTokenAmount } from './components/input/InputTokenAmount.svelte'; -export { default as WalletConnect } from './components/wallet/WalletConnect.svelte'; -export { default as DisclaimerModal } from './components/deployment/DisclaimerModal.svelte'; -export { default as InvalidOrdersSection } from './components/deployment/InvalidOrdersSection.svelte'; -export { default as ValidOrdersSection } from './components/deployment/ValidOrdersSection.svelte'; -export { default as InputRegistryUrl } from './components/input/InputRegistryUrl.svelte'; -export { default as TransactionList } from './components/transactions/TransactionList.svelte'; -export { default as FixedBottomTransaction } from './components/transactions/FixedBottomTransaction.svelte'; -export { default as LocalDbStatusCard } from './components/LocalDbStatusCard.svelte'; -export { default as LocalDbStatusBadge } from './components/LocalDbStatusBadge.svelte'; -export { default as LocalDbStatusModal } from './components/LocalDbStatusModal.svelte'; +export { default as CardProperty } from "./components/CardProperty.svelte"; +export { default as Hash, HashType } from "./components/Hash.svelte"; +export { default as TanstackAppTable } from "./components/TanstackAppTable.svelte"; +export { default as DropdownCheckbox } from "./components/dropdown/DropdownCheckbox.svelte"; +export { default as DropdownTokensFilter } from "./components/dropdown/DropdownTokensFilter.svelte"; +export { default as DropdownRaindexesFilter } from "./components/dropdown/DropdownRaindexesFilter.svelte"; +export { default as InputOwnerFilter } from "./components/input/InputOwnerFilter.svelte"; +export { default as DropdownRadio } from "./components/dropdown/DropdownRadio.svelte"; +export { default as Refresh } from "./components/icon/Refresh.svelte"; +export { default as CheckboxActiveOrders } from "./components/checkbox/CheckboxActiveOrders.svelte"; +export { default as InputOrderHash } from "./components/input/InputOrderHash.svelte"; +export { default as CheckboxZeroBalanceVault } from "./components/CheckboxZeroBalanceVault.svelte"; +export { default as CheckboxInactiveOrdersVault } from "./components/CheckboxInactiveOrdersVault.svelte"; +export { default as ListViewRaindexFilters } from "./components/ListViewRaindexFilters.svelte"; +export { default as OrdersListTable } from "./components/tables/OrdersListTable.svelte"; +export { default as VaultsListTable } from "./components/tables/VaultsListTable.svelte"; +export { default as PageHeader } from "./components/PageHeader.svelte"; +export { default as CodeMirrorRainlang } from "./components/CodeMirrorRainlang.svelte"; +export { default as BadgeActive } from "./components/BadgeActive.svelte"; +export { default as ButtonVaultLink } from "./components/ButtonVaultLink.svelte"; +export { default as ButtonTab } from "./components/ButtonTab.svelte"; +export { default as ChartTimeFilters } from "./components/charts/ChartTimeFilters.svelte"; +export { default as LightweightChart } from "./components/charts/LightweightChart.svelte"; +export { default as TanstackLightweightChartLine } from "./components/charts/TanstackLightweightChartLine.svelte"; +export { default as MockComponent } from "./__mocks__/MockComponent.svelte"; +export { default as OrderTradesChart } from "./components/charts/OrderTradesChart.svelte"; +export { default as TableTimeFilters } from "./components/charts/TableTimeFilters.svelte"; +export { default as OrderTradesListTable } from "./components/tables/OrderTradesListTable.svelte"; +export { default as Checkbox } from "./components/checkbox/Checkbox.svelte"; +export { default as TanstackPageContentDetail } from "./components/detail/TanstackPageContentDetail.svelte"; +export { default as TanstackOrderQuote } from "./components/detail/TanstackOrderQuote.svelte"; +export { default as EditableSpan } from "./components/EditableSpan.svelte"; +export { default as OrderVaultsVolTable } from "./components/tables/OrderVaultsVolTable.svelte"; +export { default as OrderDetail } from "./components/detail/OrderDetail.svelte"; +export { default as BlockQuote } from "./components/BlockQuote.svelte"; +export { default as Heading } from "./components/Heading.svelte"; +export { default as Text } from "./components/Text.svelte"; +export { default as DropdownProperty } from "./components/DropdownProperty.svelte"; +export { default as IconError } from "./components/IconError.svelte"; +export { default as ButtonLoading } from "./components/ButtonLoading.svelte"; +export { default as IconExternalLink } from "./components/IconExternalLink.svelte"; +export { default as IconInfo } from "./components/IconInfo.svelte"; +export { default as IconLedger } from "./components/IconLedger.svelte"; +export { default as IconSuccess } from "./components/IconSuccess.svelte"; +export { default as IconTelegram } from "./components/IconTelegram.svelte"; +export { default as IconWalletConnect } from "./components/IconWalletConnect.svelte"; +export { default as IconWarning } from "./components/IconWarning.svelte"; +export { default as FieldDefinitionInput } from "./components/deployment/FieldDefinitionInput.svelte"; +export { default as DepositInput } from "./components/deployment/DepositInput.svelte"; +export { default as DeploymentSteps } from "./components/deployment/DeploymentSteps.svelte"; +export { default as TokenIOInput } from "./components/deployment/TokenIOInput.svelte"; +export { default as SelectToken } from "./components/deployment/SelectToken.svelte"; +export { default as VaultBalanceChangesTable } from "./components/tables/VaultBalanceChangesTable.svelte"; +export { default as VaultBalanceChangeTypeFilter } from "./components/VaultBalanceChangeTypeFilter.svelte"; +export { default as VaultBalanceChart } from "./components/charts/VaultBalanceChart.svelte"; +export { default as VaultDetail } from "./components/detail/VaultDetail.svelte"; +export { default as InputToken } from "./components/input/InputToken.svelte"; +export { default as CodeMirrorDotrain } from "./components/CodeMirrorDotrain.svelte"; +export { default as OrderOrVaultHash } from "./components/OrderOrVaultHash.svelte"; +export { default as License } from "./components/License.svelte"; +export { default as ButtonDarkMode } from "./components/ButtonDarkMode.svelte"; +export { default as OrderPage } from "./components/deployment/OrderPage.svelte"; +export { default as InputHex } from "./components/input/InputHex.svelte"; +export { default as InputTokenAmount } from "./components/input/InputTokenAmount.svelte"; +export { default as WalletConnect } from "./components/wallet/WalletConnect.svelte"; +export { default as DisclaimerModal } from "./components/deployment/DisclaimerModal.svelte"; +export { default as InvalidOrdersSection } from "./components/deployment/InvalidOrdersSection.svelte"; +export { default as ValidOrdersSection } from "./components/deployment/ValidOrdersSection.svelte"; +export { default as InputRegistryUrl } from "./components/input/InputRegistryUrl.svelte"; +export { default as TransactionList } from "./components/transactions/TransactionList.svelte"; +export { default as FixedBottomTransaction } from "./components/transactions/FixedBottomTransaction.svelte"; +export { default as LocalDbStatusCard } from "./components/LocalDbStatusCard.svelte"; +export { default as LocalDbStatusBadge } from "./components/LocalDbStatusBadge.svelte"; +export { default as LocalDbStatusModal } from "./components/LocalDbStatusModal.svelte"; //Types -export type { AppStoresInterface } from './types/appStores.ts'; +export type { AppStoresInterface } from "./types/appStores.ts"; export { - TransactionStatusMessage, - TransactionStoreErrorMessage, - type TransactionArgs, - type VaultActionArgs -} from './types/transaction'; + TransactionStatusMessage, + TransactionStoreErrorMessage, + type TransactionArgs, + type VaultActionArgs, +} from "./types/transaction"; export type { - VaultActionModalProps, - QuoteDebugModalHandler, - DebugTradeModalHandler, - DisclaimerModalProps, - TransactionConfirmationProps, - HandleTransactionConfirmationModal -} from './types/modal'; -export type { ValidOrderDetail, InvalidOrderDetail } from './types/order.ts'; -export type { ToastProps } from './types/toast'; -export type { DotrainRegistryContext } from './providers/dotrainRegistry/context'; + VaultActionModalProps, + QuoteDebugModalHandler, + DebugTradeModalHandler, + DisclaimerModalProps, + TransactionConfirmationProps, + HandleTransactionConfirmationModal, +} from "./types/modal"; +export type { ValidOrderDetail, InvalidOrderDetail } from "./types/order.ts"; +export type { ToastProps } from "./types/toast"; +export type { DotrainRegistryContext } from "./providers/dotrainRegistry/context"; // Functions -export { createResolvableQuery, createResolvableInfiniteQuery } from './__mocks__/queries'; export { - formatTimestampSecondsAsLocal, - timestampSecondsToUTCTimestamp, - promiseTimeout -} from './services/time'; -export { bigintStringToHex, HEX_INPUT_REGEX } from './utils/hex'; -export { getExplorerLink } from './services/getExplorerLink'; -export { invalidateTanstackQueries } from './queries/queryClient'; -export { getToastsContext } from './providers/toasts/context'; -export { getNetworkName } from './utils/getNetworkName'; + createResolvableQuery, + createResolvableInfiniteQuery, +} from "./__mocks__/queries"; +export { + formatTimestampSecondsAsLocal, + timestampSecondsToUTCTimestamp, + promiseTimeout, +} from "./services/time"; +export { bigintStringToHex, HEX_INPUT_REGEX } from "./utils/hex"; +export { getExplorerLink } from "./services/getExplorerLink"; +export { invalidateTanstackQueries } from "./queries/queryClient"; +export { getToastsContext } from "./providers/toasts/context"; +export { getNetworkName } from "./utils/getNetworkName"; // Constants -export { DEFAULT_PAGE_SIZE, DEFAULT_REFRESH_INTERVAL } from './queries/constants'; export { - QKEY_VAULTS, - QKEY_VAULT, - QKEY_VAULT_CHANGES, - QKEY_ORDERS, - QKEY_ORDER, - QKEY_ORDER_TRADES_LIST, - QKEY_ORDER_QUOTE, - QKEY_VAULTS_VOL_LIST, - QKEY_ORDER_APY -} from './queries/keys'; -export { darkChartTheme, lightChartTheme } from './utils/lightweightChartsThemes'; -export { lightCodeMirrorTheme, darkCodeMirrorTheme } from './utils/codeMirrorThemes'; + DEFAULT_PAGE_SIZE, + DEFAULT_REFRESH_INTERVAL, +} from "./queries/constants"; +export { + QKEY_VAULTS, + QKEY_VAULT, + QKEY_VAULT_CHANGES, + QKEY_ORDERS, + QKEY_ORDER, + QKEY_ORDER_TRADES_LIST, + QKEY_ORDER_QUOTE, + QKEY_VAULTS_VOL_LIST, + QKEY_ORDER_APY, +} from "./queries/keys"; +export { + darkChartTheme, + lightChartTheme, +} from "./utils/lightweightChartsThemes"; +export { + lightCodeMirrorTheme, + darkCodeMirrorTheme, +} from "./utils/codeMirrorThemes"; // Stores export { - cachedWritableStore, - cachedWritableIntOptional, - cachedWritableStringOptional, - cachedWritableString -} from './storesGeneric/cachedWritableStore'; + cachedWritableStore, + cachedWritableIntOptional, + cachedWritableStringOptional, + cachedWritableString, +} from "./storesGeneric/cachedWritableStore"; // Assets -export { default as logoLight } from './assets/logo-light.svg'; -export { default as logoDark } from './assets/logo-dark.svg'; +export { default as logoLight } from "./assets/logo-light.svg"; +export { default as logoDark } from "./assets/logo-dark.svg"; // Providers -export { default as RaindexOrderBuilderProvider } from './providers/RaindexOrderBuilderProvider.svelte'; -export { default as RaindexClientProvider } from './providers/RaindexClientProvider.svelte'; -export { default as WalletProvider } from './providers/wallet/WalletProvider.svelte'; -export { default as RegistryProvider } from './providers/registry/RegistryProvider.svelte'; -export { default as ToastProvider } from './providers/toasts/ToastProvider.svelte'; -export { default as TransactionProvider } from './providers/transactions/TransactionProvider.svelte'; -export { default as LocalDbProvider } from './providers/LocalDbProvider.svelte'; -export { default as DotrainRegistryProvider } from './providers/dotrainRegistry/DotrainRegistryProvider.svelte'; +export { default as RaindexOrderBuilderProvider } from "./providers/RaindexOrderBuilderProvider.svelte"; +export { default as RaindexClientProvider } from "./providers/RaindexClientProvider.svelte"; +export { default as WalletProvider } from "./providers/wallet/WalletProvider.svelte"; +export { default as RegistryProvider } from "./providers/registry/RegistryProvider.svelte"; +export { default as ToastProvider } from "./providers/toasts/ToastProvider.svelte"; +export { default as TransactionProvider } from "./providers/transactions/TransactionProvider.svelte"; +export { default as LocalDbProvider } from "./providers/LocalDbProvider.svelte"; +export { default as DotrainRegistryProvider } from "./providers/dotrainRegistry/DotrainRegistryProvider.svelte"; // Hooks -export { useRaindexOrderBuilder } from './hooks/useRaindexOrderBuilder'; -export { useRaindexClient, RAINDEX_CLIENT_CONTEXT_KEY } from './hooks/useRaindexClient'; -export { useLocalDb } from './hooks/useLocalDb'; -export { useAccount } from './providers/wallet/useAccount'; -export { useRegistry } from './providers/registry/useRegistry'; -export { useToasts } from './providers/toasts/useToasts'; -export { useTransactions } from './providers/transactions/useTransactions'; -export { useDotrainRegistry } from './providers/dotrainRegistry/useDotrainRegistry'; +export { useRaindexOrderBuilder } from "./hooks/useRaindexOrderBuilder"; +export { + useRaindexClient, + RAINDEX_CLIENT_CONTEXT_KEY, +} from "./hooks/useRaindexClient"; +export { useLocalDb } from "./hooks/useLocalDb"; +export { useAccount } from "./providers/wallet/useAccount"; +export { useRegistry } from "./providers/registry/useRegistry"; +export { useToasts } from "./providers/toasts/useToasts"; +export { useTransactions } from "./providers/transactions/useTransactions"; +export { useDotrainRegistry } from "./providers/dotrainRegistry/useDotrainRegistry"; // Classes -export { RegistryManager } from './providers/registry/RegistryManager'; -export { TransactionStore } from './models/Transaction'; -export { TransactionManager } from './providers/transactions/TransactionManager'; +export { RegistryManager } from "./providers/registry/RegistryManager"; +export { TransactionStore } from "./models/Transaction"; +export { TransactionManager } from "./providers/transactions/TransactionManager"; // Mocks -export { mockPageStore } from './__mocks__/stores'; +export { mockPageStore } from "./__mocks__/stores"; diff --git a/packages/ui-components/src/lib/models/Transaction.ts b/packages/ui-components/src/lib/models/Transaction.ts index 79d3dcf574..0df2a184f6 100644 --- a/packages/ui-components/src/lib/models/Transaction.ts +++ b/packages/ui-components/src/lib/models/Transaction.ts @@ -1,14 +1,14 @@ -import type { Hex } from 'viem'; -import { waitForTransactionReceipt } from '@wagmi/core'; +import type { Hex } from "viem"; +import { waitForTransactionReceipt } from "@wagmi/core"; import { - TransactionStatusMessage, - TransactionStoreErrorMessage, - type AwaitIndexingFn -} from '$lib/types/transaction'; -import type { TransactionArgs } from '$lib/types/transaction'; -import type { Config } from '@wagmi/core'; -import { writable, type Writable } from 'svelte/store'; -import type { ToastLink } from '$lib/types/toast'; + TransactionStatusMessage, + TransactionStoreErrorMessage, + type AwaitIndexingFn, +} from "$lib/types/transaction"; +import type { TransactionArgs } from "$lib/types/transaction"; +import type { Config } from "@wagmi/core"; +import { writable, type Writable } from "svelte/store"; +import type { ToastLink } from "$lib/types/toast"; /** * Represents the state of a transaction. @@ -19,13 +19,13 @@ import type { ToastLink } from '$lib/types/toast'; * @property {Array<{link: string, label: string}>} links - An array of relevant links for the transaction (e.g., explorer link, link to the affected entity). */ export type TransactionStoreState = { - name: string; - status: TransactionStatusMessage; - errorDetails?: TransactionStoreErrorMessage; - links: { - link: string; - label: string; - }[]; + name: string; + status: TransactionStatusMessage; + errorDetails?: TransactionStoreErrorMessage; + links: { + link: string; + label: string; + }[]; }; /** @@ -34,7 +34,7 @@ export type TransactionStoreState = { * @property {Writable} state - A writable store holding the current state of the transaction. */ export type Transaction = { - readonly state: Writable; + readonly state: Writable; }; /** @@ -45,99 +45,99 @@ export type Transaction = { * @implements {Transaction} */ export class TransactionStore implements Transaction { - private name: string; - private config: Config; - private txHash: Hex; - private links: ToastLink[]; - private onSuccess: () => void; - private onError: () => void; - // Optional indexing function called after receipt confirmation. - // TransactionStore doesn't know what this function does - it just calls it. - private awaitIndexingFn?: AwaitIndexingFn; - public readonly state: Writable; + private name: string; + private config: Config; + private txHash: Hex; + private links: ToastLink[]; + private onSuccess: () => void; + private onError: () => void; + // Optional indexing function called after receipt confirmation. + // TransactionStore doesn't know what this function does - it just calls it. + private awaitIndexingFn?: AwaitIndexingFn; + public readonly state: Writable; - /** - * Creates a new TransactionStore instance. - * @param {TransactionArgs & { config: Config }} args - Configuration arguments for the transaction, including the wagmi `Config`. - * @param {() => void} onSuccess - Callback invoked when the transaction successfully completes (including indexing). - * @param {() => void} onError - Callback invoked if the transaction fails at any stage. - */ - constructor( - args: TransactionArgs & { config: Config }, - onSuccess: () => void, - onError: () => void - ) { - this.config = args.config; - this.txHash = args.txHash; - this.name = args.name; - this.links = args.toastLinks; - this.state = writable({ - name: this.name, - status: TransactionStatusMessage.IDLE, - links: this.links - }); - this.awaitIndexingFn = args.awaitIndexingFn; - this.onSuccess = onSuccess; - this.onError = onError; - } + /** + * Creates a new TransactionStore instance. + * @param {TransactionArgs & { config: Config }} args - Configuration arguments for the transaction, including the wagmi `Config`. + * @param {() => void} onSuccess - Callback invoked when the transaction successfully completes (including indexing). + * @param {() => void} onError - Callback invoked if the transaction fails at any stage. + */ + constructor( + args: TransactionArgs & { config: Config }, + onSuccess: () => void, + onError: () => void, + ) { + this.config = args.config; + this.txHash = args.txHash; + this.name = args.name; + this.links = args.toastLinks; + this.state = writable({ + name: this.name, + status: TransactionStatusMessage.IDLE, + links: this.links, + }); + this.awaitIndexingFn = args.awaitIndexingFn; + this.onSuccess = onSuccess; + this.onError = onError; + } - /** - * Updates the internal Svelte store with new state values. - * @param {Partial} partialState - An object containing the state properties to update. - * @private - */ - private updateState(partialState: Partial): void { - this.state.update((currentState) => ({ - ...currentState, - ...partialState - })); - } + /** + * Updates the internal Svelte store with new state values. + * @param {Partial} partialState - An object containing the state properties to update. + * @private + */ + private updateState(partialState: Partial): void { + this.state.update((currentState) => ({ + ...currentState, + ...partialState, + })); + } - /** - * Executes the transaction and begins monitoring its status - * @returns {Promise} - */ - public async execute(): Promise { - this.updateState({ - status: TransactionStatusMessage.PENDING_RECEIPT - }); - await this.waitForTxReceipt(this.txHash); - } + /** + * Executes the transaction and begins monitoring its status + * @returns {Promise} + */ + public async execute(): Promise { + this.updateState({ + status: TransactionStatusMessage.PENDING_RECEIPT, + }); + await this.waitForTxReceipt(this.txHash); + } - /** - * Waits for the transaction receipt to be confirmed on the blockchain. - * If an indexing function is provided, it will be called after receipt confirmation. - * TransactionStore doesn't know what the indexing function does - it just calls it. - * @param {Hex} hash - The transaction hash to monitor - * @returns {Promise} - * @private - */ - private async waitForTxReceipt(hash: Hex): Promise { - try { - await waitForTransactionReceipt(this.config, { hash }); + /** + * Waits for the transaction receipt to be confirmed on the blockchain. + * If an indexing function is provided, it will be called after receipt confirmation. + * TransactionStore doesn't know what the indexing function does - it just calls it. + * @param {Hex} hash - The transaction hash to monitor + * @returns {Promise} + * @private + */ + private async waitForTxReceipt(hash: Hex): Promise { + try { + await waitForTransactionReceipt(this.config, { hash }); - if (this.awaitIndexingFn) { - // Call the indexing function with the context it needs. - // The function handles everything: updating state, calling callbacks, etc. - await this.awaitIndexingFn({ - updateState: this.updateState.bind(this), - onSuccess: this.onSuccess, - onError: this.onError, - links: this.links - }); - } else { - // No indexing needed, mark as success immediately - this.updateState({ - status: TransactionStatusMessage.SUCCESS - }); - return this.onSuccess(); - } - } catch { - this.updateState({ - status: TransactionStatusMessage.ERROR, - errorDetails: TransactionStoreErrorMessage.RECEIPT_FAILED - }); - return this.onError(); - } - } + if (this.awaitIndexingFn) { + // Call the indexing function with the context it needs. + // The function handles everything: updating state, calling callbacks, etc. + await this.awaitIndexingFn({ + updateState: this.updateState.bind(this), + onSuccess: this.onSuccess, + onError: this.onError, + links: this.links, + }); + } else { + // No indexing needed, mark as success immediately + this.updateState({ + status: TransactionStatusMessage.SUCCESS, + }); + return this.onSuccess(); + } + } catch { + this.updateState({ + status: TransactionStatusMessage.ERROR, + errorDetails: TransactionStoreErrorMessage.RECEIPT_FAILED, + }); + return this.onError(); + } + } } diff --git a/packages/ui-components/src/lib/providers/dotrainRegistry/context.ts b/packages/ui-components/src/lib/providers/dotrainRegistry/context.ts index 5aabd76f0a..27889f7991 100644 --- a/packages/ui-components/src/lib/providers/dotrainRegistry/context.ts +++ b/packages/ui-components/src/lib/providers/dotrainRegistry/context.ts @@ -1,63 +1,66 @@ -import { getContext, setContext } from 'svelte'; -import type { DotrainRegistry } from '@rainlanguage/raindex'; -import type { RegistryManager } from '../registry/RegistryManager'; +import { getContext, setContext } from "svelte"; +import type { DotrainRegistry } from "@rainlanguage/raindex"; +import type { RegistryManager } from "../registry/RegistryManager"; export type DotrainRegistryContext = { - registry: DotrainRegistry | null; - error?: string; - manager: RegistryManager; + registry: DotrainRegistry | null; + error?: string; + manager: RegistryManager; }; -const DOTRAIN_REGISTRY_CONTEXT_KEY = 'dotrain-registry-context'; +const DOTRAIN_REGISTRY_CONTEXT_KEY = "dotrain-registry-context"; export const setDotrainRegistryContext = (context: DotrainRegistryContext) => { - setContext(DOTRAIN_REGISTRY_CONTEXT_KEY, context); + setContext(DOTRAIN_REGISTRY_CONTEXT_KEY, context); }; export const getDotrainRegistryContext = (): DotrainRegistryContext => { - const ctx = getContext(DOTRAIN_REGISTRY_CONTEXT_KEY); - if (!ctx) { - throw new Error( - 'Dotrain registry context not found. Did you forget to wrap your app in DotrainRegistryProvider?' - ); - } - return ctx; + const ctx = getContext(DOTRAIN_REGISTRY_CONTEXT_KEY); + if (!ctx) { + throw new Error( + "Dotrain registry context not found. Did you forget to wrap your app in DotrainRegistryProvider?", + ); + } + return ctx; }; if (import.meta.vitest) { - const { describe, it, expect, vi, beforeEach } = import.meta.vitest; + const { describe, it, expect, vi, beforeEach } = import.meta.vitest; - vi.mock('svelte', async (importOriginal) => ({ - ...((await importOriginal()) as object), - getContext: vi.fn() - })); + vi.mock("svelte", async (importOriginal) => ({ + ...((await importOriginal()) as object), + getContext: vi.fn(), + })); - describe('getDotrainRegistryContext', () => { - const mockGetContext = vi.mocked(getContext); + describe("getDotrainRegistryContext", () => { + const mockGetContext = vi.mocked(getContext); - beforeEach(() => { - mockGetContext.mockReset(); - }); + beforeEach(() => { + mockGetContext.mockReset(); + }); - it('should return the context when it exists', () => { - const mockCtx = { registry: null, manager: {} as RegistryManager } as DotrainRegistryContext; + it("should return the context when it exists", () => { + const mockCtx = { + registry: null, + manager: {} as RegistryManager, + } as DotrainRegistryContext; - mockGetContext.mockImplementation((key) => { - if (key === DOTRAIN_REGISTRY_CONTEXT_KEY) return mockCtx; - return undefined; - }); + mockGetContext.mockImplementation((key) => { + if (key === DOTRAIN_REGISTRY_CONTEXT_KEY) return mockCtx; + return undefined; + }); - const result = getDotrainRegistryContext(); - expect(mockGetContext).toHaveBeenCalledWith(DOTRAIN_REGISTRY_CONTEXT_KEY); - expect(result).toEqual(mockCtx); - }); + const result = getDotrainRegistryContext(); + expect(mockGetContext).toHaveBeenCalledWith(DOTRAIN_REGISTRY_CONTEXT_KEY); + expect(result).toEqual(mockCtx); + }); - it('should throw an error when context is not set', () => { - mockGetContext.mockReturnValue(undefined); + it("should throw an error when context is not set", () => { + mockGetContext.mockReturnValue(undefined); - expect(() => getDotrainRegistryContext()).toThrow( - 'Dotrain registry context not found. Did you forget to wrap your app in DotrainRegistryProvider?' - ); - }); - }); + expect(() => getDotrainRegistryContext()).toThrow( + "Dotrain registry context not found. Did you forget to wrap your app in DotrainRegistryProvider?", + ); + }); + }); } diff --git a/packages/ui-components/src/lib/providers/dotrainRegistry/useDotrainRegistry.ts b/packages/ui-components/src/lib/providers/dotrainRegistry/useDotrainRegistry.ts index eb6e9395b2..00e038f382 100644 --- a/packages/ui-components/src/lib/providers/dotrainRegistry/useDotrainRegistry.ts +++ b/packages/ui-components/src/lib/providers/dotrainRegistry/useDotrainRegistry.ts @@ -1,43 +1,46 @@ -import { getDotrainRegistryContext, type DotrainRegistryContext } from './context'; +import { + getDotrainRegistryContext, + type DotrainRegistryContext, +} from "./context"; /** * Hook to access the current Dotrain registry context. */ export function useDotrainRegistry() { - return getDotrainRegistryContext(); + return getDotrainRegistryContext(); } if (import.meta.vitest) { - const { describe, it, expect, vi, beforeEach } = import.meta.vitest; - - vi.mock('./context', () => ({ - getDotrainRegistryContext: vi.fn() - })); - - describe('useDotrainRegistry', () => { - const mockGetContext = vi.mocked(getDotrainRegistryContext); - - beforeEach(() => { - mockGetContext.mockReset(); - }); - - it('should return the registry context', () => { - const mockContext: DotrainRegistryContext = { - registry: null, - manager: { - getCurrentRegistry: vi.fn().mockReturnValue(''), - setRegistry: vi.fn(), - resetToDefault: vi.fn(), - updateUrlWithRegistry: vi.fn(), - isCustomRegistry: vi.fn().mockReturnValue(false) - } as unknown as DotrainRegistryContext['manager'] - }; - mockGetContext.mockReturnValue(mockContext); - - const result = useDotrainRegistry(); - - expect(mockGetContext).toHaveBeenCalled(); - expect(result).toEqual(mockContext); - }); - }); + const { describe, it, expect, vi, beforeEach } = import.meta.vitest; + + vi.mock("./context", () => ({ + getDotrainRegistryContext: vi.fn(), + })); + + describe("useDotrainRegistry", () => { + const mockGetContext = vi.mocked(getDotrainRegistryContext); + + beforeEach(() => { + mockGetContext.mockReset(); + }); + + it("should return the registry context", () => { + const mockContext: DotrainRegistryContext = { + registry: null, + manager: { + getCurrentRegistry: vi.fn().mockReturnValue(""), + setRegistry: vi.fn(), + resetToDefault: vi.fn(), + updateUrlWithRegistry: vi.fn(), + isCustomRegistry: vi.fn().mockReturnValue(false), + } as unknown as DotrainRegistryContext["manager"], + }; + mockGetContext.mockReturnValue(mockContext); + + const result = useDotrainRegistry(); + + expect(mockGetContext).toHaveBeenCalled(); + expect(result).toEqual(mockContext); + }); + }); } diff --git a/packages/ui-components/src/lib/providers/registry/RegistryManager.ts b/packages/ui-components/src/lib/providers/registry/RegistryManager.ts index 0acbe8b312..c2da138613 100644 --- a/packages/ui-components/src/lib/providers/registry/RegistryManager.ts +++ b/packages/ui-components/src/lib/providers/registry/RegistryManager.ts @@ -2,150 +2,155 @@ * Manages registry URL settings, persisting values in localStorage and URL parameters */ export class RegistryManager { - /** The default registry URL to fall back to */ - private defaultRegistry: string; + /** The default registry URL to fall back to */ + private defaultRegistry: string; - /** The currently selected registry URL */ - private currentRegistry: string | null; + /** The currently selected registry URL */ + private currentRegistry: string | null; - /** Key used for localStorage and URL parameters */ - private static STORAGE_KEY = 'registry'; + /** Key used for localStorage and URL parameters */ + private static STORAGE_KEY = "registry"; - /** - * Create a new RegistryManager - * @param defaultRegistry The default registry URL to use. - */ - constructor(defaultRegistry: string) { - this.defaultRegistry = defaultRegistry; - this.currentRegistry = this.loadRegistryFromStorageOrUrl(); - } + /** + * Create a new RegistryManager + * @param defaultRegistry The default registry URL to use. + */ + constructor(defaultRegistry: string) { + this.defaultRegistry = defaultRegistry; + this.currentRegistry = this.loadRegistryFromStorageOrUrl(); + } - /** - * Initialize registry from URL param or local storage - * @returns The registry URL to use - */ - private loadRegistryFromStorageOrUrl(): string { - const urlParam = this.getRegistryParamFromUrl(); - if (urlParam) { - this.setRegistryToLocalStorage(urlParam); - return urlParam; - } - return this.getRegistryFromLocalStorage() ?? this.defaultRegistry; - } + /** + * Initialize registry from URL param or local storage + * @returns The registry URL to use + */ + private loadRegistryFromStorageOrUrl(): string { + const urlParam = this.getRegistryParamFromUrl(); + if (urlParam) { + this.setRegistryToLocalStorage(urlParam); + return urlParam; + } + return this.getRegistryFromLocalStorage() ?? this.defaultRegistry; + } - /** - * Get the registry from the URL param - * @returns The registry value from URL or null if not present - * @throws Error if URL parsing fails - */ - private getRegistryParamFromUrl(): string | null { - try { - return new URL(window.location.href).searchParams.get(RegistryManager.STORAGE_KEY); - } catch (error) { - throw new Error( - 'Failed to get registry parameter: ' + - (error instanceof Error ? error.message : String(error)) - ); - } - } + /** + * Get the registry from the URL param + * @returns The registry value from URL or null if not present + * @throws Error if URL parsing fails + */ + private getRegistryParamFromUrl(): string | null { + try { + return new URL(window.location.href).searchParams.get( + RegistryManager.STORAGE_KEY, + ); + } catch (error) { + throw new Error( + "Failed to get registry parameter: " + + (error instanceof Error ? error.message : String(error)), + ); + } + } - /** - * Save the registry to local storage - * @param registry The registry URL to save - * @throws Error if localStorage is not available - */ - private setRegistryToLocalStorage(registry: string): void { - try { - localStorage.setItem(RegistryManager.STORAGE_KEY, registry); - } catch (error) { - throw new Error( - 'Failed to save to localStorage: ' + - (error instanceof Error ? error.message : String(error)) - ); - } - } + /** + * Save the registry to local storage + * @param registry The registry URL to save + * @throws Error if localStorage is not available + */ + private setRegistryToLocalStorage(registry: string): void { + try { + localStorage.setItem(RegistryManager.STORAGE_KEY, registry); + } catch (error) { + throw new Error( + "Failed to save to localStorage: " + + (error instanceof Error ? error.message : String(error)), + ); + } + } - /** - * Retrieve the registry from local storage - * @returns The stored registry URL or null if not found - * @throws Error if localStorage is not available - */ - private getRegistryFromLocalStorage(): string | null { - try { - return localStorage.getItem(RegistryManager.STORAGE_KEY); - } catch (error) { - throw new Error( - 'Failed to access localStorage: ' + (error instanceof Error ? error.message : String(error)) - ); - } - } + /** + * Retrieve the registry from local storage + * @returns The stored registry URL or null if not found + * @throws Error if localStorage is not available + */ + private getRegistryFromLocalStorage(): string | null { + try { + return localStorage.getItem(RegistryManager.STORAGE_KEY); + } catch (error) { + throw new Error( + "Failed to access localStorage: " + + (error instanceof Error ? error.message : String(error)), + ); + } + } - /** - * Get the currently active registry - * @returns The current registry URL, falling back to default if not set - */ - public getCurrentRegistry(): string { - return this.currentRegistry ?? this.defaultRegistry; - } + /** + * Get the currently active registry + * @returns The current registry URL, falling back to default if not set + */ + public getCurrentRegistry(): string { + return this.currentRegistry ?? this.defaultRegistry; + } - /** - * Set the registry and update both localStorage and URL - * @param registry The new registry URL to set - */ - public setRegistry(registry: string): void { - this.currentRegistry = registry; - this.setRegistryToLocalStorage(registry); - this.updateUrlWithRegistry(); - } + /** + * Set the registry and update both localStorage and URL + * @param registry The new registry URL to set + */ + public setRegistry(registry: string): void { + this.currentRegistry = registry; + this.setRegistryToLocalStorage(registry); + this.updateUrlWithRegistry(); + } - /** - * Reset to the default registry, clearing both localStorage and URL param - * @throws Error if localStorage is not available - */ - public resetToDefault(): void { - this.currentRegistry = this.defaultRegistry; - try { - localStorage.removeItem(RegistryManager.STORAGE_KEY); - } catch (error) { - throw new Error( - 'Failed to clear registry from localStorage: ' + - (error instanceof Error ? error.message : String(error)) - ); - } - this.updateUrlWithRegistry(null); - } + /** + * Reset to the default registry, clearing both localStorage and URL param + * @throws Error if localStorage is not available + */ + public resetToDefault(): void { + this.currentRegistry = this.defaultRegistry; + try { + localStorage.removeItem(RegistryManager.STORAGE_KEY); + } catch (error) { + throw new Error( + "Failed to clear registry from localStorage: " + + (error instanceof Error ? error.message : String(error)), + ); + } + this.updateUrlWithRegistry(null); + } - /** - * Update the URL param to reflect the current or specified registry - * @param value The registry value to set in URL, defaults to current registry - * @throws Error if URL manipulation fails - */ - public updateUrlWithRegistry(value: string | null = this.currentRegistry): void { - try { - const url = new URL(window.location.href); - if (value) { - url.searchParams.set(RegistryManager.STORAGE_KEY, value); - } else { - url.searchParams.delete(RegistryManager.STORAGE_KEY); - } - window.history.pushState({}, '', url.toString()); - } catch (error) { - throw new Error( - 'Failed to update URL parameter: ' + - (error instanceof Error ? error.message : String(error)) - ); - } - } + /** + * Update the URL param to reflect the current or specified registry + * @param value The registry value to set in URL, defaults to current registry + * @throws Error if URL manipulation fails + */ + public updateUrlWithRegistry( + value: string | null = this.currentRegistry, + ): void { + try { + const url = new URL(window.location.href); + if (value) { + url.searchParams.set(RegistryManager.STORAGE_KEY, value); + } else { + url.searchParams.delete(RegistryManager.STORAGE_KEY); + } + window.history.pushState({}, "", url.toString()); + } catch (error) { + throw new Error( + "Failed to update URL parameter: " + + (error instanceof Error ? error.message : String(error)), + ); + } + } - /** - * Check if the current registry is custom (different from the default) - * @returns True if using a non-default registry - */ - public isCustomRegistry(): boolean { - return ( - this.currentRegistry !== undefined && - this.currentRegistry !== null && - this.currentRegistry !== this.defaultRegistry - ); - } + /** + * Check if the current registry is custom (different from the default) + * @returns True if using a non-default registry + */ + public isCustomRegistry(): boolean { + return ( + this.currentRegistry !== undefined && + this.currentRegistry !== null && + this.currentRegistry !== this.defaultRegistry + ); + } } diff --git a/packages/ui-components/src/lib/providers/registry/context.ts b/packages/ui-components/src/lib/providers/registry/context.ts index 053cc4d57a..71280c331b 100644 --- a/packages/ui-components/src/lib/providers/registry/context.ts +++ b/packages/ui-components/src/lib/providers/registry/context.ts @@ -1,61 +1,61 @@ -import { getContext, setContext } from 'svelte'; -import type { RegistryManager } from './RegistryManager'; +import { getContext, setContext } from "svelte"; +import type { RegistryManager } from "./RegistryManager"; -export const REGISTRY_KEY = 'registry_key'; +export const REGISTRY_KEY = "registry_key"; /** * Retrieves the registry manager directly from Svelte's context */ export const getRegistryContext = (): RegistryManager => { - const registry = getContext(REGISTRY_KEY); - if (!registry) { - throw new Error( - 'No registry manager was found in Svelte context. Did you forget to wrap your component with RegistryProvider?' - ); - } - return registry; + const registry = getContext(REGISTRY_KEY); + if (!registry) { + throw new Error( + "No registry manager was found in Svelte context. Did you forget to wrap your component with RegistryProvider?", + ); + } + return registry; }; /** * Sets the registry manager in Svelte's context */ export const setRegistryContext = (registry: RegistryManager) => { - setContext(REGISTRY_KEY, registry); + setContext(REGISTRY_KEY, registry); }; if (import.meta.vitest) { - const { describe, it, expect, vi, beforeEach } = import.meta.vitest; + const { describe, it, expect, vi, beforeEach } = import.meta.vitest; - vi.mock('svelte', async (importOriginal) => ({ - ...((await importOriginal()) as object), - getContext: vi.fn() - })); + vi.mock("svelte", async (importOriginal) => ({ + ...((await importOriginal()) as object), + getContext: vi.fn(), + })); - describe('getRegistryContext', () => { - const mockGetContext = vi.mocked(getContext); + describe("getRegistryContext", () => { + const mockGetContext = vi.mocked(getContext); - beforeEach(() => { - mockGetContext.mockReset(); - }); + beforeEach(() => { + mockGetContext.mockReset(); + }); - it('should return the registry from context when it exists', () => { - const mockRegistry = {} as RegistryManager; + it("should return the registry from context when it exists", () => { + const mockRegistry = {} as RegistryManager; - mockGetContext.mockImplementation((key) => { - if (key === REGISTRY_KEY) return mockRegistry; - return undefined; - }); + mockGetContext.mockImplementation((key) => { + if (key === REGISTRY_KEY) return mockRegistry; + return undefined; + }); - const result = getRegistryContext(); - expect(mockGetContext).toHaveBeenCalledWith(REGISTRY_KEY); - expect(result).toEqual(mockRegistry); - }); + const result = getRegistryContext(); + expect(mockGetContext).toHaveBeenCalledWith(REGISTRY_KEY); + expect(result).toEqual(mockRegistry); + }); - it('should throw an error when registry is not in context', () => { - mockGetContext.mockReturnValue(undefined); + it("should throw an error when registry is not in context", () => { + mockGetContext.mockReturnValue(undefined); - expect(() => getRegistryContext()).toThrow( - 'No registry manager was found in Svelte context. Did you forget to wrap your component with RegistryProvider?' - ); - }); - }); + expect(() => getRegistryContext()).toThrow( + "No registry manager was found in Svelte context. Did you forget to wrap your component with RegistryProvider?", + ); + }); + }); } diff --git a/packages/ui-components/src/lib/providers/registry/useRegistry.ts b/packages/ui-components/src/lib/providers/registry/useRegistry.ts index 1e3988480d..9f4f0c07f4 100644 --- a/packages/ui-components/src/lib/providers/registry/useRegistry.ts +++ b/packages/ui-components/src/lib/providers/registry/useRegistry.ts @@ -1,5 +1,5 @@ -import { getRegistryContext } from './context'; -import type { RegistryManager } from './RegistryManager'; +import { getRegistryContext } from "./context"; +import type { RegistryManager } from "./RegistryManager"; /** * Hook to access registry manager information from context @@ -7,32 +7,32 @@ import type { RegistryManager } from './RegistryManager'; * @returns An object containing the registry manager */ export function useRegistry() { - const registry = getRegistryContext(); - return registry; + const registry = getRegistryContext(); + return registry; } if (import.meta.vitest) { - const { describe, it, expect, vi, beforeEach } = import.meta.vitest; + const { describe, it, expect, vi, beforeEach } = import.meta.vitest; - vi.mock('./context', () => ({ - getRegistryContext: vi.fn() - })); + vi.mock("./context", () => ({ + getRegistryContext: vi.fn(), + })); - describe('useRegistry', () => { - const mockGetRegistryContext = vi.mocked(getRegistryContext); + describe("useRegistry", () => { + const mockGetRegistryContext = vi.mocked(getRegistryContext); - beforeEach(() => { - mockGetRegistryContext.mockReset(); - }); + beforeEach(() => { + mockGetRegistryContext.mockReset(); + }); - it('should return registry', () => { - const mockRegistry = {} as RegistryManager; - mockGetRegistryContext.mockReturnValue(mockRegistry); + it("should return registry", () => { + const mockRegistry = {} as RegistryManager; + mockGetRegistryContext.mockReturnValue(mockRegistry); - const result = useRegistry(); + const result = useRegistry(); - expect(mockGetRegistryContext).toHaveBeenCalled(); - expect(result).toEqual(mockRegistry); - }); - }); + expect(mockGetRegistryContext).toHaveBeenCalled(); + expect(result).toEqual(mockRegistry); + }); + }); } diff --git a/packages/ui-components/src/lib/providers/toasts/context.ts b/packages/ui-components/src/lib/providers/toasts/context.ts index a390ba4487..b78afa9037 100644 --- a/packages/ui-components/src/lib/providers/toasts/context.ts +++ b/packages/ui-components/src/lib/providers/toasts/context.ts @@ -1,20 +1,20 @@ -import { getContext, setContext } from 'svelte'; -import { type Writable } from 'svelte/store'; -import type { ToastProps } from '$lib/types/toast'; +import { getContext, setContext } from "svelte"; +import { type Writable } from "svelte/store"; +import type { ToastProps } from "$lib/types/toast"; -export const TOASTS_KEY = 'rain:ui-components:toasts'; +export const TOASTS_KEY = "rain:ui-components:toasts"; /** * Retrieves the toasts store from Svelte's context */ export function getToastsContext(): Writable { - const toasts = getContext>(TOASTS_KEY); - if (!toasts) { - throw new Error( - 'No toasts context found. Did you forget to wrap your component with ToastProvider?' - ); - } - return toasts; + const toasts = getContext>(TOASTS_KEY); + if (!toasts) { + throw new Error( + "No toasts context found. Did you forget to wrap your component with ToastProvider?", + ); + } + return toasts; } /** @@ -24,5 +24,5 @@ export function getToastsContext(): Writable { * @returns {void} */ export function setToastsContext(toasts: Writable) { - setContext(TOASTS_KEY, toasts); + setContext(TOASTS_KEY, toasts); } diff --git a/packages/ui-components/src/lib/providers/toasts/useToasts.ts b/packages/ui-components/src/lib/providers/toasts/useToasts.ts index ebaf50cdd8..72355b1f29 100644 --- a/packages/ui-components/src/lib/providers/toasts/useToasts.ts +++ b/packages/ui-components/src/lib/providers/toasts/useToasts.ts @@ -1,5 +1,5 @@ -import { getToastsContext } from './context'; -import type { ToastProps } from '$lib/types/toast'; +import { getToastsContext } from "./context"; +import type { ToastProps } from "$lib/types/toast"; /** * Hook for managing toast notifications in the application. @@ -11,59 +11,59 @@ import type { ToastProps } from '$lib/types/toast'; * - removeToast: Function to remove a toast notification by index */ export function useToasts() { - const toasts = getToastsContext(); + const toasts = getToastsContext(); - /** - * Removes a toast notification by its index from the toasts store - * - * @param {number} index - The index of the toast to remove - * @returns {void} - */ - const removeToast = (index: number) => { - toasts.update((toasts) => { - if (index < 0 || index >= toasts.length) { - return toasts; - } - return toasts.filter((_, i) => i !== index); - }); - }; + /** + * Removes a toast notification by its index from the toasts store + * + * @param {number} index - The index of the toast to remove + * @returns {void} + */ + const removeToast = (index: number) => { + toasts.update((toasts) => { + if (index < 0 || index >= toasts.length) { + return toasts; + } + return toasts.filter((_, i) => i !== index); + }); + }; - /** - * Adds a new toast notification to the toasts store - * - * @param {ToastProps} toast - The toast configuration object containing: - * - message: The text to display in the toast - * - type: The type of toast (success, error, warning, info) - * - color: The color theme of the toast (green, red, yellow, blue) - * - links: Optional array of links to display in the toast - * @returns {void} - */ - const addToast = (toast: ToastProps) => { - toasts.update((toasts) => { - const updatedToasts = [...toasts, toast]; - return updatedToasts; - }); - }; + /** + * Adds a new toast notification to the toasts store + * + * @param {ToastProps} toast - The toast configuration object containing: + * - message: The text to display in the toast + * - type: The type of toast (success, error, warning, info) + * - color: The color theme of the toast (green, red, yellow, blue) + * - links: Optional array of links to display in the toast + * @returns {void} + */ + const addToast = (toast: ToastProps) => { + toasts.update((toasts) => { + const updatedToasts = [...toasts, toast]; + return updatedToasts; + }); + }; - /** - * Adds a standardized error toast notification - * - * @param message - The error message to display - * @param detail - The detail of the error - */ - const errToast = (message: string, detail?: string) => { - addToast({ - message, - detail, - type: 'error', - color: 'red' - }); - }; + /** + * Adds a standardized error toast notification + * + * @param message - The error message to display + * @param detail - The detail of the error + */ + const errToast = (message: string, detail?: string) => { + addToast({ + message, + detail, + type: "error", + color: "red", + }); + }; - return { - toasts, - addToast, - removeToast, - errToast - }; + return { + toasts, + addToast, + removeToast, + errToast, + }; } diff --git a/packages/ui-components/src/lib/providers/transactions/TransactionManager.ts b/packages/ui-components/src/lib/providers/transactions/TransactionManager.ts index 57b5b5e1bf..2610ce1f65 100644 --- a/packages/ui-components/src/lib/providers/transactions/TransactionManager.ts +++ b/packages/ui-components/src/lib/providers/transactions/TransactionManager.ts @@ -1,27 +1,27 @@ -import { writable, type Readable, type Writable } from 'svelte/store'; -import type { QueryClient } from '@tanstack/svelte-query'; -import { TransactionStore, type Transaction } from '$lib/models/Transaction'; +import { writable, type Readable, type Writable } from "svelte/store"; +import type { QueryClient } from "@tanstack/svelte-query"; +import { TransactionStore, type Transaction } from "$lib/models/Transaction"; import type { - InternalTransactionArgs, - TransactionArgs, - IndexingContext -} from '$lib/types/transaction'; + InternalTransactionArgs, + TransactionArgs, + IndexingContext, +} from "$lib/types/transaction"; import { - TransactionName, - TransactionStatusMessage, - TransactionStoreErrorMessage -} from '$lib/types/transaction'; -import type { Config } from '@wagmi/core'; -import type { ToastLink, ToastProps } from '$lib/types/toast'; -import { getExplorerLink } from '$lib/services/getExplorerLink'; + TransactionName, + TransactionStatusMessage, + TransactionStoreErrorMessage, +} from "$lib/types/transaction"; +import type { Config } from "@wagmi/core"; +import type { ToastLink, ToastProps } from "$lib/types/toast"; +import { getExplorerLink } from "$lib/services/getExplorerLink"; import { - type RaindexVault, - type RaindexOrder, - RaindexClient, - type Address, - Float, - type WasmEncodedResult -} from '@rainlanguage/raindex'; + type RaindexVault, + type RaindexOrder, + RaindexClient, + type Address, + Float, + type WasmEncodedResult, +} from "@rainlanguage/raindex"; /** * Function type for adding toast notifications to the UI. @@ -31,7 +31,7 @@ import { * @param toast.color - The color theme of the toast. * @param toast.links - Optional array of links to display in the toast. */ -export type AddToastFunction = (toast: Omit) => void; +export type AddToastFunction = (toast: Omit) => void; /** * Creates an indexing function that wraps SDK-based polling logic. @@ -45,56 +45,56 @@ export type AddToastFunction = (toast: Omit) => void; * @returns An indexing function compatible with TransactionStore */ export function createSdkIndexingFn(options: { - call: () => Promise>; - isSuccess: (value: T) => boolean; - buildLinks?: (value: T) => ToastLink[]; + call: () => Promise>; + isSuccess: (value: T) => boolean; + buildLinks?: (value: T) => ToastLink[]; }) { - return async (ctx: IndexingContext): Promise => { - ctx.updateState({ status: TransactionStatusMessage.PENDING_SUBGRAPH }); - - try { - const result = await options.call(); - - if (result.error) { - const errorMsg = result.error.readableMsg?.toLowerCase() ?? ''; - if (errorMsg.includes('timeout')) { - ctx.updateState({ - status: TransactionStatusMessage.ERROR, - errorDetails: TransactionStoreErrorMessage.SUBGRAPH_TIMEOUT_ERROR - }); - } else { - ctx.updateState({ - status: TransactionStatusMessage.ERROR, - errorDetails: TransactionStoreErrorMessage.SUBGRAPH_FAILED - }); - } - return ctx.onError(); - } - - const value = result.value; - if (value && options.isSuccess(value)) { - const extraLinks = options.buildLinks?.(value) ?? []; - if (extraLinks.length > 0) { - ctx.updateState({ links: [...extraLinks, ...ctx.links] }); - } - ctx.updateState({ status: TransactionStatusMessage.SUCCESS }); - return ctx.onSuccess(); - } - - // No valid data after polling - ctx.updateState({ - status: TransactionStatusMessage.ERROR, - errorDetails: TransactionStoreErrorMessage.SUBGRAPH_FAILED - }); - return ctx.onError(); - } catch { - ctx.updateState({ - status: TransactionStatusMessage.ERROR, - errorDetails: TransactionStoreErrorMessage.SUBGRAPH_FAILED - }); - return ctx.onError(); - } - }; + return async (ctx: IndexingContext): Promise => { + ctx.updateState({ status: TransactionStatusMessage.PENDING_SUBGRAPH }); + + try { + const result = await options.call(); + + if (result.error) { + const errorMsg = result.error.readableMsg?.toLowerCase() ?? ""; + if (errorMsg.includes("timeout")) { + ctx.updateState({ + status: TransactionStatusMessage.ERROR, + errorDetails: TransactionStoreErrorMessage.SUBGRAPH_TIMEOUT_ERROR, + }); + } else { + ctx.updateState({ + status: TransactionStatusMessage.ERROR, + errorDetails: TransactionStoreErrorMessage.SUBGRAPH_FAILED, + }); + } + return ctx.onError(); + } + + const value = result.value; + if (value && options.isSuccess(value)) { + const extraLinks = options.buildLinks?.(value) ?? []; + if (extraLinks.length > 0) { + ctx.updateState({ links: [...extraLinks, ...ctx.links] }); + } + ctx.updateState({ status: TransactionStatusMessage.SUCCESS }); + return ctx.onSuccess(); + } + + // No valid data after polling + ctx.updateState({ + status: TransactionStatusMessage.ERROR, + errorDetails: TransactionStoreErrorMessage.SUBGRAPH_FAILED, + }); + return ctx.onError(); + } catch { + ctx.updateState({ + status: TransactionStatusMessage.ERROR, + errorDetails: TransactionStoreErrorMessage.SUBGRAPH_FAILED, + }); + return ctx.onError(); + } + }; } /** @@ -103,523 +103,550 @@ export function createSdkIndexingFn(options: { * Provides functionality for creating, tracking, and managing blockchain transactions. */ export class TransactionManager { - /** Writable store tracking all active transactions. */ - private transactions: Writable; - /** Query client for cache invalidation after successful transactions. */ - private queryClient: QueryClient; - /** Function to display toast notifications in the UI. */ - private addToast: AddToastFunction; - /** Wagmi configuration for blockchain interactions. */ - private wagmiConfig: Config; - - /** - * Initializes a new TransactionManager instance. - * @param queryClient - Query client for cache invalidation. - * @param addToast - Function to display toast notifications. - * @param wagmiConfig - Wagmi configuration for blockchain interactions. - */ - constructor(queryClient: QueryClient, addToast: AddToastFunction, wagmiConfig: Config) { - this.queryClient = queryClient; - this.addToast = addToast; - this.wagmiConfig = wagmiConfig; - this.transactions = writable([]); - } - - /** - * Creates and initializes a new transaction for removing an order from the raindex. - * @param args - Configuration for the remove order transaction. - * @param args.txHash - Hash of the transaction to track. - * @param args.chainId - Chain ID where the transaction is being executed. - * @param args.queryKey - The hash of the order to be removed (used for query invalidation and UI links). - * @param args.entity - The `SgOrder` entity associated with this transaction. - * @returns A new Transaction instance configured for order removal. - * @example - * const tx = await manager.createRemoveOrderTransaction({ - * txHash: '0x123...', - * chainId: 1, - * queryKey: '0x456...', // Order hash - * entity: sgOrderInstance - * }); - */ - public async createRemoveOrderTransaction( - args: InternalTransactionArgs & { entity: RaindexOrder; raindexClient: RaindexClient } - ): Promise { - const name = TransactionName.REMOVAL; - const errorMessage = 'Order removal failed.'; - const successMessage = 'Order removed successfully.'; - const { - chainId, - entity: { raindex }, - queryKey, - txHash, - raindexClient - } = args; - - const explorerLink = await getExplorerLink(txHash, chainId, 'tx'); - const toastLinks: ToastLink[] = [ - { - link: explorerLink, - label: 'View on explorer' - } - ]; - - const awaitIndexingFn = createSdkIndexingFn({ - call: () => raindexClient.getRemoveOrdersForTransaction(chainId, raindex, txHash), - isSuccess: (orders) => Array.isArray(orders) && orders.length > 0 - }); - - return this.createTransaction({ - ...args, - name, - errorMessage, - successMessage, - queryKey, - toastLinks, - awaitIndexingFn - }); - } - - /** - * Creates and initializes a new transaction for withdrawing funds from a vault. - * @param args - Configuration for the withdrawal transaction. - * @param args.txHash - Hash of the transaction to track. - * @param args.chainId - Chain ID where the transaction is being executed. - * @param args.queryKey - The ID of the vault from which funds are withdrawn (used for query invalidation and UI links). - * @param args.entity - The `SgVault` entity associated with this transaction. - * @returns A new Transaction instance configured for withdrawal. - * @example - * const tx = await manager.createWithdrawTransaction({ - * txHash: '0x123...', - * chainId: 1, - * queryKey: '0x789...', // Vault ID - * entity: sgVaultInstance - * }); - */ - public async createWithdrawTransaction( - args: InternalTransactionArgs & { entity: RaindexVault; raindexClient: RaindexClient } - ): Promise { - const name = TransactionName.WITHDRAWAL; - const errorMessage = 'Withdrawal failed.'; - const successMessage = 'Withdrawal successful.'; - const { - chainId, - entity: { raindex }, - queryKey, - txHash, - raindexClient - } = args; - - const explorerLink = await getExplorerLink(txHash, chainId, 'tx'); - const toastLinks: ToastLink[] = [ - { - link: `/vaults/${chainId}-${raindex}-${queryKey}`, - label: 'View vault' - }, - { - link: explorerLink, - label: 'View on explorer' - } - ]; - - const awaitIndexingFn = createSdkIndexingFn({ - call: () => raindexClient.getTransaction(chainId, raindex, txHash), - isSuccess: (tx) => !!tx - }); - - return this.createTransaction({ - ...args, - name, - errorMessage, - successMessage, - queryKey, - toastLinks, - awaitIndexingFn - }); - } - - /** - * Creates a multicall withdrawal transaction. - * - * Precondition: all provided vaults must share the same raindex. - * This is enforced upstream in handleVaultsWithdrawAll.ts: - * if (vaults.some(v => v.raindex !== vaults[0].raindex)) { … } - * - * @param args.chainId the target chain ID - * @param args.vaults list of RaindexVault instances (must share a raindex) - * @param args.txHash the transaction hash to wrap - * @param args.queryKey cache key for invalidation - * @param args.raindexClient Raindex API client * @example - * const tx = await manager.createVaultsWithdrawAllTransaction({ - * txHash: '0x123...', - * chainId: 1, - * queryKey: 'QKEY_VAULTS', - * vaults: [vault1, vault2, vault3], - * raindexClient: clientInstance - * }); - */ - public async createVaultsWithdrawAllTransaction( - args: InternalTransactionArgs & { vaults: RaindexVault[]; raindexClient: RaindexClient } - ): Promise { - const name = TransactionName.WITHDRAWAL_MULTIPLE; - const errorMessage = 'Withdrawal failed.'; - const successMessage = 'Withdrawal successful.'; - const { chainId, vaults, txHash, queryKey, raindexClient } = args; - - if (vaults.length === 0) { - throw new Error('At least one vault is required for withdrawal'); - } - // All vaults must share the same raindex for multicall transactions - // It should be validated before calling this method - const raindex = vaults[0].raindex; - const explorerLink = await getExplorerLink(txHash, chainId, 'tx'); - const toastLinks: ToastLink[] = [ - { - link: '/vaults/', - label: 'View all vaults' - }, - { - link: explorerLink, - label: 'View on explorer' - } - ]; - - const awaitIndexingFn = createSdkIndexingFn({ - call: () => raindexClient.getTransaction(chainId, raindex, txHash), - isSuccess: (tx) => !!tx - }); - - return this.createTransaction({ - ...args, - name, - errorMessage, - successMessage, - toastLinks, - queryKey, - awaitIndexingFn - }); - } - - /** - * Creates and initializes a new transaction for approving token spend. - * @param args - Configuration for the approval transaction. - * @param args.txHash - Hash of the transaction to track. - * @param args.chainId - Chain ID where the transaction is being executed. - * @param args.queryKey - The ID of the vault or context for which approval is made (used for query invalidation and UI links). - * @param args.tokenSymbol - The symbol of the token being approved. - * @param args.entity - The `SgVault` entity associated with this transaction. (Optional, used for approvals to pre-existing vaults). - * @returns A new Transaction instance configured for token approval. - * @example - * const tx = await manager.createApprovalTransaction({ - * txHash: '0xabc...', - * chainId: 1, - * queryKey: '0x789...', // Vault ID - * entity: sgVaultInstance - * }); - */ - public async createApprovalTransaction( - args: InternalTransactionArgs & { entity?: RaindexVault } - ): Promise { - const { entity, queryKey, chainId } = args; - const tokenSymbol = entity?.token.symbol || 'token'; - const name = `Approving ${tokenSymbol} spend`; - const errorMessage = 'Approval failed.'; - const successMessage = 'Approval successful.'; - - const explorerLink = await getExplorerLink(args.txHash, args.chainId, 'tx'); - let toastLinks: ToastLink[] = [ - { - link: explorerLink, - label: 'View on explorer' - } - ]; - - if (entity) { - toastLinks = [ - { - link: `/vaults/${chainId}-${entity.raindex}-${queryKey}`, - label: 'View vault' - }, - ...toastLinks - ]; - } - - return this.createTransaction({ - ...args, - name, - errorMessage, - successMessage, - toastLinks - }); - } - - /** - * Creates and initializes a new transaction for publishing metadata to the metaboard. - * @param args - Configuration for the metadata transaction. - * @param args.txHash - Hash of the metadata transaction. - * @param args.chainId - Chain ID where the transaction is executed. - * @param args.queryKey - Identifier used for query invalidation, typically the order hash. - */ - public async createMetaTransaction(args: InternalTransactionArgs): Promise { - const name = 'Publishing metadata'; - const errorMessage = 'Metadata publication failed.'; - const successMessage = 'Metadata published.'; - - const explorerLink = await getExplorerLink(args.txHash, args.chainId, 'tx'); - const toastLinks: ToastLink[] = [ - { - link: explorerLink, - label: 'View on explorer' - } - ]; - - return this.createTransaction({ - ...args, - name, - errorMessage, - successMessage, - toastLinks - }); - } - - /** - * Creates and initializes a new transaction for depositing funds into a vault. - * @param args - Configuration for the deposit transaction. - * @param args.txHash - Hash of the transaction to track. - * @param args.chainId - Chain ID where the transaction is being executed. - * @param args.queryKey - The ID of the vault into which funds are deposited (used for query invalidation and UI links). - * @param args.entity - The `SgVault` entity associated with this transaction. - * @param args.amount - The amount of tokens being deposited. - * @returns A new Transaction instance configured for deposit. - * @example - * const tx = await manager.createDepositTransaction({ - * txHash: '0xdef...', - * chainId: 1, - * queryKey: '0x789...', // Vault ID - * entity: sgVaultInstance, - * amount: 1000n - * }); - */ - public async createDepositTransaction( - args: InternalTransactionArgs & { - amount: Float; - entity: RaindexVault; - raindexClient: RaindexClient; - } - ): Promise { - const tokenSymbol = args.entity.token.symbol; - const name = `Depositing ${args.amount.format().value} ${tokenSymbol}`; - const errorMessage = 'Deposit failed.'; - const successMessage = 'Deposit successful.'; - const { - chainId, - entity: { raindex }, - txHash, - queryKey, - raindexClient - } = args; - - const explorerLink = await getExplorerLink(txHash, chainId, 'tx'); - const toastLinks: ToastLink[] = [ - { - link: `/vaults/${chainId}-${raindex}-${queryKey}`, - label: 'View vault' - }, - { - link: explorerLink, - label: 'View on explorer' - } - ]; - - const awaitIndexingFn = createSdkIndexingFn({ - call: () => raindexClient.getTransaction(chainId, raindex, txHash), - isSuccess: (tx) => !!tx - }); - - return this.createTransaction({ - ...args, - name, - errorMessage, - successMessage, - queryKey, - toastLinks, - awaitIndexingFn - }); - } - - /** - * Creates and initializes a new transaction for deploying an order. - * @param args - Configuration for the deployment transaction. - * @param args.txHash - Hash of the transaction to track. - * @param args.chainId - Chain ID where the transaction is being executed. - * @param args.queryKey - The ID of the vault into which funds are deposited (used for query invalidation and UI links). - * @returns A new Transaction instance configured for deposit. - * @example - * const tx = await manager.createAddOrderTransaction({ - * txHash: '0xdeploytxhash', - * chainId: 1, - * queryKey: '0x789...', // Vault ID - * }); - */ - - public async createAddOrderTransaction( - args: InternalTransactionArgs & { raindex: Address; raindexClient: RaindexClient } - ): Promise { - const { queryKey, txHash, chainId, raindex, raindexClient } = args; - const name = 'Deploying order'; - const errorMessage = 'Deployment failed.'; - const successMessage = 'Order deployed successfully.'; - - const explorerLink = await getExplorerLink(txHash, chainId, 'tx'); - const toastLinks: ToastLink[] = [ - { - link: explorerLink, - label: 'View on explorer' - } - ]; - - // SDK-based indexing - the SDK's getAddOrdersForTransaction handles - // local-DB-first polling followed by subgraph fallback internally - const awaitIndexingFn = createSdkIndexingFn({ - call: () => raindexClient.getAddOrdersForTransaction(chainId, raindex, txHash), - isSuccess: (orders) => Array.isArray(orders) && orders.length > 0, - buildLinks: (orders) => { - if (!Array.isArray(orders) || orders.length === 0) return []; - const firstOrder = orders[0]; - if (!firstOrder?.orderHash) return []; - return [ - { - link: `/orders/${chainId}-${raindex}-${firstOrder.orderHash}`, - label: 'View order' - } - ]; - } - }); - - return this.createTransaction({ - ...args, - name, - errorMessage, - successMessage, - queryKey, - toastLinks, - awaitIndexingFn - }); - } - - /** - * Creates and initializes a new transaction for taking orders. - * @param args - Configuration for the take order transaction. - * @param args.txHash - Hash of the transaction to track. - * @param args.chainId - Chain ID where the transaction is being executed. - * @param args.queryKey - The hash of the order being taken (used for query invalidation). - * @param args.entity - The `RaindexOrder` entity associated with this transaction. - * @returns A new Transaction instance configured for taking orders. - * @example - * const tx = await manager.createTakeOrderTransaction({ - * txHash: '0x123...', - * chainId: 1, - * queryKey: '0x456...', // Order hash - * entity: raindexOrderInstance, - * raindexClient: clientInstance - * }); - */ - public async createTakeOrderTransaction( - args: InternalTransactionArgs & { entity: RaindexOrder; raindexClient: RaindexClient } - ): Promise { - const name = TransactionName.TAKE_ORDER; - const errorMessage = 'Take order failed.'; - const successMessage = 'Order taken successfully.'; - const { - chainId, - entity: { raindex }, - queryKey, - txHash, - raindexClient - } = args; - - const explorerLink = await getExplorerLink(txHash, chainId, 'tx'); - const toastLinks: ToastLink[] = [ - { - link: explorerLink, - label: 'View on explorer' - } - ]; - const awaitIndexingFn = createSdkIndexingFn({ - call: () => raindexClient.getTransaction(chainId, raindex, txHash), - isSuccess: (tx) => !!tx - }); - - return this.createTransaction({ - ...args, - name, - errorMessage, - successMessage, - queryKey, - toastLinks, - awaitIndexingFn - }); - } - - /** - * Creates, initializes, and executes a new transaction instance. - * @param args - Configuration for the transaction. - * @param args.name - Name or title of the transaction. - * @param args.errorMessage - Message to display on transaction failure. - * @param args.successMessage - Message to display on transaction success. - * @param args.queryKey - Key used for query invalidation. - * @param args.toastLinks - Array of links to display in toast notifications. - * @param args.awaitIndexingFn - Optional function to await transaction indexing. - * @returns A new Transaction instance that has been initialized and started. - * @private - */ - private async createTransaction(args: TransactionArgs): Promise { - const createTransactionArgs: TransactionArgs & { config: Config } = { - ...args, - config: this.wagmiConfig - }; - - const onSuccess = () => { - if (args.queryKey) { - this.queryClient.invalidateQueries({ queryKey: [args.queryKey] }); - } - }; - - const onError = () => { - this.addToast({ - message: args.errorMessage, - type: 'error', - color: 'red', - links: args.toastLinks - }); - }; - - const transactionInstance = new TransactionStore(createTransactionArgs, onSuccess, onError); - - this.transactions.update((currentTransactions) => [ - ...currentTransactions, - transactionInstance - ]); - await transactionInstance.execute(); - return transactionInstance; - } - - /** - * Retrieves the store containing all active transactions. - * @returns A readable store containing all active Transaction instances. - * @example - * const transactionsStore = manager.getTransactions(); - * transactionsStore.subscribe(transactions => console.log(transactions)); - */ - public getTransactions(): Readable { - return this.transactions; - } - - /** - * Removes all transactions from the store, resetting the transaction tracking state. - * @example - * manager.clearTransactions(); // Clear all tracked transactions - */ - public clearTransactions(): void { - this.transactions.set([]); - } + /** Writable store tracking all active transactions. */ + private transactions: Writable; + /** Query client for cache invalidation after successful transactions. */ + private queryClient: QueryClient; + /** Function to display toast notifications in the UI. */ + private addToast: AddToastFunction; + /** Wagmi configuration for blockchain interactions. */ + private wagmiConfig: Config; + + /** + * Initializes a new TransactionManager instance. + * @param queryClient - Query client for cache invalidation. + * @param addToast - Function to display toast notifications. + * @param wagmiConfig - Wagmi configuration for blockchain interactions. + */ + constructor( + queryClient: QueryClient, + addToast: AddToastFunction, + wagmiConfig: Config, + ) { + this.queryClient = queryClient; + this.addToast = addToast; + this.wagmiConfig = wagmiConfig; + this.transactions = writable([]); + } + + /** + * Creates and initializes a new transaction for removing an order from the raindex. + * @param args - Configuration for the remove order transaction. + * @param args.txHash - Hash of the transaction to track. + * @param args.chainId - Chain ID where the transaction is being executed. + * @param args.queryKey - The hash of the order to be removed (used for query invalidation and UI links). + * @param args.entity - The `SgOrder` entity associated with this transaction. + * @returns A new Transaction instance configured for order removal. + * @example + * const tx = await manager.createRemoveOrderTransaction({ + * txHash: '0x123...', + * chainId: 1, + * queryKey: '0x456...', // Order hash + * entity: sgOrderInstance + * }); + */ + public async createRemoveOrderTransaction( + args: InternalTransactionArgs & { + entity: RaindexOrder; + raindexClient: RaindexClient; + }, + ): Promise { + const name = TransactionName.REMOVAL; + const errorMessage = "Order removal failed."; + const successMessage = "Order removed successfully."; + const { + chainId, + entity: { raindex }, + queryKey, + txHash, + raindexClient, + } = args; + + const explorerLink = await getExplorerLink(txHash, chainId, "tx"); + const toastLinks: ToastLink[] = [ + { + link: explorerLink, + label: "View on explorer", + }, + ]; + + const awaitIndexingFn = createSdkIndexingFn({ + call: () => + raindexClient.getRemoveOrdersForTransaction(chainId, raindex, txHash), + isSuccess: (orders) => Array.isArray(orders) && orders.length > 0, + }); + + return this.createTransaction({ + ...args, + name, + errorMessage, + successMessage, + queryKey, + toastLinks, + awaitIndexingFn, + }); + } + + /** + * Creates and initializes a new transaction for withdrawing funds from a vault. + * @param args - Configuration for the withdrawal transaction. + * @param args.txHash - Hash of the transaction to track. + * @param args.chainId - Chain ID where the transaction is being executed. + * @param args.queryKey - The ID of the vault from which funds are withdrawn (used for query invalidation and UI links). + * @param args.entity - The `SgVault` entity associated with this transaction. + * @returns A new Transaction instance configured for withdrawal. + * @example + * const tx = await manager.createWithdrawTransaction({ + * txHash: '0x123...', + * chainId: 1, + * queryKey: '0x789...', // Vault ID + * entity: sgVaultInstance + * }); + */ + public async createWithdrawTransaction( + args: InternalTransactionArgs & { + entity: RaindexVault; + raindexClient: RaindexClient; + }, + ): Promise { + const name = TransactionName.WITHDRAWAL; + const errorMessage = "Withdrawal failed."; + const successMessage = "Withdrawal successful."; + const { + chainId, + entity: { raindex }, + queryKey, + txHash, + raindexClient, + } = args; + + const explorerLink = await getExplorerLink(txHash, chainId, "tx"); + const toastLinks: ToastLink[] = [ + { + link: `/vaults/${chainId}-${raindex}-${queryKey}`, + label: "View vault", + }, + { + link: explorerLink, + label: "View on explorer", + }, + ]; + + const awaitIndexingFn = createSdkIndexingFn({ + call: () => raindexClient.getTransaction(chainId, raindex, txHash), + isSuccess: (tx) => !!tx, + }); + + return this.createTransaction({ + ...args, + name, + errorMessage, + successMessage, + queryKey, + toastLinks, + awaitIndexingFn, + }); + } + + /** + * Creates a multicall withdrawal transaction. + * + * Precondition: all provided vaults must share the same raindex. + * This is enforced upstream in handleVaultsWithdrawAll.ts: + * if (vaults.some(v => v.raindex !== vaults[0].raindex)) { … } + * + * @param args.chainId the target chain ID + * @param args.vaults list of RaindexVault instances (must share a raindex) + * @param args.txHash the transaction hash to wrap + * @param args.queryKey cache key for invalidation + * @param args.raindexClient Raindex API client * @example + * const tx = await manager.createVaultsWithdrawAllTransaction({ + * txHash: '0x123...', + * chainId: 1, + * queryKey: 'QKEY_VAULTS', + * vaults: [vault1, vault2, vault3], + * raindexClient: clientInstance + * }); + */ + public async createVaultsWithdrawAllTransaction( + args: InternalTransactionArgs & { + vaults: RaindexVault[]; + raindexClient: RaindexClient; + }, + ): Promise { + const name = TransactionName.WITHDRAWAL_MULTIPLE; + const errorMessage = "Withdrawal failed."; + const successMessage = "Withdrawal successful."; + const { chainId, vaults, txHash, queryKey, raindexClient } = args; + + if (vaults.length === 0) { + throw new Error("At least one vault is required for withdrawal"); + } + // All vaults must share the same raindex for multicall transactions + // It should be validated before calling this method + const raindex = vaults[0].raindex; + const explorerLink = await getExplorerLink(txHash, chainId, "tx"); + const toastLinks: ToastLink[] = [ + { + link: "/vaults/", + label: "View all vaults", + }, + { + link: explorerLink, + label: "View on explorer", + }, + ]; + + const awaitIndexingFn = createSdkIndexingFn({ + call: () => raindexClient.getTransaction(chainId, raindex, txHash), + isSuccess: (tx) => !!tx, + }); + + return this.createTransaction({ + ...args, + name, + errorMessage, + successMessage, + toastLinks, + queryKey, + awaitIndexingFn, + }); + } + + /** + * Creates and initializes a new transaction for approving token spend. + * @param args - Configuration for the approval transaction. + * @param args.txHash - Hash of the transaction to track. + * @param args.chainId - Chain ID where the transaction is being executed. + * @param args.queryKey - The ID of the vault or context for which approval is made (used for query invalidation and UI links). + * @param args.tokenSymbol - The symbol of the token being approved. + * @param args.entity - The `SgVault` entity associated with this transaction. (Optional, used for approvals to pre-existing vaults). + * @returns A new Transaction instance configured for token approval. + * @example + * const tx = await manager.createApprovalTransaction({ + * txHash: '0xabc...', + * chainId: 1, + * queryKey: '0x789...', // Vault ID + * entity: sgVaultInstance + * }); + */ + public async createApprovalTransaction( + args: InternalTransactionArgs & { entity?: RaindexVault }, + ): Promise { + const { entity, queryKey, chainId } = args; + const tokenSymbol = entity?.token.symbol || "token"; + const name = `Approving ${tokenSymbol} spend`; + const errorMessage = "Approval failed."; + const successMessage = "Approval successful."; + + const explorerLink = await getExplorerLink(args.txHash, args.chainId, "tx"); + let toastLinks: ToastLink[] = [ + { + link: explorerLink, + label: "View on explorer", + }, + ]; + + if (entity) { + toastLinks = [ + { + link: `/vaults/${chainId}-${entity.raindex}-${queryKey}`, + label: "View vault", + }, + ...toastLinks, + ]; + } + + return this.createTransaction({ + ...args, + name, + errorMessage, + successMessage, + toastLinks, + }); + } + + /** + * Creates and initializes a new transaction for publishing metadata to the metaboard. + * @param args - Configuration for the metadata transaction. + * @param args.txHash - Hash of the metadata transaction. + * @param args.chainId - Chain ID where the transaction is executed. + * @param args.queryKey - Identifier used for query invalidation, typically the order hash. + */ + public async createMetaTransaction( + args: InternalTransactionArgs, + ): Promise { + const name = "Publishing metadata"; + const errorMessage = "Metadata publication failed."; + const successMessage = "Metadata published."; + + const explorerLink = await getExplorerLink(args.txHash, args.chainId, "tx"); + const toastLinks: ToastLink[] = [ + { + link: explorerLink, + label: "View on explorer", + }, + ]; + + return this.createTransaction({ + ...args, + name, + errorMessage, + successMessage, + toastLinks, + }); + } + + /** + * Creates and initializes a new transaction for depositing funds into a vault. + * @param args - Configuration for the deposit transaction. + * @param args.txHash - Hash of the transaction to track. + * @param args.chainId - Chain ID where the transaction is being executed. + * @param args.queryKey - The ID of the vault into which funds are deposited (used for query invalidation and UI links). + * @param args.entity - The `SgVault` entity associated with this transaction. + * @param args.amount - The amount of tokens being deposited. + * @returns A new Transaction instance configured for deposit. + * @example + * const tx = await manager.createDepositTransaction({ + * txHash: '0xdef...', + * chainId: 1, + * queryKey: '0x789...', // Vault ID + * entity: sgVaultInstance, + * amount: 1000n + * }); + */ + public async createDepositTransaction( + args: InternalTransactionArgs & { + amount: Float; + entity: RaindexVault; + raindexClient: RaindexClient; + }, + ): Promise { + const tokenSymbol = args.entity.token.symbol; + const name = `Depositing ${args.amount.format().value} ${tokenSymbol}`; + const errorMessage = "Deposit failed."; + const successMessage = "Deposit successful."; + const { + chainId, + entity: { raindex }, + txHash, + queryKey, + raindexClient, + } = args; + + const explorerLink = await getExplorerLink(txHash, chainId, "tx"); + const toastLinks: ToastLink[] = [ + { + link: `/vaults/${chainId}-${raindex}-${queryKey}`, + label: "View vault", + }, + { + link: explorerLink, + label: "View on explorer", + }, + ]; + + const awaitIndexingFn = createSdkIndexingFn({ + call: () => raindexClient.getTransaction(chainId, raindex, txHash), + isSuccess: (tx) => !!tx, + }); + + return this.createTransaction({ + ...args, + name, + errorMessage, + successMessage, + queryKey, + toastLinks, + awaitIndexingFn, + }); + } + + /** + * Creates and initializes a new transaction for deploying an order. + * @param args - Configuration for the deployment transaction. + * @param args.txHash - Hash of the transaction to track. + * @param args.chainId - Chain ID where the transaction is being executed. + * @param args.queryKey - The ID of the vault into which funds are deposited (used for query invalidation and UI links). + * @returns A new Transaction instance configured for deposit. + * @example + * const tx = await manager.createAddOrderTransaction({ + * txHash: '0xdeploytxhash', + * chainId: 1, + * queryKey: '0x789...', // Vault ID + * }); + */ + + public async createAddOrderTransaction( + args: InternalTransactionArgs & { + raindex: Address; + raindexClient: RaindexClient; + }, + ): Promise { + const { queryKey, txHash, chainId, raindex, raindexClient } = args; + const name = "Deploying order"; + const errorMessage = "Deployment failed."; + const successMessage = "Order deployed successfully."; + + const explorerLink = await getExplorerLink(txHash, chainId, "tx"); + const toastLinks: ToastLink[] = [ + { + link: explorerLink, + label: "View on explorer", + }, + ]; + + // SDK-based indexing - the SDK's getAddOrdersForTransaction handles + // local-DB-first polling followed by subgraph fallback internally + const awaitIndexingFn = createSdkIndexingFn({ + call: () => + raindexClient.getAddOrdersForTransaction(chainId, raindex, txHash), + isSuccess: (orders) => Array.isArray(orders) && orders.length > 0, + buildLinks: (orders) => { + if (!Array.isArray(orders) || orders.length === 0) return []; + const firstOrder = orders[0]; + if (!firstOrder?.orderHash) return []; + return [ + { + link: `/orders/${chainId}-${raindex}-${firstOrder.orderHash}`, + label: "View order", + }, + ]; + }, + }); + + return this.createTransaction({ + ...args, + name, + errorMessage, + successMessage, + queryKey, + toastLinks, + awaitIndexingFn, + }); + } + + /** + * Creates and initializes a new transaction for taking orders. + * @param args - Configuration for the take order transaction. + * @param args.txHash - Hash of the transaction to track. + * @param args.chainId - Chain ID where the transaction is being executed. + * @param args.queryKey - The hash of the order being taken (used for query invalidation). + * @param args.entity - The `RaindexOrder` entity associated with this transaction. + * @returns A new Transaction instance configured for taking orders. + * @example + * const tx = await manager.createTakeOrderTransaction({ + * txHash: '0x123...', + * chainId: 1, + * queryKey: '0x456...', // Order hash + * entity: raindexOrderInstance, + * raindexClient: clientInstance + * }); + */ + public async createTakeOrderTransaction( + args: InternalTransactionArgs & { + entity: RaindexOrder; + raindexClient: RaindexClient; + }, + ): Promise { + const name = TransactionName.TAKE_ORDER; + const errorMessage = "Take order failed."; + const successMessage = "Order taken successfully."; + const { + chainId, + entity: { raindex }, + queryKey, + txHash, + raindexClient, + } = args; + + const explorerLink = await getExplorerLink(txHash, chainId, "tx"); + const toastLinks: ToastLink[] = [ + { + link: explorerLink, + label: "View on explorer", + }, + ]; + const awaitIndexingFn = createSdkIndexingFn({ + call: () => raindexClient.getTransaction(chainId, raindex, txHash), + isSuccess: (tx) => !!tx, + }); + + return this.createTransaction({ + ...args, + name, + errorMessage, + successMessage, + queryKey, + toastLinks, + awaitIndexingFn, + }); + } + + /** + * Creates, initializes, and executes a new transaction instance. + * @param args - Configuration for the transaction. + * @param args.name - Name or title of the transaction. + * @param args.errorMessage - Message to display on transaction failure. + * @param args.successMessage - Message to display on transaction success. + * @param args.queryKey - Key used for query invalidation. + * @param args.toastLinks - Array of links to display in toast notifications. + * @param args.awaitIndexingFn - Optional function to await transaction indexing. + * @returns A new Transaction instance that has been initialized and started. + * @private + */ + private async createTransaction(args: TransactionArgs): Promise { + const createTransactionArgs: TransactionArgs & { config: Config } = { + ...args, + config: this.wagmiConfig, + }; + + const onSuccess = () => { + if (args.queryKey) { + this.queryClient.invalidateQueries({ queryKey: [args.queryKey] }); + } + }; + + const onError = () => { + this.addToast({ + message: args.errorMessage, + type: "error", + color: "red", + links: args.toastLinks, + }); + }; + + const transactionInstance = new TransactionStore( + createTransactionArgs, + onSuccess, + onError, + ); + + this.transactions.update((currentTransactions) => [ + ...currentTransactions, + transactionInstance, + ]); + await transactionInstance.execute(); + return transactionInstance; + } + + /** + * Retrieves the store containing all active transactions. + * @returns A readable store containing all active Transaction instances. + * @example + * const transactionsStore = manager.getTransactions(); + * transactionsStore.subscribe(transactions => console.log(transactions)); + */ + public getTransactions(): Readable { + return this.transactions; + } + + /** + * Removes all transactions from the store, resetting the transaction tracking state. + * @example + * manager.clearTransactions(); // Clear all tracked transactions + */ + public clearTransactions(): void { + this.transactions.set([]); + } } diff --git a/packages/ui-components/src/lib/providers/transactions/context.ts b/packages/ui-components/src/lib/providers/transactions/context.ts index 3c8d8cb8f5..381fffaa73 100644 --- a/packages/ui-components/src/lib/providers/transactions/context.ts +++ b/packages/ui-components/src/lib/providers/transactions/context.ts @@ -1,10 +1,11 @@ -import { getContext, setContext } from 'svelte'; -import { TransactionManager } from './TransactionManager'; +import { getContext, setContext } from "svelte"; +import { TransactionManager } from "./TransactionManager"; /** * The context key used to store and retrieve the TransactionManager instance */ -export const TRANSACTION_MANAGER_CONTEXT_KEY = 'rain:ui-components:transactionManager'; +export const TRANSACTION_MANAGER_CONTEXT_KEY = + "rain:ui-components:transactionManager"; /** * Sets the TransactionManager instance in Svelte's context @@ -13,7 +14,7 @@ export const TRANSACTION_MANAGER_CONTEXT_KEY = 'rain:ui-components:transactionMa * @returns {void} */ export function setTransactionManagerContext(manager: TransactionManager) { - setContext(TRANSACTION_MANAGER_CONTEXT_KEY, manager); + setContext(TRANSACTION_MANAGER_CONTEXT_KEY, manager); } /** @@ -23,11 +24,13 @@ export function setTransactionManagerContext(manager: TransactionManager) { * @throws {Error} If no TransactionManager is found in context */ export function getTransactionManagerContext(): TransactionManager { - const manager = getContext(TRANSACTION_MANAGER_CONTEXT_KEY); - if (!manager) { - throw new Error( - 'TransactionManager not found. Did you forget to setTransactionManagerContext?' - ); - } - return manager; + const manager = getContext( + TRANSACTION_MANAGER_CONTEXT_KEY, + ); + if (!manager) { + throw new Error( + "TransactionManager not found. Did you forget to setTransactionManagerContext?", + ); + } + return manager; } diff --git a/packages/ui-components/src/lib/providers/transactions/useTransactions.ts b/packages/ui-components/src/lib/providers/transactions/useTransactions.ts index bb0ada5922..6c4d926b85 100644 --- a/packages/ui-components/src/lib/providers/transactions/useTransactions.ts +++ b/packages/ui-components/src/lib/providers/transactions/useTransactions.ts @@ -1,4 +1,4 @@ -import { getTransactionManagerContext } from './context'; +import { getTransactionManagerContext } from "./context"; /** * Hook for accessing the transaction manager in the application. @@ -10,12 +10,12 @@ import { getTransactionManagerContext } from './context'; * @returns An object containing the transactions store that can be subscribed to */ export function useTransactions() { - const manager = getTransactionManagerContext(); + const manager = getTransactionManagerContext(); - const transactions = manager.getTransactions(); + const transactions = manager.getTransactions(); - return { - manager, - transactions - }; + return { + manager, + transactions, + }; } diff --git a/packages/ui-components/src/lib/providers/wallet/context.ts b/packages/ui-components/src/lib/providers/wallet/context.ts index 0e057a8a96..11f81a552e 100644 --- a/packages/ui-components/src/lib/providers/wallet/context.ts +++ b/packages/ui-components/src/lib/providers/wallet/context.ts @@ -1,63 +1,63 @@ -import { getContext, setContext } from 'svelte'; -import { readable } from 'svelte/store'; -import type { Account } from '../../types/account'; +import { getContext, setContext } from "svelte"; +import { readable } from "svelte/store"; +import type { Account } from "../../types/account"; -export const ACCOUNT_KEY = 'account_key'; +export const ACCOUNT_KEY = "account_key"; /** * Retrieves the account store directly from Svelte's context */ export const getAccountContext = (): Account => { - const account = getContext(ACCOUNT_KEY); - if (!account) { - throw new Error( - 'No account was found in Svelte context. Did you forget to wrap your component with WalletProvider?' - ); - } - return account; + const account = getContext(ACCOUNT_KEY); + if (!account) { + throw new Error( + "No account was found in Svelte context. Did you forget to wrap your component with WalletProvider?", + ); + } + return account; }; /** * Sets the account store in Svelte's context */ export const setAccountContext = (account: Account) => { - setContext(ACCOUNT_KEY, account); + setContext(ACCOUNT_KEY, account); }; if (import.meta.vitest) { - const { describe, it, expect, vi, beforeEach } = import.meta.vitest; + const { describe, it, expect, vi, beforeEach } = import.meta.vitest; - vi.mock('svelte', async (importOriginal) => ({ - ...((await importOriginal()) as object), - getContext: vi.fn() - })); + vi.mock("svelte", async (importOriginal) => ({ + ...((await importOriginal()) as object), + getContext: vi.fn(), + })); - describe('getAccountContext', () => { - const mockGetContext = vi.mocked(getContext); + describe("getAccountContext", () => { + const mockGetContext = vi.mocked(getContext); - beforeEach(() => { - mockGetContext.mockReset(); - }); + beforeEach(() => { + mockGetContext.mockReset(); + }); - it('should return the account from context when it exists', () => { - const mockAccount = readable('0x456'); + it("should return the account from context when it exists", () => { + const mockAccount = readable("0x456"); - mockGetContext.mockImplementation((key) => { - if (key === ACCOUNT_KEY) return mockAccount; - return undefined; - }); + mockGetContext.mockImplementation((key) => { + if (key === ACCOUNT_KEY) return mockAccount; + return undefined; + }); - const result = getAccountContext(); - expect(mockGetContext).toHaveBeenCalledWith(ACCOUNT_KEY); - expect(result).toEqual(mockAccount); - }); + const result = getAccountContext(); + expect(mockGetContext).toHaveBeenCalledWith(ACCOUNT_KEY); + expect(result).toEqual(mockAccount); + }); - it('should throw an error when account is not in context', () => { - mockGetContext.mockReturnValue(undefined); + it("should throw an error when account is not in context", () => { + mockGetContext.mockReturnValue(undefined); - expect(() => getAccountContext()).toThrow( - 'No account was found in Svelte context. Did you forget to wrap your component with WalletProvider?' - ); - }); - }); + expect(() => getAccountContext()).toThrow( + "No account was found in Svelte context. Did you forget to wrap your component with WalletProvider?", + ); + }); + }); } diff --git a/packages/ui-components/src/lib/providers/wallet/useAccount.ts b/packages/ui-components/src/lib/providers/wallet/useAccount.ts index ec0513c251..a752abdf6d 100644 --- a/packages/ui-components/src/lib/providers/wallet/useAccount.ts +++ b/packages/ui-components/src/lib/providers/wallet/useAccount.ts @@ -1,181 +1,187 @@ -import type { Hex } from 'viem'; -import { get } from 'svelte/store'; -import { isAddress, isAddressEqual } from 'viem'; -import { getAccountContext } from './context'; -import { readable } from 'svelte/store'; +import type { Hex } from "viem"; +import { get } from "svelte/store"; +import { isAddress, isAddressEqual } from "viem"; +import { getAccountContext } from "./context"; +import { readable } from "svelte/store"; /** * Hook to access wallet account information from context * Must be used within a component that is a child of WalletProvider */ export function useAccount() { - /** - * The account store containing the current wallet address (as a Hex string) or null if not connected. - * This is a readable Svelte store that can be subscribed to for reactive updates. - * @type {import('svelte/store').Readable} - */ - const account = getAccountContext(); - - /** - * Checks if the provided address matches the currently connected account. - * Returns false if no account is connected or if the provided address is invalid. - */ - const matchesAccount = (otherAddress: string): boolean => { - if (!otherAddress) return false; - const currentAccount = get(account); - if (!currentAccount) { - return false; - } - - if ( - isAddress(currentAccount) && - isAddress(otherAddress) && - isAddressEqual(currentAccount, otherAddress) - ) { - return true; - } - - return false; - }; - - return { - account, - matchesAccount - }; + /** + * The account store containing the current wallet address (as a Hex string) or null if not connected. + * This is a readable Svelte store that can be subscribed to for reactive updates. + * @type {import('svelte/store').Readable} + */ + const account = getAccountContext(); + + /** + * Checks if the provided address matches the currently connected account. + * Returns false if no account is connected or if the provided address is invalid. + */ + const matchesAccount = (otherAddress: string): boolean => { + if (!otherAddress) return false; + const currentAccount = get(account); + if (!currentAccount) { + return false; + } + + if ( + isAddress(currentAccount) && + isAddress(otherAddress) && + isAddressEqual(currentAccount, otherAddress) + ) { + return true; + } + + return false; + }; + + return { + account, + matchesAccount, + }; } if (import.meta.vitest) { - const { describe, it, expect, vi, beforeEach } = import.meta.vitest; - - vi.mock('viem', async () => { - const actual = await vi.importActual('viem'); - return { - ...actual, - isAddress: vi.fn(), - isAddressEqual: vi.fn() - }; - }); - - vi.mock('./context', () => ({ - getAccountContext: vi.fn() - })); - - vi.mock('svelte/store', async () => { - const actual = await vi.importActual('svelte/store'); - return { - ...actual, - get: vi.fn() - }; - }); - - describe('useAccount', () => { - const mockGetAccountContext = vi.mocked(getAccountContext); - const mockGet = vi.mocked(get); - const mockIsAddress = vi.mocked(isAddress); - const mockIsAddressEqual = vi.mocked(isAddressEqual); - - beforeEach(() => { - vi.clearAllMocks(); - }); - - it('should return account wrapped in an object', () => { - const mockAccountStore = readable('0x123' as Hex); - mockGetAccountContext.mockReturnValue(mockAccountStore); - - const result = useAccount(); - - expect(mockGetAccountContext).toHaveBeenCalled(); - expect(result.account).toBe(mockAccountStore); - expect(result.matchesAccount).toBeInstanceOf(Function); - }); - - describe('matchesAccount', () => { - const mockAccountStore = readable('0x123' as Hex); - const currentAccount = '0x123' as Hex; - const testAddress1 = '0x123' as Hex; - const testAddress2 = '0xdef' as Hex; - const invalidAddress = 'invalid'; - - beforeEach(() => { - mockGetAccountContext.mockReturnValue(mockAccountStore); - }); - - it('should return true if addresses are valid and equal', () => { - // Setup mocks - mockGet.mockReturnValue(currentAccount); - mockIsAddress.mockReturnValue(true); - mockIsAddressEqual.mockReturnValue(true); - - const { matchesAccount } = useAccount(); - const result = matchesAccount(testAddress1); - - expect(mockGet).toHaveBeenCalledWith(mockAccountStore); - expect(mockIsAddress).toHaveBeenCalledWith(currentAccount); - expect(mockIsAddress).toHaveBeenCalledWith(testAddress1); - expect(mockIsAddressEqual).toHaveBeenCalledWith(currentAccount, testAddress1); - expect(result).toBe(true); - }); - - it('should return false if addresses are valid but not equal', () => { - // Setup mocks - mockGet.mockReturnValue(currentAccount); - mockIsAddress.mockReturnValue(true); - mockIsAddressEqual.mockReturnValue(false); - - const { matchesAccount } = useAccount(); - const result = matchesAccount(testAddress2); - - expect(mockGet).toHaveBeenCalledWith(mockAccountStore); - expect(mockIsAddress).toHaveBeenCalledWith(currentAccount); - expect(mockIsAddress).toHaveBeenCalledWith(testAddress2); - expect(mockIsAddressEqual).toHaveBeenCalledWith(currentAccount, testAddress2); - expect(result).toBe(false); - }); - - it('should return false if current account is not set', () => { - // Setup mocks - mockGet.mockReturnValue(null); - - const { matchesAccount } = useAccount(); - const result = matchesAccount(testAddress1); - - expect(mockGet).toHaveBeenCalledWith(mockAccountStore); - expect(mockIsAddress).not.toHaveBeenCalled(); - expect(mockIsAddressEqual).not.toHaveBeenCalled(); - expect(result).toBe(false); - }); - it('should return false if provided address is invalid', () => { - // Setup mocks - mockGet.mockReturnValue(currentAccount); - - // This is crucial: we need to ensure short-circuit evaluation works correctly - mockIsAddress.mockImplementation((address) => { - return address !== invalidAddress; // Only the invalid address returns false - }); - - // This should never be called due to short-circuit evaluation - mockIsAddressEqual.mockReturnValue(false); - - const { matchesAccount } = useAccount(); - const result = matchesAccount(invalidAddress); - - expect(mockGet).toHaveBeenCalledWith(mockAccountStore); - expect(mockIsAddress).toHaveBeenCalledWith(currentAccount); - expect(mockIsAddress).toHaveBeenCalledWith(invalidAddress); - expect(mockIsAddressEqual).not.toHaveBeenCalled(); // This should now pass - expect(result).toBe(false); - }); - it('should return false if provided address is null', () => { - // Setup mocks - mockGet.mockReturnValue(currentAccount); - - const { matchesAccount } = useAccount(); - const result = matchesAccount(null as unknown as string); - - expect(mockIsAddress).not.toHaveBeenCalled(); - expect(mockIsAddressEqual).not.toHaveBeenCalled(); - expect(result).toBe(false); - }); - }); - }); + const { describe, it, expect, vi, beforeEach } = import.meta.vitest; + + vi.mock("viem", async () => { + const actual = await vi.importActual("viem"); + return { + ...actual, + isAddress: vi.fn(), + isAddressEqual: vi.fn(), + }; + }); + + vi.mock("./context", () => ({ + getAccountContext: vi.fn(), + })); + + vi.mock("svelte/store", async () => { + const actual = await vi.importActual("svelte/store"); + return { + ...actual, + get: vi.fn(), + }; + }); + + describe("useAccount", () => { + const mockGetAccountContext = vi.mocked(getAccountContext); + const mockGet = vi.mocked(get); + const mockIsAddress = vi.mocked(isAddress); + const mockIsAddressEqual = vi.mocked(isAddressEqual); + + beforeEach(() => { + vi.clearAllMocks(); + }); + + it("should return account wrapped in an object", () => { + const mockAccountStore = readable("0x123" as Hex); + mockGetAccountContext.mockReturnValue(mockAccountStore); + + const result = useAccount(); + + expect(mockGetAccountContext).toHaveBeenCalled(); + expect(result.account).toBe(mockAccountStore); + expect(result.matchesAccount).toBeInstanceOf(Function); + }); + + describe("matchesAccount", () => { + const mockAccountStore = readable("0x123" as Hex); + const currentAccount = "0x123" as Hex; + const testAddress1 = "0x123" as Hex; + const testAddress2 = "0xdef" as Hex; + const invalidAddress = "invalid"; + + beforeEach(() => { + mockGetAccountContext.mockReturnValue(mockAccountStore); + }); + + it("should return true if addresses are valid and equal", () => { + // Setup mocks + mockGet.mockReturnValue(currentAccount); + mockIsAddress.mockReturnValue(true); + mockIsAddressEqual.mockReturnValue(true); + + const { matchesAccount } = useAccount(); + const result = matchesAccount(testAddress1); + + expect(mockGet).toHaveBeenCalledWith(mockAccountStore); + expect(mockIsAddress).toHaveBeenCalledWith(currentAccount); + expect(mockIsAddress).toHaveBeenCalledWith(testAddress1); + expect(mockIsAddressEqual).toHaveBeenCalledWith( + currentAccount, + testAddress1, + ); + expect(result).toBe(true); + }); + + it("should return false if addresses are valid but not equal", () => { + // Setup mocks + mockGet.mockReturnValue(currentAccount); + mockIsAddress.mockReturnValue(true); + mockIsAddressEqual.mockReturnValue(false); + + const { matchesAccount } = useAccount(); + const result = matchesAccount(testAddress2); + + expect(mockGet).toHaveBeenCalledWith(mockAccountStore); + expect(mockIsAddress).toHaveBeenCalledWith(currentAccount); + expect(mockIsAddress).toHaveBeenCalledWith(testAddress2); + expect(mockIsAddressEqual).toHaveBeenCalledWith( + currentAccount, + testAddress2, + ); + expect(result).toBe(false); + }); + + it("should return false if current account is not set", () => { + // Setup mocks + mockGet.mockReturnValue(null); + + const { matchesAccount } = useAccount(); + const result = matchesAccount(testAddress1); + + expect(mockGet).toHaveBeenCalledWith(mockAccountStore); + expect(mockIsAddress).not.toHaveBeenCalled(); + expect(mockIsAddressEqual).not.toHaveBeenCalled(); + expect(result).toBe(false); + }); + it("should return false if provided address is invalid", () => { + // Setup mocks + mockGet.mockReturnValue(currentAccount); + + // This is crucial: we need to ensure short-circuit evaluation works correctly + mockIsAddress.mockImplementation((address) => { + return address !== invalidAddress; // Only the invalid address returns false + }); + + // This should never be called due to short-circuit evaluation + mockIsAddressEqual.mockReturnValue(false); + + const { matchesAccount } = useAccount(); + const result = matchesAccount(invalidAddress); + + expect(mockGet).toHaveBeenCalledWith(mockAccountStore); + expect(mockIsAddress).toHaveBeenCalledWith(currentAccount); + expect(mockIsAddress).toHaveBeenCalledWith(invalidAddress); + expect(mockIsAddressEqual).not.toHaveBeenCalled(); // This should now pass + expect(result).toBe(false); + }); + it("should return false if provided address is null", () => { + // Setup mocks + mockGet.mockReturnValue(currentAccount); + + const { matchesAccount } = useAccount(); + const result = matchesAccount(null as unknown as string); + + expect(mockIsAddress).not.toHaveBeenCalled(); + expect(mockIsAddressEqual).not.toHaveBeenCalled(); + expect(result).toBe(false); + }); + }); + }); } diff --git a/packages/ui-components/src/lib/queries/keys.ts b/packages/ui-components/src/lib/queries/keys.ts index ccb0f17148..857e95bf17 100644 --- a/packages/ui-components/src/lib/queries/keys.ts +++ b/packages/ui-components/src/lib/queries/keys.ts @@ -1,10 +1,10 @@ -export const QKEY_VAULTS = 'vaults'; -export const QKEY_VAULT = 'vault'; -export const QKEY_VAULT_CHANGES = 'vaultBalanceChanges'; -export const QKEY_ORDERS = 'orders'; -export const QKEY_ORDER = 'order'; -export const QKEY_ORDER_TRADES_LIST = 'orderTradesList'; -export const QKEY_ORDER_QUOTE = 'orderQuote'; -export const QKEY_VAULTS_VOL_LIST = 'orderVaultsVolumeList'; -export const QKEY_ORDER_APY = 'orderApy'; -export const QKEY_TOKENS = 'tokens'; +export const QKEY_VAULTS = "vaults"; +export const QKEY_VAULT = "vault"; +export const QKEY_VAULT_CHANGES = "vaultBalanceChanges"; +export const QKEY_ORDERS = "orders"; +export const QKEY_ORDER = "order"; +export const QKEY_ORDER_TRADES_LIST = "orderTradesList"; +export const QKEY_ORDER_QUOTE = "orderQuote"; +export const QKEY_VAULTS_VOL_LIST = "orderVaultsVolumeList"; +export const QKEY_ORDER_APY = "orderApy"; +export const QKEY_TOKENS = "tokens"; diff --git a/packages/ui-components/src/lib/queries/queryClient.ts b/packages/ui-components/src/lib/queries/queryClient.ts index 6c8dd968ac..23817bfc14 100644 --- a/packages/ui-components/src/lib/queries/queryClient.ts +++ b/packages/ui-components/src/lib/queries/queryClient.ts @@ -1,22 +1,25 @@ -import { browser } from '$app/environment'; -import { QueryClient } from '@tanstack/svelte-query'; +import { browser } from "$app/environment"; +import { QueryClient } from "@tanstack/svelte-query"; export const queryClient = new QueryClient({ - defaultOptions: { - queries: { - enabled: browser - } - } + defaultOptions: { + queries: { + enabled: browser, + }, + }, }); -export const invalidateTanstackQueries = async (queryClient: QueryClient, queryKey: string[]) => { - try { - await queryClient.invalidateQueries({ - queryKey, - refetchType: 'all', - exact: false - }); - } catch { - throw new Error('Failed to refresh data.'); - } +export const invalidateTanstackQueries = async ( + queryClient: QueryClient, + queryKey: string[], +) => { + try { + await queryClient.invalidateQueries({ + queryKey, + refetchType: "all", + exact: false, + }); + } catch { + throw new Error("Failed to refresh data."); + } }; diff --git a/packages/ui-components/src/lib/services/awaitTransactionIndexing.ts b/packages/ui-components/src/lib/services/awaitTransactionIndexing.ts index 8f3563763f..15b8df77ea 100644 --- a/packages/ui-components/src/lib/services/awaitTransactionIndexing.ts +++ b/packages/ui-components/src/lib/services/awaitTransactionIndexing.ts @@ -3,26 +3,28 @@ * @description Utilities for waiting for transactions to be indexed by a subgraph */ -import { TransactionStoreErrorMessage } from '$lib/types/transaction'; +import { TransactionStoreErrorMessage } from "$lib/types/transaction"; import type { - WasmEncodedResult, - RaindexTransaction, - RaindexOrder, - Address, - Hex -} from '@rainlanguage/raindex'; + WasmEncodedResult, + RaindexTransaction, + RaindexOrder, + Address, + Hex, +} from "@rainlanguage/raindex"; export type AwaitSubgraphConfig = { - chainId: number; - raindex: Address; - txHash: Hex; - successMessage: string; - fetchEntityFn: ( - chainId: number, - raindex: Address, - txHash: Hex - ) => Promise>; - isSuccess: (data: RaindexTransaction | RaindexOrder[]) => boolean; + chainId: number; + raindex: Address; + txHash: Hex; + successMessage: string; + fetchEntityFn: ( + chainId: number, + raindex: Address, + txHash: Hex, + ) => Promise< + WasmEncodedResult + >; + isSuccess: (data: RaindexTransaction | RaindexOrder[]) => boolean; }; /** @@ -30,35 +32,35 @@ export type AwaitSubgraphConfig = { * @template T The type of data returned by the subgraph */ export type IndexingResult = { - /** - * The successful result of the indexing operation - */ - value?: { - /** - * The transaction hash - */ - txHash: Hex; - /** - * Message to display on successful indexing - */ - successMessage: string; - /** - * Optional order hash if available - */ - orderHash?: Hex; - /** - * Optional network key - */ - network?: string; - /** - * Optional data returned from the subgraph - */ - data?: T; - }; - /** - * Error message if indexing failed - */ - error?: string; + /** + * The successful result of the indexing operation + */ + value?: { + /** + * The transaction hash + */ + txHash: Hex; + /** + * Message to display on successful indexing + */ + successMessage: string; + /** + * Optional order hash if available + */ + orderHash?: Hex; + /** + * Optional network key + */ + network?: string; + /** + * Optional data returned from the subgraph + */ + data?: T; + }; + /** + * Error message if indexing failed + */ + error?: string; }; /** @@ -79,98 +81,102 @@ export type IndexingResult = { * @returns Promise resolving to an IndexingResult */ export const awaitSubgraphIndexing = async (options: { - /** - * Chain ID to query - */ - chainId: number; - /** - * Raindex address to query - */ - raindex: Address; - /** - * Transaction hash to check for indexing - */ - txHash: Hex; - /** - * Message to display on successful indexing - */ - successMessage: string; - /** - * Maximum number of attempts before timing out - */ - maxAttempts?: number; - /** - * Interval between attempts in milliseconds - */ - interval?: number; - /** - * Optional network identifier - */ - network?: string; - /** - * Function to fetch data from the subgraph - * @param chainId Chain ID to query - * @param raindex Raindex address to query - * @param txHash Transaction hash to query - */ - fetchEntityFn: ( - chainId: number, - raindex: Address, - txHash: Hex - ) => Promise>; - /** - * Function to determine if the fetched data indicates success - * @param data The data returned from the subgraph - */ - isSuccess: (data: T) => boolean; + /** + * Chain ID to query + */ + chainId: number; + /** + * Raindex address to query + */ + raindex: Address; + /** + * Transaction hash to check for indexing + */ + txHash: Hex; + /** + * Message to display on successful indexing + */ + successMessage: string; + /** + * Maximum number of attempts before timing out + */ + maxAttempts?: number; + /** + * Interval between attempts in milliseconds + */ + interval?: number; + /** + * Optional network identifier + */ + network?: string; + /** + * Function to fetch data from the subgraph + * @param chainId Chain ID to query + * @param raindex Raindex address to query + * @param txHash Transaction hash to query + */ + fetchEntityFn: ( + chainId: number, + raindex: Address, + txHash: Hex, + ) => Promise>; + /** + * Function to determine if the fetched data indicates success + * @param data The data returned from the subgraph + */ + isSuccess: (data: T) => boolean; }): Promise> => { - const { - chainId, - raindex, - txHash, - successMessage, - maxAttempts = 10, - interval = 1000, - network, - fetchEntityFn, - isSuccess - } = options; + const { + chainId, + raindex, + txHash, + successMessage, + maxAttempts = 10, + interval = 1000, + network, + fetchEntityFn, + isSuccess, + } = options; - const checkIndexing = async (attempt: number): Promise> => { - try { - const data = await fetchEntityFn(chainId, raindex, txHash); + const checkIndexing = async (attempt: number): Promise> => { + try { + const data = await fetchEntityFn(chainId, raindex, txHash); - if (data.value && isSuccess(data.value)) { - let newOrderHash; - // Extract orderHash from order data if it exists in the expected format - // This only applies to addOrder transactions - if (Array.isArray(data.value) && data.value.length > 0 && data.value[0]?.orderHash) { - newOrderHash = data.value[0].orderHash; - } + if (data.value && isSuccess(data.value)) { + let newOrderHash; + // Extract orderHash from order data if it exists in the expected format + // This only applies to addOrder transactions + if ( + Array.isArray(data.value) && + data.value.length > 0 && + data.value[0]?.orderHash + ) { + newOrderHash = data.value[0].orderHash; + } - return { - value: { - txHash, - successMessage, - orderHash: newOrderHash, - network, - data: data.value - } - }; - } - } catch { - // Continue with the next attempt - } + return { + value: { + txHash, + successMessage, + orderHash: newOrderHash, + network, + data: data.value, + }, + }; + } + } catch { + // Continue with the next attempt + } - if (attempt >= maxAttempts) { - return { - error: TransactionStoreErrorMessage.SUBGRAPH_TIMEOUT_ERROR - }; - } + if (attempt >= maxAttempts) { + return { + error: TransactionStoreErrorMessage.SUBGRAPH_TIMEOUT_ERROR, + }; + } - await new Promise((resolve) => setTimeout(resolve, interval)); - return checkIndexing(attempt + 1); - }; + await new Promise((resolve) => setTimeout(resolve, interval)); + return checkIndexing(attempt + 1); + }; - return checkIndexing(1); + return checkIndexing(1); }; diff --git a/packages/ui-components/src/lib/services/getExplorerLink.ts b/packages/ui-components/src/lib/services/getExplorerLink.ts index 7de9bfa402..a5d5f86a0d 100644 --- a/packages/ui-components/src/lib/services/getExplorerLink.ts +++ b/packages/ui-components/src/lib/services/getExplorerLink.ts @@ -1,9 +1,13 @@ -import * as chains from 'viem/chains'; +import * as chains from "viem/chains"; -export const getExplorerLink = (hash: string, chainId: number, type: 'tx' | 'address'): string => { - const chain = Object.values(chains).find((chain) => chain.id === chainId); - if (chain?.blockExplorers) { - return chain.blockExplorers.default.url + `/${type}/${hash}`; - } - return ''; +export const getExplorerLink = ( + hash: string, + chainId: number, + type: "tx" | "address", +): string => { + const chain = Object.values(chains).find((chain) => chain.id === chainId); + if (chain?.blockExplorers) { + return chain.blockExplorers.default.url + `/${type}/${hash}`; + } + return ""; }; diff --git a/packages/ui-components/src/lib/services/handleShareChoices.ts b/packages/ui-components/src/lib/services/handleShareChoices.ts index 41c98bcd21..d535fd2042 100644 --- a/packages/ui-components/src/lib/services/handleShareChoices.ts +++ b/packages/ui-components/src/lib/services/handleShareChoices.ts @@ -1,18 +1,21 @@ -import type { RaindexOrderBuilder } from '@rainlanguage/raindex'; -import { page } from '$app/stores'; -import { get } from 'svelte/store'; +import type { RaindexOrderBuilder } from "@rainlanguage/raindex"; +import { page } from "$app/stores"; +import { get } from "svelte/store"; -export async function handleShareChoices(builder: RaindexOrderBuilder, registryUrl: string) { - // get the current url - const url = get(page).url; +export async function handleShareChoices( + builder: RaindexOrderBuilder, + registryUrl: string, +) { + // get the current url + const url = get(page).url; - // get the current state - const result = builder.serializeState(); - if (result.error) { - throw new Error(result.error.msg); - } - const state = result.value; - url.searchParams.set('state', state || ''); - url.searchParams.set('registry', registryUrl); - navigator.clipboard.writeText(url.toString()); + // get the current state + const result = builder.serializeState(); + if (result.error) { + throw new Error(result.error.msg); + } + const state = result.value; + url.searchParams.set("state", state || ""); + url.searchParams.set("registry", registryUrl); + navigator.clipboard.writeText(url.toString()); } diff --git a/packages/ui-components/src/lib/services/historicalOrderCharts.ts b/packages/ui-components/src/lib/services/historicalOrderCharts.ts index 56e9db5539..c0d6dfd539 100644 --- a/packages/ui-components/src/lib/services/historicalOrderCharts.ts +++ b/packages/ui-components/src/lib/services/historicalOrderCharts.ts @@ -1,458 +1,469 @@ import type { - RaindexTrade, - RaindexTransaction, - RaindexVaultBalanceChange, - RaindexVaultToken -} from '@rainlanguage/raindex'; -import type { UTCTimestamp } from 'lightweight-charts'; -import { timestampSecondsToUTCTimestamp } from '../services/time'; -import { sortBy } from 'lodash'; + RaindexTrade, + RaindexTransaction, + RaindexVaultBalanceChange, + RaindexVaultToken, +} from "@rainlanguage/raindex"; +import type { UTCTimestamp } from "lightweight-charts"; +import { timestampSecondsToUTCTimestamp } from "../services/time"; +import { sortBy } from "lodash"; -export type HistoricalOrderChartData = { value: number; time: UTCTimestamp; color?: string }[]; +export type HistoricalOrderChartData = { + value: number; + time: UTCTimestamp; + color?: string; +}[]; export function prepareHistoricalOrderChartData( - takeOrderEntities: RaindexTrade[], - colorTheme: string + takeOrderEntities: RaindexTrade[], + colorTheme: string, ) { - const transformedData = takeOrderEntities.map((d) => ({ - value: Math.abs( - Number(d.inputVaultBalanceChange.formattedAmount) / - Number(d.outputVaultBalanceChange.formattedAmount) - ), - time: timestampSecondsToUTCTimestamp(BigInt(d.timestamp)), - color: colorTheme == 'dark' ? '#5178FF' : '#4E4AF6', - outputAmount: Number(d.outputVaultBalanceChange.amount) - })); + const transformedData = takeOrderEntities.map((d) => ({ + value: Math.abs( + Number(d.inputVaultBalanceChange.formattedAmount) / + Number(d.outputVaultBalanceChange.formattedAmount), + ), + time: timestampSecondsToUTCTimestamp(BigInt(d.timestamp)), + color: colorTheme == "dark" ? "#5178FF" : "#4E4AF6", + outputAmount: Number(d.outputVaultBalanceChange.amount), + })); - // if we have multiple object in the array with the same timestamp, we need to merge them - // we do this by taking the weighted average of the ioratio values for objects that share the same timestamp. - const uniqueTimestamps = Array.from(new Set(transformedData.map((d) => d.time))); - const finalData: HistoricalOrderChartData = []; - uniqueTimestamps.forEach((timestamp) => { - const objectsWithSameTimestamp = transformedData.filter((d) => d.time === timestamp); - if (objectsWithSameTimestamp.length > 1) { - // calculate a weighted average of the ioratio values using the amount of the output token as the weight - const ioratioSum = objectsWithSameTimestamp.reduce( - (acc, d) => acc + d.value * d.outputAmount, - 0 - ); - const outputAmountSum = objectsWithSameTimestamp.reduce((acc, d) => acc + d.outputAmount, 0); - const ioratioAverage = ioratioSum / outputAmountSum; - finalData.push({ - value: ioratioAverage, - time: timestamp, - color: objectsWithSameTimestamp[0].color - }); - } else { - finalData.push(objectsWithSameTimestamp[0]); - } - }); + // if we have multiple object in the array with the same timestamp, we need to merge them + // we do this by taking the weighted average of the ioratio values for objects that share the same timestamp. + const uniqueTimestamps = Array.from( + new Set(transformedData.map((d) => d.time)), + ); + const finalData: HistoricalOrderChartData = []; + uniqueTimestamps.forEach((timestamp) => { + const objectsWithSameTimestamp = transformedData.filter( + (d) => d.time === timestamp, + ); + if (objectsWithSameTimestamp.length > 1) { + // calculate a weighted average of the ioratio values using the amount of the output token as the weight + const ioratioSum = objectsWithSameTimestamp.reduce( + (acc, d) => acc + d.value * d.outputAmount, + 0, + ); + const outputAmountSum = objectsWithSameTimestamp.reduce( + (acc, d) => acc + d.outputAmount, + 0, + ); + const ioratioAverage = ioratioSum / outputAmountSum; + finalData.push({ + value: ioratioAverage, + time: timestamp, + color: objectsWithSameTimestamp[0].color, + }); + } else { + finalData.push(objectsWithSameTimestamp[0]); + } + }); - return sortBy(finalData, (d) => d.time); + return sortBy(finalData, (d) => d.time); } if (import.meta.vitest) { - const { it, expect } = import.meta.vitest; + const { it, expect } = import.meta.vitest; - it('transforms and sorts data as expected', () => { - const takeOrderEntities: RaindexTrade[] = [ - { - id: '1', - timestamp: BigInt(1632000000), - transaction: { - id: 'transaction_id', - from: '0xsender_address', - timestamp: BigInt(1632000000), - blockNumber: BigInt(0) - } as unknown as RaindexTransaction, - outputVaultBalanceChange: { - amount: BigInt(100), - formattedAmount: '100', - vaultId: BigInt(1), - __typename: 'Withdraw', - token: { - id: 'output_token', - address: '0xoutput_token', - name: 'output_token', - symbol: 'output_token', - decimals: BigInt(1) - } as unknown as RaindexVaultToken, - newBalance: BigInt(0), - formattedNewBalance: '0', - oldBalance: BigInt(0), - formattedOldBalance: '0', - timestamp: BigInt(0), - transaction: { - id: 'transaction_id', - from: 'sender_address', - timestamp: BigInt(1632000000), - blockNumber: BigInt(0) - } as unknown as RaindexTransaction, - raindex: '0x1' - } as unknown as RaindexVaultBalanceChange, - orderHash: 'orderHash', - inputVaultBalanceChange: { - vaultId: BigInt(1), - token: { - id: 'output_token', - address: '0xoutput_token', - name: 'output_token', - symbol: 'output_token', - decimals: BigInt(1) - } as unknown as RaindexVaultToken, - amount: BigInt(50), - formattedAmount: '50', - __typename: 'Withdraw', - newBalance: BigInt(0), - formattedNewBalance: '0', - oldBalance: BigInt(0), - formattedOldBalance: '0', - timestamp: BigInt(0), - transaction: { - id: 'transaction_id', - from: '0xsender_address', - timestamp: BigInt(1632000000), - blockNumber: BigInt(0) - } as unknown as RaindexTransaction, - raindex: '0x1' - } as unknown as RaindexVaultBalanceChange, - raindex: '0x00' - } as unknown as RaindexTrade, - { - id: '2', - timestamp: BigInt(1631000000), - transaction: { - id: 'transaction_id', - from: '0xsender_address', - timestamp: BigInt(1631000000), - blockNumber: BigInt(0) - } as unknown as RaindexTransaction, - outputVaultBalanceChange: { - amount: BigInt(100), - formattedAmount: '100', - vaultId: BigInt(1), - token: { - id: 'output_token', - address: '0xoutput_token', - name: 'output_token', - symbol: 'output_token', - decimals: BigInt(1) - } as unknown as RaindexVaultToken, - newBalance: BigInt(0), - formattedNewBalance: '0', - oldBalance: BigInt(0), - formattedOldBalance: '0', - __typename: 'Withdraw', - timestamp: BigInt(0), - transaction: { - id: 'transaction_id', - from: '0xsender_address', - timestamp: BigInt(1632000000), - blockNumber: BigInt(0) - } as unknown as RaindexTransaction, - raindex: '0x1' - } as unknown as RaindexVaultBalanceChange, - orderHash: 'orderHash', - inputVaultBalanceChange: { - vaultId: BigInt(1), - token: { - id: 'output_token', - address: '0xoutput_token', - name: 'output_token', - symbol: 'output_token', - decimals: BigInt(1) - } as unknown as RaindexVaultToken, - amount: BigInt(50), - formattedAmount: '50', - __typename: 'Withdraw', - newBalance: BigInt(0), - formattedNewBalance: '0', - oldBalance: BigInt(0), - formattedOldBalance: '0', - timestamp: BigInt(0), - transaction: { - id: 'transaction_id', - from: '0xsender_address', - timestamp: BigInt(1632000000), - blockNumber: BigInt(0) - } as unknown as RaindexTransaction, - raindex: '0x1' - } as unknown as RaindexVaultBalanceChange, - raindex: '0x00' - } as unknown as RaindexTrade, - { - id: '3', - timestamp: BigInt(1630000000), - transaction: { - id: 'transaction_id', - from: '0xsender_address', - timestamp: BigInt(1630000000), - blockNumber: BigInt(0) - } as unknown as RaindexTransaction, - outputVaultBalanceChange: { - amount: BigInt(100), - formattedAmount: '100', - vaultId: BigInt(1), - token: { - id: 'output_token', - address: '0xoutput_token', - name: 'output_token', - symbol: 'output_token', - decimals: BigInt(1) - } as unknown as RaindexVaultToken, - newBalance: BigInt(0), - formattedNewBalance: '0', - oldBalance: BigInt(0), - formattedOldBalance: '0', - __typename: 'Withdraw', - timestamp: BigInt(0), - transaction: { - id: 'transaction_id', - from: 'sender_address', - timestamp: BigInt(1632000000), - blockNumber: BigInt(0) - } as unknown as RaindexTransaction, - raindex: '0x1' - } as unknown as RaindexVaultBalanceChange, - orderHash: 'orderHash', - inputVaultBalanceChange: { - vaultId: BigInt(1), - token: { - id: 'output_token', - address: '0xoutput_token', - name: 'output_token', - symbol: 'output_token', - decimals: BigInt(1) - } as unknown as RaindexVaultToken, - newBalance: BigInt(0), - formattedNewBalance: '0', - oldBalance: BigInt(0), - formattedOldBalance: '0', - amount: BigInt(50), - formattedAmount: '50', - __typename: 'Withdraw', - timestamp: BigInt(0), - transaction: { - id: 'transaction_id', - from: 'sender_address', - timestamp: BigInt(1632000000), - blockNumber: BigInt(0) - } as unknown as RaindexTransaction, - raindex: '0x1' - } as unknown as RaindexVaultBalanceChange, - raindex: '0x00' - } as unknown as RaindexTrade - ]; + it("transforms and sorts data as expected", () => { + const takeOrderEntities: RaindexTrade[] = [ + { + id: "1", + timestamp: BigInt(1632000000), + transaction: { + id: "transaction_id", + from: "0xsender_address", + timestamp: BigInt(1632000000), + blockNumber: BigInt(0), + } as unknown as RaindexTransaction, + outputVaultBalanceChange: { + amount: BigInt(100), + formattedAmount: "100", + vaultId: BigInt(1), + __typename: "Withdraw", + token: { + id: "output_token", + address: "0xoutput_token", + name: "output_token", + symbol: "output_token", + decimals: BigInt(1), + } as unknown as RaindexVaultToken, + newBalance: BigInt(0), + formattedNewBalance: "0", + oldBalance: BigInt(0), + formattedOldBalance: "0", + timestamp: BigInt(0), + transaction: { + id: "transaction_id", + from: "sender_address", + timestamp: BigInt(1632000000), + blockNumber: BigInt(0), + } as unknown as RaindexTransaction, + raindex: "0x1", + } as unknown as RaindexVaultBalanceChange, + orderHash: "orderHash", + inputVaultBalanceChange: { + vaultId: BigInt(1), + token: { + id: "output_token", + address: "0xoutput_token", + name: "output_token", + symbol: "output_token", + decimals: BigInt(1), + } as unknown as RaindexVaultToken, + amount: BigInt(50), + formattedAmount: "50", + __typename: "Withdraw", + newBalance: BigInt(0), + formattedNewBalance: "0", + oldBalance: BigInt(0), + formattedOldBalance: "0", + timestamp: BigInt(0), + transaction: { + id: "transaction_id", + from: "0xsender_address", + timestamp: BigInt(1632000000), + blockNumber: BigInt(0), + } as unknown as RaindexTransaction, + raindex: "0x1", + } as unknown as RaindexVaultBalanceChange, + raindex: "0x00", + } as unknown as RaindexTrade, + { + id: "2", + timestamp: BigInt(1631000000), + transaction: { + id: "transaction_id", + from: "0xsender_address", + timestamp: BigInt(1631000000), + blockNumber: BigInt(0), + } as unknown as RaindexTransaction, + outputVaultBalanceChange: { + amount: BigInt(100), + formattedAmount: "100", + vaultId: BigInt(1), + token: { + id: "output_token", + address: "0xoutput_token", + name: "output_token", + symbol: "output_token", + decimals: BigInt(1), + } as unknown as RaindexVaultToken, + newBalance: BigInt(0), + formattedNewBalance: "0", + oldBalance: BigInt(0), + formattedOldBalance: "0", + __typename: "Withdraw", + timestamp: BigInt(0), + transaction: { + id: "transaction_id", + from: "0xsender_address", + timestamp: BigInt(1632000000), + blockNumber: BigInt(0), + } as unknown as RaindexTransaction, + raindex: "0x1", + } as unknown as RaindexVaultBalanceChange, + orderHash: "orderHash", + inputVaultBalanceChange: { + vaultId: BigInt(1), + token: { + id: "output_token", + address: "0xoutput_token", + name: "output_token", + symbol: "output_token", + decimals: BigInt(1), + } as unknown as RaindexVaultToken, + amount: BigInt(50), + formattedAmount: "50", + __typename: "Withdraw", + newBalance: BigInt(0), + formattedNewBalance: "0", + oldBalance: BigInt(0), + formattedOldBalance: "0", + timestamp: BigInt(0), + transaction: { + id: "transaction_id", + from: "0xsender_address", + timestamp: BigInt(1632000000), + blockNumber: BigInt(0), + } as unknown as RaindexTransaction, + raindex: "0x1", + } as unknown as RaindexVaultBalanceChange, + raindex: "0x00", + } as unknown as RaindexTrade, + { + id: "3", + timestamp: BigInt(1630000000), + transaction: { + id: "transaction_id", + from: "0xsender_address", + timestamp: BigInt(1630000000), + blockNumber: BigInt(0), + } as unknown as RaindexTransaction, + outputVaultBalanceChange: { + amount: BigInt(100), + formattedAmount: "100", + vaultId: BigInt(1), + token: { + id: "output_token", + address: "0xoutput_token", + name: "output_token", + symbol: "output_token", + decimals: BigInt(1), + } as unknown as RaindexVaultToken, + newBalance: BigInt(0), + formattedNewBalance: "0", + oldBalance: BigInt(0), + formattedOldBalance: "0", + __typename: "Withdraw", + timestamp: BigInt(0), + transaction: { + id: "transaction_id", + from: "sender_address", + timestamp: BigInt(1632000000), + blockNumber: BigInt(0), + } as unknown as RaindexTransaction, + raindex: "0x1", + } as unknown as RaindexVaultBalanceChange, + orderHash: "orderHash", + inputVaultBalanceChange: { + vaultId: BigInt(1), + token: { + id: "output_token", + address: "0xoutput_token", + name: "output_token", + symbol: "output_token", + decimals: BigInt(1), + } as unknown as RaindexVaultToken, + newBalance: BigInt(0), + formattedNewBalance: "0", + oldBalance: BigInt(0), + formattedOldBalance: "0", + amount: BigInt(50), + formattedAmount: "50", + __typename: "Withdraw", + timestamp: BigInt(0), + transaction: { + id: "transaction_id", + from: "sender_address", + timestamp: BigInt(1632000000), + blockNumber: BigInt(0), + } as unknown as RaindexTransaction, + raindex: "0x1", + } as unknown as RaindexVaultBalanceChange, + raindex: "0x00", + } as unknown as RaindexTrade, + ]; - const result = prepareHistoricalOrderChartData(takeOrderEntities, 'dark'); + const result = prepareHistoricalOrderChartData(takeOrderEntities, "dark"); - expect(result.length).toEqual(3); - expect(result[0].value).toEqual(0.5); - expect(result[0].time).toEqual(1630000000); - expect(result[1].value).toEqual(0.5); - expect(result[1].time).toEqual(1631000000); - expect(result[2].value).toEqual(0.5); - expect(result[2].time).toEqual(1632000000); + expect(result.length).toEqual(3); + expect(result[0].value).toEqual(0.5); + expect(result[0].time).toEqual(1630000000); + expect(result[1].value).toEqual(0.5); + expect(result[1].time).toEqual(1631000000); + expect(result[2].value).toEqual(0.5); + expect(result[2].time).toEqual(1632000000); - // check the color - expect(result[0].color).toEqual('#5178FF'); - expect(result[1].color).toEqual('#5178FF'); - expect(result[2].color).toEqual('#5178FF'); - }); + // check the color + expect(result[0].color).toEqual("#5178FF"); + expect(result[1].color).toEqual("#5178FF"); + expect(result[2].color).toEqual("#5178FF"); + }); - it('handles the case where multiple trades have the same timestamp', () => { - const takeOrderEntities: RaindexTrade[] = [ - { - id: '1', - timestamp: BigInt(1632000000), - transaction: { - id: 'transaction_id', - from: '0xsender_address', - timestamp: BigInt(1632000000), - blockNumber: BigInt(0) - } as unknown as RaindexTransaction, - outputVaultBalanceChange: { - amount: BigInt(100), - formattedAmount: '100', - vaultId: BigInt(1), - token: { - id: 'output_token', - address: '0xoutput_token', - name: 'output_token', - symbol: 'output_token', - decimals: BigInt(1) - } as unknown as RaindexVaultToken, - newBalance: BigInt(0), - formattedNewBalance: '0', - oldBalance: BigInt(0), - formattedOldBalance: '0', - timestamp: BigInt(0), - transaction: { - id: 'transaction_id', - from: '0xsender_address', - timestamp: BigInt(1632000000), - blockNumber: BigInt(0) - } as unknown as RaindexTransaction, - __typename: 'Withdraw', - raindex: '0x1' - } as unknown as RaindexVaultBalanceChange, - orderHash: 'orderHash', - inputVaultBalanceChange: { - vaultId: BigInt(1), - token: { - id: 'output_token', - address: '0xoutput_token', - name: 'output_token', - symbol: 'output_token', - decimals: BigInt(1) - } as unknown as RaindexVaultToken, - amount: BigInt(50), - formattedAmount: '50', - newBalance: BigInt(0), - formattedNewBalance: '0', - oldBalance: BigInt(0), - formattedOldBalance: '0', - timestamp: BigInt(0), - transaction: { - id: 'transaction_id', - from: '0xsender_address', - timestamp: BigInt(1632000000), - blockNumber: BigInt(0) - } as unknown as RaindexTransaction, - raindex: '0x1' - } as unknown as RaindexVaultBalanceChange, - raindex: '0x00' - } as unknown as RaindexTrade, - { - id: '2', - timestamp: BigInt(1632000000), - transaction: { - id: 'transaction_id', - from: '0xsender_address', - timestamp: BigInt(1632000000), - blockNumber: BigInt(0) - } as unknown as RaindexTransaction, - outputVaultBalanceChange: { - amount: BigInt(200), - formattedAmount: '200', - vaultId: BigInt(1), - token: { - id: 'output_token', - address: '0xoutput_token', - name: 'output_token', - symbol: 'output_token', - decimals: BigInt(1) - } as unknown as RaindexVaultToken, - newBalance: BigInt(0), - formattedNewBalance: '0', - oldBalance: BigInt(0), - formattedOldBalance: '0', - timestamp: BigInt(0), - transaction: { - id: 'transaction_id', - from: '0xsender_address', - timestamp: BigInt(1632000000), - blockNumber: BigInt(0) - } as unknown as RaindexTransaction, - raindex: '0x1' - } as unknown as RaindexVaultBalanceChange, - orderHash: 'orderHash', - inputVaultBalanceChange: { - vaultId: BigInt(1), - token: { - id: 'output_token', - address: '0xoutput_token', - name: 'output_token', - symbol: 'output_token', - decimals: BigInt(1) - } as unknown as RaindexVaultToken, - amount: BigInt(50), - formattedAmount: '50', - newBalance: BigInt(0), - formattedNewBalance: '0', - oldBalance: BigInt(0), - formattedOldBalance: '0', - timestamp: BigInt(0), - transaction: { - id: 'transaction_id', - from: '0xsender_address', - timestamp: BigInt(1632000000), - blockNumber: BigInt(0) - } as unknown as RaindexTransaction, - raindex: '0x1' - } as unknown as RaindexVaultBalanceChange, - raindex: '0x00' - } as unknown as RaindexTrade, - { - id: '3', - timestamp: BigInt(1632000000), - transaction: { - id: 'transaction_id', - from: '0xsender_address', - timestamp: BigInt(1632000000), - blockNumber: BigInt(0) - } as unknown as RaindexTransaction, - outputVaultBalanceChange: { - amount: BigInt(400), - formattedAmount: '400', - vaultId: BigInt(1), - token: { - id: 'output_token', - address: '0xoutput_token', - name: 'output_token', - symbol: 'output_token', - decimals: BigInt(1) - } as unknown as RaindexVaultToken, - newBalance: BigInt(0), - formattedNewBalance: '0', - oldBalance: BigInt(0), - formattedOldBalance: '0', - timestamp: BigInt(0), - transaction: { - id: 'transaction_id', - from: '0xsender_address', - timestamp: BigInt(1632000000), - blockNumber: BigInt(0) - } as unknown as RaindexTransaction, - raindex: '0x1' - } as unknown as RaindexVaultBalanceChange, - orderHash: 'orderHash', - inputVaultBalanceChange: { - vaultId: BigInt(1), - token: { - id: 'output_token_id', - address: '0xoutput_token', - name: 'output_token', - symbol: 'output_token', - decimals: BigInt(1) - } as unknown as RaindexVaultToken, - amount: BigInt(50), - formattedAmount: '50', - newBalance: BigInt(0), - formattedNewBalance: '0', - oldBalance: BigInt(0), - formattedOldBalance: '0', - timestamp: BigInt(0), - transaction: { - id: 'transaction_id', - from: '0xsender_address', - timestamp: BigInt(1632000000), - blockNumber: BigInt(0) - } as unknown as RaindexTransaction, - raindex: '0x1' - } as unknown as RaindexVaultBalanceChange, - raindex: '0x00' - } as unknown as RaindexTrade - ]; + it("handles the case where multiple trades have the same timestamp", () => { + const takeOrderEntities: RaindexTrade[] = [ + { + id: "1", + timestamp: BigInt(1632000000), + transaction: { + id: "transaction_id", + from: "0xsender_address", + timestamp: BigInt(1632000000), + blockNumber: BigInt(0), + } as unknown as RaindexTransaction, + outputVaultBalanceChange: { + amount: BigInt(100), + formattedAmount: "100", + vaultId: BigInt(1), + token: { + id: "output_token", + address: "0xoutput_token", + name: "output_token", + symbol: "output_token", + decimals: BigInt(1), + } as unknown as RaindexVaultToken, + newBalance: BigInt(0), + formattedNewBalance: "0", + oldBalance: BigInt(0), + formattedOldBalance: "0", + timestamp: BigInt(0), + transaction: { + id: "transaction_id", + from: "0xsender_address", + timestamp: BigInt(1632000000), + blockNumber: BigInt(0), + } as unknown as RaindexTransaction, + __typename: "Withdraw", + raindex: "0x1", + } as unknown as RaindexVaultBalanceChange, + orderHash: "orderHash", + inputVaultBalanceChange: { + vaultId: BigInt(1), + token: { + id: "output_token", + address: "0xoutput_token", + name: "output_token", + symbol: "output_token", + decimals: BigInt(1), + } as unknown as RaindexVaultToken, + amount: BigInt(50), + formattedAmount: "50", + newBalance: BigInt(0), + formattedNewBalance: "0", + oldBalance: BigInt(0), + formattedOldBalance: "0", + timestamp: BigInt(0), + transaction: { + id: "transaction_id", + from: "0xsender_address", + timestamp: BigInt(1632000000), + blockNumber: BigInt(0), + } as unknown as RaindexTransaction, + raindex: "0x1", + } as unknown as RaindexVaultBalanceChange, + raindex: "0x00", + } as unknown as RaindexTrade, + { + id: "2", + timestamp: BigInt(1632000000), + transaction: { + id: "transaction_id", + from: "0xsender_address", + timestamp: BigInt(1632000000), + blockNumber: BigInt(0), + } as unknown as RaindexTransaction, + outputVaultBalanceChange: { + amount: BigInt(200), + formattedAmount: "200", + vaultId: BigInt(1), + token: { + id: "output_token", + address: "0xoutput_token", + name: "output_token", + symbol: "output_token", + decimals: BigInt(1), + } as unknown as RaindexVaultToken, + newBalance: BigInt(0), + formattedNewBalance: "0", + oldBalance: BigInt(0), + formattedOldBalance: "0", + timestamp: BigInt(0), + transaction: { + id: "transaction_id", + from: "0xsender_address", + timestamp: BigInt(1632000000), + blockNumber: BigInt(0), + } as unknown as RaindexTransaction, + raindex: "0x1", + } as unknown as RaindexVaultBalanceChange, + orderHash: "orderHash", + inputVaultBalanceChange: { + vaultId: BigInt(1), + token: { + id: "output_token", + address: "0xoutput_token", + name: "output_token", + symbol: "output_token", + decimals: BigInt(1), + } as unknown as RaindexVaultToken, + amount: BigInt(50), + formattedAmount: "50", + newBalance: BigInt(0), + formattedNewBalance: "0", + oldBalance: BigInt(0), + formattedOldBalance: "0", + timestamp: BigInt(0), + transaction: { + id: "transaction_id", + from: "0xsender_address", + timestamp: BigInt(1632000000), + blockNumber: BigInt(0), + } as unknown as RaindexTransaction, + raindex: "0x1", + } as unknown as RaindexVaultBalanceChange, + raindex: "0x00", + } as unknown as RaindexTrade, + { + id: "3", + timestamp: BigInt(1632000000), + transaction: { + id: "transaction_id", + from: "0xsender_address", + timestamp: BigInt(1632000000), + blockNumber: BigInt(0), + } as unknown as RaindexTransaction, + outputVaultBalanceChange: { + amount: BigInt(400), + formattedAmount: "400", + vaultId: BigInt(1), + token: { + id: "output_token", + address: "0xoutput_token", + name: "output_token", + symbol: "output_token", + decimals: BigInt(1), + } as unknown as RaindexVaultToken, + newBalance: BigInt(0), + formattedNewBalance: "0", + oldBalance: BigInt(0), + formattedOldBalance: "0", + timestamp: BigInt(0), + transaction: { + id: "transaction_id", + from: "0xsender_address", + timestamp: BigInt(1632000000), + blockNumber: BigInt(0), + } as unknown as RaindexTransaction, + raindex: "0x1", + } as unknown as RaindexVaultBalanceChange, + orderHash: "orderHash", + inputVaultBalanceChange: { + vaultId: BigInt(1), + token: { + id: "output_token_id", + address: "0xoutput_token", + name: "output_token", + symbol: "output_token", + decimals: BigInt(1), + } as unknown as RaindexVaultToken, + amount: BigInt(50), + formattedAmount: "50", + newBalance: BigInt(0), + formattedNewBalance: "0", + oldBalance: BigInt(0), + formattedOldBalance: "0", + timestamp: BigInt(0), + transaction: { + id: "transaction_id", + from: "0xsender_address", + timestamp: BigInt(1632000000), + blockNumber: BigInt(0), + } as unknown as RaindexTransaction, + raindex: "0x1", + } as unknown as RaindexVaultBalanceChange, + raindex: "0x00", + } as unknown as RaindexTrade, + ]; - const result = prepareHistoricalOrderChartData(takeOrderEntities, 'dark'); + const result = prepareHistoricalOrderChartData(takeOrderEntities, "dark"); - // calculate the weighted average of the ioratio values - const ioratioSum = 0.5 * 100 + 0.25 * 200 + 0.125 * 400; - const outputAmountSum = 100 + 200 + 400; - const ioratioAverage = ioratioSum / outputAmountSum; + // calculate the weighted average of the ioratio values + const ioratioSum = 0.5 * 100 + 0.25 * 200 + 0.125 * 400; + const outputAmountSum = 100 + 200 + 400; + const ioratioAverage = ioratioSum / outputAmountSum; - expect(result.length).toEqual(1); - expect(result[0].value).toEqual(ioratioAverage); - }); + expect(result.length).toEqual(1); + expect(result[0].value).toEqual(ioratioAverage); + }); } diff --git a/packages/ui-components/src/lib/services/index.ts b/packages/ui-components/src/lib/services/index.ts index b9a5cdf5a6..c71e330b8f 100644 --- a/packages/ui-components/src/lib/services/index.ts +++ b/packages/ui-components/src/lib/services/index.ts @@ -1,3 +1,7 @@ -export { fetchParseRegistry, fetchRegistryDotrains, validateOrders } from './registry'; -export { loadRegistryUrl } from './loadRegistryUrl'; -export type { RegistryDotrain, RegistryFile } from './registry'; +export { + fetchParseRegistry, + fetchRegistryDotrains, + validateOrders, +} from "./registry"; +export { loadRegistryUrl } from "./loadRegistryUrl"; +export type { RegistryDotrain, RegistryFile } from "./registry"; diff --git a/packages/ui-components/src/lib/services/loadRegistryUrl.ts b/packages/ui-components/src/lib/services/loadRegistryUrl.ts index 8fd78c6d15..5809968146 100644 --- a/packages/ui-components/src/lib/services/loadRegistryUrl.ts +++ b/packages/ui-components/src/lib/services/loadRegistryUrl.ts @@ -1,27 +1,28 @@ -import { RegistryManager } from '../providers/registry/RegistryManager'; -import { DotrainRegistry } from '@rainlanguage/raindex'; +import { RegistryManager } from "../providers/registry/RegistryManager"; +import { DotrainRegistry } from "@rainlanguage/raindex"; export async function loadRegistryUrl( - url: string, - registryManager: RegistryManager + url: string, + registryManager: RegistryManager, ): Promise { - if (!url) { - throw new Error('No URL provided'); - } + if (!url) { + throw new Error("No URL provided"); + } - if (!registryManager) { - throw new Error('Registry manager is required'); - } + if (!registryManager) { + throw new Error("Registry manager is required"); + } - try { - const validationResult = await DotrainRegistry.validate(url); - if (validationResult.error) { - throw new Error(validationResult.error.readableMsg); - } - registryManager.setRegistry(url); - window.location.reload(); - } catch (e) { - const errorMessage = e instanceof Error ? e.message : 'Failed to update registry URL'; - throw new Error(errorMessage); - } + try { + const validationResult = await DotrainRegistry.validate(url); + if (validationResult.error) { + throw new Error(validationResult.error.readableMsg); + } + registryManager.setRegistry(url); + window.location.reload(); + } catch (e) { + const errorMessage = + e instanceof Error ? e.message : "Failed to update registry URL"; + throw new Error(errorMessage); + } } diff --git a/packages/ui-components/src/lib/services/pairTradesChartData.ts b/packages/ui-components/src/lib/services/pairTradesChartData.ts index 3951602a99..a72a7eef9a 100644 --- a/packages/ui-components/src/lib/services/pairTradesChartData.ts +++ b/packages/ui-components/src/lib/services/pairTradesChartData.ts @@ -1,7 +1,11 @@ -import type { RaindexTrade, RaindexVaultToken } from '@rainlanguage/raindex'; -import type { UTCTimestamp } from 'lightweight-charts'; -import { sortBy } from 'lodash'; -import { TIME_DELTA_24_HOURS, TIME_DELTA_7_DAYS, TIME_DELTA_30_DAYS } from './time'; +import type { RaindexTrade, RaindexVaultToken } from "@rainlanguage/raindex"; +import type { UTCTimestamp } from "lightweight-charts"; +import { sortBy } from "lodash"; +import { + TIME_DELTA_24_HOURS, + TIME_DELTA_7_DAYS, + TIME_DELTA_30_DAYS, +} from "./time"; export const BUCKET_SECONDS_24_HOURS = 900; export const BUCKET_SECONDS_7_DAYS = 3600; @@ -9,255 +13,280 @@ export const BUCKET_SECONDS_30_DAYS = 14400; export const BUCKET_SECONDS_1_YEAR = 86400; export const CHART_COLORS = { - BUY_VOLUME: '#26a69a', - BUY_VOLUME_TRANSPARENT: 'rgba(38, 166, 154, 0.5)', - SELL_VOLUME: '#ef5350', - SELL_VOLUME_TRANSPARENT: 'rgba(239, 83, 80, 0.5)', - PRICE_LINE: '#5c6bc0', - ZERO_LINE: '#888888' + BUY_VOLUME: "#26a69a", + BUY_VOLUME_TRANSPARENT: "rgba(38, 166, 154, 0.5)", + SELL_VOLUME: "#ef5350", + SELL_VOLUME_TRANSPARENT: "rgba(239, 83, 80, 0.5)", + PRICE_LINE: "#5c6bc0", + ZERO_LINE: "#888888", } as const; export function getBucketSecondsForTimeDelta(timeDeltaSeconds: number): number { - if (timeDeltaSeconds <= TIME_DELTA_24_HOURS) return BUCKET_SECONDS_24_HOURS; - if (timeDeltaSeconds <= TIME_DELTA_7_DAYS) return BUCKET_SECONDS_7_DAYS; - if (timeDeltaSeconds <= TIME_DELTA_30_DAYS) return BUCKET_SECONDS_30_DAYS; - return BUCKET_SECONDS_1_YEAR; + if (timeDeltaSeconds <= TIME_DELTA_24_HOURS) return BUCKET_SECONDS_24_HOURS; + if (timeDeltaSeconds <= TIME_DELTA_7_DAYS) return BUCKET_SECONDS_7_DAYS; + if (timeDeltaSeconds <= TIME_DELTA_30_DAYS) return BUCKET_SECONDS_30_DAYS; + return BUCKET_SECONDS_1_YEAR; } export type TradingPair = { - baseToken: RaindexVaultToken; - quoteToken: RaindexVaultToken; + baseToken: RaindexVaultToken; + quoteToken: RaindexVaultToken; }; export type PricePoint = { - time: UTCTimestamp; - value: number; + time: UTCTimestamp; + value: number; }; export type VolumePoint = { - time: UTCTimestamp; - value: number; - color?: string; + time: UTCTimestamp; + value: number; + color?: string; }; export type PairTradesChartData = { - pricePoints: PricePoint[]; - buyVolumePoints: VolumePoint[]; - sellVolumePoints: VolumePoint[]; + pricePoints: PricePoint[]; + buyVolumePoints: VolumePoint[]; + sellVolumePoints: VolumePoint[]; }; type TradeAmounts = { - baseAmount: number; - quoteAmount: number; - isBuy: boolean; + baseAmount: number; + quoteAmount: number; + isBuy: boolean; }; -function getTokenAddressLower(trade: RaindexTrade, which: 'in' | 'out'): string { - const change = which === 'in' ? trade.inputVaultBalanceChange : trade.outputVaultBalanceChange; - return change.token.address.toLowerCase(); +function getTokenAddressLower( + trade: RaindexTrade, + which: "in" | "out", +): string { + const change = + which === "in" + ? trade.inputVaultBalanceChange + : trade.outputVaultBalanceChange; + return change.token.address.toLowerCase(); } function tradeMatchesPair( - trade: RaindexTrade, - baseTokenAddress: string, - quoteTokenAddress: string + trade: RaindexTrade, + baseTokenAddress: string, + quoteTokenAddress: string, ): boolean { - const inAddr = getTokenAddressLower(trade, 'in'); - const outAddr = getTokenAddressLower(trade, 'out'); - const baseLower = baseTokenAddress.toLowerCase(); - const quoteLower = quoteTokenAddress.toLowerCase(); - - return ( - (inAddr === baseLower && outAddr === quoteLower) || - (inAddr === quoteLower && outAddr === baseLower) - ); + const inAddr = getTokenAddressLower(trade, "in"); + const outAddr = getTokenAddressLower(trade, "out"); + const baseLower = baseTokenAddress.toLowerCase(); + const quoteLower = quoteTokenAddress.toLowerCase(); + + return ( + (inAddr === baseLower && outAddr === quoteLower) || + (inAddr === quoteLower && outAddr === baseLower) + ); } -function getTradeAmounts(trade: RaindexTrade, baseTokenAddress: string): TradeAmounts | null { - const inAddr = getTokenAddressLower(trade, 'in'); - const baseLower = baseTokenAddress.toLowerCase(); +function getTradeAmounts( + trade: RaindexTrade, + baseTokenAddress: string, +): TradeAmounts | null { + const inAddr = getTokenAddressLower(trade, "in"); + const baseLower = baseTokenAddress.toLowerCase(); - const inFormattedAmount = trade.inputVaultBalanceChange.formattedAmount; - const outFormattedAmount = trade.outputVaultBalanceChange.formattedAmount; + const inFormattedAmount = trade.inputVaultBalanceChange.formattedAmount; + const outFormattedAmount = trade.outputVaultBalanceChange.formattedAmount; - const inAmt = Math.abs(parseFloat(inFormattedAmount)); - const outAmt = Math.abs(parseFloat(outFormattedAmount)); + const inAmt = Math.abs(parseFloat(inFormattedAmount)); + const outAmt = Math.abs(parseFloat(outFormattedAmount)); - if (!Number.isFinite(inAmt) || !Number.isFinite(outAmt)) return null; + if (!Number.isFinite(inAmt) || !Number.isFinite(outAmt)) return null; - const isBuy = inAddr === baseLower; + const isBuy = inAddr === baseLower; - return { - baseAmount: isBuy ? inAmt : outAmt, - quoteAmount: isBuy ? outAmt : inAmt, - isBuy - }; + return { + baseAmount: isBuy ? inAmt : outAmt, + quoteAmount: isBuy ? outAmt : inAmt, + isBuy, + }; } export function extractPairsFromTrades(trades: RaindexTrade[]): TradingPair[] { - const pairMap = new Map(); + const pairMap = new Map(); - for (const trade of trades) { - const inToken = trade.inputVaultBalanceChange.token; - const outToken = trade.outputVaultBalanceChange.token; + for (const trade of trades) { + const inToken = trade.inputVaultBalanceChange.token; + const outToken = trade.outputVaultBalanceChange.token; - const inAddr = inToken.address.toLowerCase(); - const outAddr = outToken.address.toLowerCase(); + const inAddr = inToken.address.toLowerCase(); + const outAddr = outToken.address.toLowerCase(); - const [firstAddr, secondAddr] = inAddr < outAddr ? [inAddr, outAddr] : [outAddr, inAddr]; - const pairKey = `${firstAddr}-${secondAddr}`; + const [firstAddr, secondAddr] = + inAddr < outAddr ? [inAddr, outAddr] : [outAddr, inAddr]; + const pairKey = `${firstAddr}-${secondAddr}`; - if (!pairMap.has(pairKey)) { - const [baseToken, quoteToken] = inAddr < outAddr ? [inToken, outToken] : [outToken, inToken]; - pairMap.set(pairKey, { baseToken, quoteToken }); - } - } + if (!pairMap.has(pairKey)) { + const [baseToken, quoteToken] = + inAddr < outAddr ? [inToken, outToken] : [outToken, inToken]; + pairMap.set(pairKey, { baseToken, quoteToken }); + } + } - return Array.from(pairMap.values()); + return Array.from(pairMap.values()); } export function getDefaultPair(trades: RaindexTrade[]): TradingPair | null { - if (trades.length === 0) return null; + if (trades.length === 0) return null; - const sortedTrades = sortBy(trades, (t) => Number(t.timestamp)); - const oldestTrade = sortedTrades[0]; - const inToken = oldestTrade.inputVaultBalanceChange.token; - const outToken = oldestTrade.outputVaultBalanceChange.token; + const sortedTrades = sortBy(trades, (t) => Number(t.timestamp)); + const oldestTrade = sortedTrades[0]; + const inToken = oldestTrade.inputVaultBalanceChange.token; + const outToken = oldestTrade.outputVaultBalanceChange.token; - const inAddr = inToken.address.toLowerCase(); - const outAddr = outToken.address.toLowerCase(); + const inAddr = inToken.address.toLowerCase(); + const outAddr = outToken.address.toLowerCase(); - if (inAddr < outAddr) { - return { baseToken: inToken, quoteToken: outToken }; - } else { - return { baseToken: outToken, quoteToken: inToken }; - } + if (inAddr < outAddr) { + return { baseToken: inToken, quoteToken: outToken }; + } else { + return { baseToken: outToken, quoteToken: inToken }; + } } export function getTokenLabel(token: RaindexVaultToken): string { - if (token.symbol && token.symbol.trim() !== '') { - return token.symbol; - } - const addr = token.address; - if (addr.length >= 10) { - return `${addr.slice(0, 6)}...${addr.slice(-4)}`; - } - return addr; + if (token.symbol && token.symbol.trim() !== "") { + return token.symbol; + } + const addr = token.address; + if (addr.length >= 10) { + return `${addr.slice(0, 6)}...${addr.slice(-4)}`; + } + return addr; } export function pairsAreEqual(pairA: TradingPair, pairB: TradingPair): boolean { - return ( - pairA.baseToken.address.toLowerCase() === pairB.baseToken.address.toLowerCase() && - pairA.quoteToken.address.toLowerCase() === pairB.quoteToken.address.toLowerCase() - ); + return ( + pairA.baseToken.address.toLowerCase() === + pairB.baseToken.address.toLowerCase() && + pairA.quoteToken.address.toLowerCase() === + pairB.quoteToken.address.toLowerCase() + ); } -export function findPairIndex(pairs: TradingPair[], targetPair: TradingPair): number { - return pairs.findIndex((p) => pairsAreEqual(p, targetPair)); +export function findPairIndex( + pairs: TradingPair[], + targetPair: TradingPair, +): number { + return pairs.findIndex((p) => pairsAreEqual(p, targetPair)); } export function flipTradingPair(pair: TradingPair): TradingPair { - return { - baseToken: pair.quoteToken, - quoteToken: pair.baseToken - }; + return { + baseToken: pair.quoteToken, + quoteToken: pair.baseToken, + }; } -export function formatChartTimestamp(timestampSeconds: number, timeDeltaSeconds: number): string { - const date = new Date(timestampSeconds * 1000); - const day = date.getDate(); - const month = date.toLocaleString('en-US', { month: 'short' }); - const hours = date.getHours().toString().padStart(2, '0'); - const minutes = date.getMinutes().toString().padStart(2, '0'); - - if (timeDeltaSeconds <= TIME_DELTA_24_HOURS) { - return `${month} ${day} ${hours}:${minutes}`; - } else if (timeDeltaSeconds <= TIME_DELTA_7_DAYS) { - return `${month} ${day} ${hours}:00`; - } else { - return `${month} ${day}`; - } +export function formatChartTimestamp( + timestampSeconds: number, + timeDeltaSeconds: number, +): string { + const date = new Date(timestampSeconds * 1000); + const day = date.getDate(); + const month = date.toLocaleString("en-US", { month: "short" }); + const hours = date.getHours().toString().padStart(2, "0"); + const minutes = date.getMinutes().toString().padStart(2, "0"); + + if (timeDeltaSeconds <= TIME_DELTA_24_HOURS) { + return `${month} ${day} ${hours}:${minutes}`; + } else if (timeDeltaSeconds <= TIME_DELTA_7_DAYS) { + return `${month} ${day} ${hours}:00`; + } else { + return `${month} ${day}`; + } } export type TransformPairTradesInput = { - trades: RaindexTrade[]; - baseTokenAddress: string; - quoteTokenAddress: string; - timeDeltaSeconds: number; + trades: RaindexTrade[]; + baseTokenAddress: string; + quoteTokenAddress: string; + timeDeltaSeconds: number; }; -export function transformPairTrades(input: TransformPairTradesInput): PairTradesChartData { - const { trades, baseTokenAddress, quoteTokenAddress, timeDeltaSeconds } = input; - const bucketSeconds = getBucketSecondsForTimeDelta(timeDeltaSeconds); - - const now = Math.floor(Date.now() / 1000); - const cutoff = now - timeDeltaSeconds; - - const filteredTrades = trades.filter((trade) => { - const ts = Number(trade.timestamp); - if (ts < cutoff || ts > now) return false; - return tradeMatchesPair(trade, baseTokenAddress, quoteTokenAddress); - }); - - const priceAggregator = new Map(); - const buyVolumeBuckets = new Map(); - const sellVolumeBuckets = new Map(); - - for (const trade of filteredTrades) { - const amounts = getTradeAmounts(trade, baseTokenAddress); - if (!amounts) continue; - - const { baseAmount, quoteAmount, isBuy } = amounts; - - if (baseAmount === 0) continue; - - const ts = Number(trade.timestamp); - - const existing = priceAggregator.get(ts); - if (existing) { - priceAggregator.set(ts, { - sumBase: existing.sumBase + baseAmount, - sumQuote: existing.sumQuote + quoteAmount - }); - } else { - priceAggregator.set(ts, { sumBase: baseAmount, sumQuote: quoteAmount }); - } - - const bucketTime = Math.floor(ts / bucketSeconds) * bucketSeconds; - const volumeMap = isBuy ? buyVolumeBuckets : sellVolumeBuckets; - const existingVol = volumeMap.get(bucketTime) ?? 0; - volumeMap.set(bucketTime, existingVol + baseAmount); - } - - const pricePoints: PricePoint[] = []; - for (const [ts, agg] of priceAggregator.entries()) { - if (agg.sumBase === 0) continue; - const price = agg.sumQuote / agg.sumBase; - if (!Number.isFinite(price)) continue; - pricePoints.push({ time: ts as UTCTimestamp, value: price }); - } - - const buyVolumePoints: VolumePoint[] = []; - for (const [bucketTime, vol] of buyVolumeBuckets.entries()) { - buyVolumePoints.push({ - time: bucketTime as UTCTimestamp, - value: vol, - color: CHART_COLORS.BUY_VOLUME - }); - } - - const sellVolumePoints: VolumePoint[] = []; - for (const [bucketTime, vol] of sellVolumeBuckets.entries()) { - sellVolumePoints.push({ - time: bucketTime as UTCTimestamp, - value: -vol, - color: CHART_COLORS.SELL_VOLUME - }); - } - - return { - pricePoints: sortBy(pricePoints, (p) => p.time), - buyVolumePoints: sortBy(buyVolumePoints, (p) => p.time), - sellVolumePoints: sortBy(sellVolumePoints, (p) => p.time) - }; +export function transformPairTrades( + input: TransformPairTradesInput, +): PairTradesChartData { + const { trades, baseTokenAddress, quoteTokenAddress, timeDeltaSeconds } = + input; + const bucketSeconds = getBucketSecondsForTimeDelta(timeDeltaSeconds); + + const now = Math.floor(Date.now() / 1000); + const cutoff = now - timeDeltaSeconds; + + const filteredTrades = trades.filter((trade) => { + const ts = Number(trade.timestamp); + if (ts < cutoff || ts > now) return false; + return tradeMatchesPair(trade, baseTokenAddress, quoteTokenAddress); + }); + + const priceAggregator = new Map< + number, + { sumBase: number; sumQuote: number } + >(); + const buyVolumeBuckets = new Map(); + const sellVolumeBuckets = new Map(); + + for (const trade of filteredTrades) { + const amounts = getTradeAmounts(trade, baseTokenAddress); + if (!amounts) continue; + + const { baseAmount, quoteAmount, isBuy } = amounts; + + if (baseAmount === 0) continue; + + const ts = Number(trade.timestamp); + + const existing = priceAggregator.get(ts); + if (existing) { + priceAggregator.set(ts, { + sumBase: existing.sumBase + baseAmount, + sumQuote: existing.sumQuote + quoteAmount, + }); + } else { + priceAggregator.set(ts, { sumBase: baseAmount, sumQuote: quoteAmount }); + } + + const bucketTime = Math.floor(ts / bucketSeconds) * bucketSeconds; + const volumeMap = isBuy ? buyVolumeBuckets : sellVolumeBuckets; + const existingVol = volumeMap.get(bucketTime) ?? 0; + volumeMap.set(bucketTime, existingVol + baseAmount); + } + + const pricePoints: PricePoint[] = []; + for (const [ts, agg] of priceAggregator.entries()) { + if (agg.sumBase === 0) continue; + const price = agg.sumQuote / agg.sumBase; + if (!Number.isFinite(price)) continue; + pricePoints.push({ time: ts as UTCTimestamp, value: price }); + } + + const buyVolumePoints: VolumePoint[] = []; + for (const [bucketTime, vol] of buyVolumeBuckets.entries()) { + buyVolumePoints.push({ + time: bucketTime as UTCTimestamp, + value: vol, + color: CHART_COLORS.BUY_VOLUME, + }); + } + + const sellVolumePoints: VolumePoint[] = []; + for (const [bucketTime, vol] of sellVolumeBuckets.entries()) { + sellVolumePoints.push({ + time: bucketTime as UTCTimestamp, + value: -vol, + color: CHART_COLORS.SELL_VOLUME, + }); + } + + return { + pricePoints: sortBy(pricePoints, (p) => p.time), + buyVolumePoints: sortBy(buyVolumePoints, (p) => p.time), + sellVolumePoints: sortBy(sellVolumePoints, (p) => p.time), + }; } diff --git a/packages/ui-components/src/lib/services/registry.ts b/packages/ui-components/src/lib/services/registry.ts index cdb75d2e9d..d3a29c2937 100644 --- a/packages/ui-components/src/lib/services/registry.ts +++ b/packages/ui-components/src/lib/services/registry.ts @@ -1,19 +1,19 @@ -import type { InvalidOrderDetail, ValidOrderDetail } from '$lib/types/order'; -import { RaindexOrderBuilder } from '@rainlanguage/raindex'; +import type { InvalidOrderDetail, ValidOrderDetail } from "$lib/types/order"; +import { RaindexOrderBuilder } from "@rainlanguage/raindex"; export type RegistryFile = { - name: string; - url: string; + name: string; + url: string; }; export type RegistryDotrain = { - name: string; - dotrain: string; + name: string; + dotrain: string; }; export interface OrderValidationResult { - validOrders: ValidOrderDetail[]; - invalidOrders: InvalidOrderDetail[]; + validOrders: ValidOrderDetail[]; + invalidOrders: InvalidOrderDetail[]; } /** @@ -29,90 +29,96 @@ export interface OrderValidationResult { * // Returns: [{ name: 'file1', url: 'https://example.com/file1.rain' }, ...] */ -export const fetchParseRegistry = async (url: string): Promise<{ name: string; url: string }[]> => { - try { - const response = await fetch(url); - if (!response.ok) { - throw new Error('Failed to fetch registry.'); - } - const filesList = await response.text(); - const files = filesList - .split('\n') - .filter((line) => line.trim()) - .map((line) => { - const [name, url] = line.split(' '); - return { name, url }; - }); - if (!files) { - throw new Error('Invalid stategy registry.'); - } - return files; - } catch (e) { - throw new Error(e instanceof Error ? e.message : 'Unknown error.'); - } +export const fetchParseRegistry = async ( + url: string, +): Promise<{ name: string; url: string }[]> => { + try { + const response = await fetch(url); + if (!response.ok) { + throw new Error("Failed to fetch registry."); + } + const filesList = await response.text(); + const files = filesList + .split("\n") + .filter((line) => line.trim()) + .map((line) => { + const [name, url] = line.split(" "); + return { name, url }; + }); + if (!files) { + throw new Error("Invalid stategy registry."); + } + return files; + } catch (e) { + throw new Error(e instanceof Error ? e.message : "Unknown error."); + } }; -export const fetchRegistryDotrains = async (url: string): Promise => { - const files = await fetchParseRegistry(url); - const dotrains = await Promise.all( - files.map(async (file) => { - try { - const response = await fetch(file.url); - if (!response.ok) { - throw new Error(`Failed to fetch dotrain for ${file.name}`); - } - const dotrain = await response.text(); - return { name: file.name, dotrain }; - } catch (e) { - throw new Error( - e instanceof Error - ? `Error fetching dotrain for ${file.name}: ${e.message}` - : `Unknown error fetching dotrain for ${file.name}` - ); - } - }) - ); - return dotrains; +export const fetchRegistryDotrains = async ( + url: string, +): Promise => { + const files = await fetchParseRegistry(url); + const dotrains = await Promise.all( + files.map(async (file) => { + try { + const response = await fetch(file.url); + if (!response.ok) { + throw new Error(`Failed to fetch dotrain for ${file.name}`); + } + const dotrain = await response.text(); + return { name: file.name, dotrain }; + } catch (e) { + throw new Error( + e instanceof Error + ? `Error fetching dotrain for ${file.name}: ${e.message}` + : `Unknown error fetching dotrain for ${file.name}`, + ); + } + }), + ); + return dotrains; }; export async function validateOrders( - registryDotrains: RegistryDotrain[] + registryDotrains: RegistryDotrain[], ): Promise { - const ordersPromises = registryDotrains.map(async (registryDotrain) => { - try { - const result = await RaindexOrderBuilder.getOrderDetails(registryDotrain.dotrain); + const ordersPromises = registryDotrains.map(async (registryDotrain) => { + try { + const result = await RaindexOrderBuilder.getOrderDetails( + registryDotrain.dotrain, + ); - if (result.error) { - throw new Error(result.error.msg); - } + if (result.error) { + throw new Error(result.error.msg); + } - return { - valid: true, - data: { - ...registryDotrain, - details: result.value - } - }; - } catch (error) { - return { - valid: false, - data: { - name: registryDotrain.name, - error: error instanceof Error ? error.message : String(error) - } - }; - } - }); + return { + valid: true, + data: { + ...registryDotrain, + details: result.value, + }, + }; + } catch (error) { + return { + valid: false, + data: { + name: registryDotrain.name, + error: error instanceof Error ? error.message : String(error), + }, + }; + } + }); - const ordersResults = await Promise.all(ordersPromises); + const ordersResults = await Promise.all(ordersPromises); - const validOrders = ordersResults - .filter((result) => result.valid) - .map((result) => result.data as ValidOrderDetail); + const validOrders = ordersResults + .filter((result) => result.valid) + .map((result) => result.data as ValidOrderDetail); - const invalidOrders = ordersResults - .filter((result) => !result.valid) - .map((result) => result.data as InvalidOrderDetail); + const invalidOrders = ordersResults + .filter((result) => !result.valid) + .map((result) => result.data as InvalidOrderDetail); - return { validOrders, invalidOrders }; + return { validOrders, invalidOrders }; } diff --git a/packages/ui-components/src/lib/services/time.ts b/packages/ui-components/src/lib/services/time.ts index 24bc292c14..3478aee7d2 100644 --- a/packages/ui-components/src/lib/services/time.ts +++ b/packages/ui-components/src/lib/services/time.ts @@ -1,8 +1,8 @@ -import dayjs from 'dayjs'; -import bigIntSupport from 'dayjs/plugin/bigIntSupport'; -import localizedFormat from 'dayjs/plugin/localizedFormat'; -import type { UTCTimestamp } from 'lightweight-charts'; -import utc from 'dayjs/plugin/utc'; +import dayjs from "dayjs"; +import bigIntSupport from "dayjs/plugin/bigIntSupport"; +import localizedFormat from "dayjs/plugin/localizedFormat"; +import type { UTCTimestamp } from "lightweight-charts"; +import utc from "dayjs/plugin/utc"; dayjs.extend(bigIntSupport); dayjs.extend(localizedFormat); dayjs.extend(utc); @@ -14,17 +14,17 @@ export const TIME_DELTA_30_DAYS = TIME_DELTA_24_HOURS * 30; export const TIME_DELTA_1_YEAR = TIME_DELTA_24_HOURS * 365; export function dateTimestamp(date: Date): number { - return Math.floor(date.getTime() / 1000); + return Math.floor(date.getTime() / 1000); } export function formatTimestampSecondsAsLocal(timestampSeconds: bigint) { - return dayjs(timestampSeconds * BigInt('1000')) - .utc() - .format('L LT'); + return dayjs(timestampSeconds * BigInt("1000")) + .utc() + .format("L LT"); } export function timestampSecondsToUTCTimestamp(timestampSeconds: bigint) { - return dayjs(timestampSeconds * BigInt('1000')).unix() as UTCTimestamp; + return dayjs(timestampSeconds * BigInt("1000")).unix() as UTCTimestamp; } /** @@ -36,87 +36,93 @@ export function timestampSecondsToUTCTimestamp(timestampSeconds: bigint) { * if the time runs out before the main promise settlement */ export async function promiseTimeout( - promise: Promise, - time: number, - exception: unknown + promise: Promise, + time: number, + exception: unknown, ): Promise { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let timeout: any; - return Promise.race([ - promise, - new Promise((_resolve, reject) => (timeout = setTimeout(reject, time, exception))) as Promise - ]).finally(() => clearTimeout(timeout)); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let timeout: any; + return Promise.race([ + promise, + new Promise( + (_resolve, reject) => (timeout = setTimeout(reject, time, exception)), + ) as Promise, + ]).finally(() => clearTimeout(timeout)); } if (import.meta.vitest) { - const { describe, it, expect, vi } = import.meta.vitest; - - describe('Date and timestamp utilities', () => { - describe('formatTimestampSecondsAsLocal', () => { - it('converts timestamp to local format', () => { - const result = formatTimestampSecondsAsLocal(BigInt('1672531200')); // Jan 1, 2023 12:00 AM - expect(result).toBe('01/01/2023 12:00 AM'); - }); - }); - - describe('timestampSecondsToUTCTimestamp', () => { - it('converts bigint timestamp to UTCTimestamp', () => { - const result = timestampSecondsToUTCTimestamp(BigInt('1672531200')); - expect(result).toBe(1672531200); - }); - }); - }); - - describe('promiseTimeout', () => { - it('resolves when promise resolves before timeout', async () => { - const testValue = 'test'; - const promise = Promise.resolve(testValue); - const result = await promiseTimeout(promise, 100, new Error('Timeout')); - expect(result).toBe(testValue); - }); - - it('rejects when promise times out', async () => { - const promise = new Promise((resolve) => setTimeout(resolve, 200)); - const exception = new Error('Timeout'); - - await expect(promiseTimeout(promise, 100, exception)).rejects.toThrow(exception); - }); - - it('rejects when original promise rejects', async () => { - const error = new Error('Original rejection'); - const promise = Promise.reject(error); - - await expect(promiseTimeout(promise, 100, new Error('Timeout'))).rejects.toThrow(error); - }); - - it('clears timeout after promise resolution', async () => { - vi.spyOn(global, 'clearTimeout'); - const promise = Promise.resolve('test'); - await promiseTimeout(promise, 100, new Error('Timeout')); - - expect(clearTimeout).toHaveBeenCalled(); - }); - - it('clears timeout after promise rejection', async () => { - vi.spyOn(global, 'clearTimeout'); - const promise = Promise.reject(new Error('Original rejection')); - - try { - await promiseTimeout(promise, 100, new Error('Timeout')); - } catch { - // Ignore the error - } - - expect(clearTimeout).toHaveBeenCalled(); - }); - }); - describe('dateTimestamp', () => { - it('should get date timestamp in seconds', () => { - const date = new Date(2022, 1, 16, 17, 32, 11, 168); - const result = dateTimestamp(date); - const expected = Math.floor(date.getTime() / 1000); - - expect(result).toEqual(expected); - }); - }); + const { describe, it, expect, vi } = import.meta.vitest; + + describe("Date and timestamp utilities", () => { + describe("formatTimestampSecondsAsLocal", () => { + it("converts timestamp to local format", () => { + const result = formatTimestampSecondsAsLocal(BigInt("1672531200")); // Jan 1, 2023 12:00 AM + expect(result).toBe("01/01/2023 12:00 AM"); + }); + }); + + describe("timestampSecondsToUTCTimestamp", () => { + it("converts bigint timestamp to UTCTimestamp", () => { + const result = timestampSecondsToUTCTimestamp(BigInt("1672531200")); + expect(result).toBe(1672531200); + }); + }); + }); + + describe("promiseTimeout", () => { + it("resolves when promise resolves before timeout", async () => { + const testValue = "test"; + const promise = Promise.resolve(testValue); + const result = await promiseTimeout(promise, 100, new Error("Timeout")); + expect(result).toBe(testValue); + }); + + it("rejects when promise times out", async () => { + const promise = new Promise((resolve) => setTimeout(resolve, 200)); + const exception = new Error("Timeout"); + + await expect(promiseTimeout(promise, 100, exception)).rejects.toThrow( + exception, + ); + }); + + it("rejects when original promise rejects", async () => { + const error = new Error("Original rejection"); + const promise = Promise.reject(error); + + await expect( + promiseTimeout(promise, 100, new Error("Timeout")), + ).rejects.toThrow(error); + }); + + it("clears timeout after promise resolution", async () => { + vi.spyOn(global, "clearTimeout"); + const promise = Promise.resolve("test"); + await promiseTimeout(promise, 100, new Error("Timeout")); + + expect(clearTimeout).toHaveBeenCalled(); + }); + + it("clears timeout after promise rejection", async () => { + vi.spyOn(global, "clearTimeout"); + const promise = Promise.reject(new Error("Original rejection")); + + try { + await promiseTimeout(promise, 100, new Error("Timeout")); + } catch { + // Ignore the error + } + + expect(clearTimeout).toHaveBeenCalled(); + }); + }); + describe("dateTimestamp", () => { + it("should get date timestamp in seconds", () => { + const date = new Date(2022, 1, 16, 17, 32, 11, 168); + const result = dateTimestamp(date); + const expected = Math.floor(date.getTime() / 1000); + + expect(result).toEqual(expected); + }); + }); } diff --git a/packages/ui-components/src/lib/storesGeneric/cachedWritableStore.ts b/packages/ui-components/src/lib/storesGeneric/cachedWritableStore.ts index 760cb7bf4f..38a32c8010 100644 --- a/packages/ui-components/src/lib/storesGeneric/cachedWritableStore.ts +++ b/packages/ui-components/src/lib/storesGeneric/cachedWritableStore.ts @@ -1,4 +1,4 @@ -import { writable } from 'svelte/store'; +import { writable } from "svelte/store"; /** * Creates a writable Svelte store that persists its value to localStorage. @@ -28,58 +28,58 @@ import { writable } from 'svelte/store'; * ); */ export function cachedWritableStore( - key: string, - defaultValue: T, - serialize: (value: T) => string, - deserialize: (serialized: string) => T + key: string, + defaultValue: T, + serialize: (value: T) => string, + deserialize: (serialized: string) => T, ) { - const getCache = () => { - try { - const cached = localStorage.getItem(key); - return cached !== null ? deserialize(cached) : defaultValue; - } catch { - return defaultValue; - } - }; - const setCache = (value?: T) => { - try { - if (value !== undefined) { - localStorage.setItem(key, serialize(value)); - } else { - localStorage.removeItem(key); - } - } catch { - // Silently ignore localStorage errors to allow the application to function - // without persistence in environments where localStorage is unavailable - } - }; + const getCache = () => { + try { + const cached = localStorage.getItem(key); + return cached !== null ? deserialize(cached) : defaultValue; + } catch { + return defaultValue; + } + }; + const setCache = (value?: T) => { + try { + if (value !== undefined) { + localStorage.setItem(key, serialize(value)); + } else { + localStorage.removeItem(key); + } + } catch { + // Silently ignore localStorage errors to allow the application to function + // without persistence in environments where localStorage is unavailable + } + }; - const data = writable(getCache()); + const data = writable(getCache()); - data.subscribe((value) => { - setCache(value); - }); + data.subscribe((value) => { + setCache(value); + }); - return data; + return data; } -export const cachedWritableString = (key: string, defaultValue = '') => - cachedWritableStore( - key, - defaultValue, - (v) => v, - (v) => v - ); +export const cachedWritableString = (key: string, defaultValue = "") => + cachedWritableStore( + key, + defaultValue, + (v) => v, + (v) => v, + ); export const cachedWritableInt = (key: string, defaultValue = 0) => - cachedWritableStore( - key, - defaultValue, - (v) => v.toString(), - (v) => { - const parsed = Number.parseInt(v); - return isNaN(parsed) ? defaultValue : parsed; - } - ); + cachedWritableStore( + key, + defaultValue, + (v) => v.toString(), + (v) => { + const parsed = Number.parseInt(v); + return isNaN(parsed) ? defaultValue : parsed; + }, + ); /** * Creates a writable store that can hold an optional value of type T and persists to localStorage. * @@ -91,17 +91,17 @@ export const cachedWritableInt = (key: string, defaultValue = 0) => * @returns A writable store that persists to localStorage and can hold undefined values */ export const cachedWritableOptionalStore = ( - key: string, - defaultValue: T | undefined = undefined, - serialize: (value: T) => string, - deserialize: (serialized: string) => T + key: string, + defaultValue: T | undefined = undefined, + serialize: (value: T) => string, + deserialize: (serialized: string) => T, ) => - cachedWritableStore( - key, - defaultValue, - (v) => (v !== undefined ? serialize(v) : ''), - (v) => (v !== '' ? deserialize(v) : undefined) - ); + cachedWritableStore( + key, + defaultValue, + (v) => (v !== undefined ? serialize(v) : ""), + (v) => (v !== "" ? deserialize(v) : undefined), + ); /** * Creates a writable store that can hold an optional number value and persists to localStorage. @@ -110,16 +110,19 @@ export const cachedWritableOptionalStore = ( * @param {number | undefined} defaultValue - The default value if nothing is found in localStorage * @returns A writable store that persists to localStorage and can hold an optional number */ -export const cachedWritableIntOptional = (key: string, defaultValue = undefined) => - cachedWritableOptionalStore( - key, - defaultValue, - (v) => v.toString(), - (v) => { - const parsed = Number.parseInt(v); - return isNaN(parsed) ? (defaultValue ?? 0) : parsed; - } - ); +export const cachedWritableIntOptional = ( + key: string, + defaultValue = undefined, +) => + cachedWritableOptionalStore( + key, + defaultValue, + (v) => v.toString(), + (v) => { + const parsed = Number.parseInt(v); + return isNaN(parsed) ? (defaultValue ?? 0) : parsed; + }, + ); /** * Creates a writable store that can hold an optional string value and persists to localStorage. @@ -128,10 +131,13 @@ export const cachedWritableIntOptional = (key: string, defaultValue = undefined) * @param {string | undefined} defaultValue - The default value if nothing is found in localStorage * @returns A writable store that persists to localStorage and can hold an optional string */ -export const cachedWritableStringOptional = (key: string, defaultValue = undefined) => - cachedWritableOptionalStore( - key, - defaultValue, - (v) => v, - (v) => v - ); +export const cachedWritableStringOptional = ( + key: string, + defaultValue = undefined, +) => + cachedWritableOptionalStore( + key, + defaultValue, + (v) => v, + (v) => v, + ); diff --git a/packages/ui-components/src/lib/test/matchers.ts b/packages/ui-components/src/lib/test/matchers.ts index e6be01899f..6f3ea96a9a 100644 --- a/packages/ui-components/src/lib/test/matchers.ts +++ b/packages/ui-components/src/lib/test/matchers.ts @@ -1,12 +1,15 @@ -import { expect as vitestExpect } from 'vitest'; -import * as matchers from '@testing-library/jest-dom/matchers'; +import { expect as vitestExpect } from "vitest"; +import * as matchers from "@testing-library/jest-dom/matchers"; vitestExpect.extend(matchers); export const expect = vitestExpect; -declare module 'vitest' { - // vitest instead `@vitest/expect` - // eslint-disable-next-line @typescript-eslint/no-empty-object-type, @typescript-eslint/no-explicit-any - interface JestAssertion - extends matchers.TestingLibraryMatchers, T> {} +declare module "vitest" { + // vitest instead `@vitest/expect` + // eslint-disable-next-line @typescript-eslint/no-empty-object-type, @typescript-eslint/no-explicit-any + interface JestAssertion + extends matchers.TestingLibraryMatchers< + ReturnType, + T + > {} } diff --git a/packages/ui-components/src/lib/types/account.ts b/packages/ui-components/src/lib/types/account.ts index 697c9ad996..4b61d7f006 100644 --- a/packages/ui-components/src/lib/types/account.ts +++ b/packages/ui-components/src/lib/types/account.ts @@ -1,4 +1,4 @@ -import type { Readable } from 'svelte/store'; -import type { Hex } from 'viem'; +import type { Readable } from "svelte/store"; +import type { Hex } from "viem"; export type Account = Readable; diff --git a/packages/ui-components/src/lib/types/appStores.ts b/packages/ui-components/src/lib/types/appStores.ts index 987e1561d3..ad2777e71c 100644 --- a/packages/ui-components/src/lib/types/appStores.ts +++ b/packages/ui-components/src/lib/types/appStores.ts @@ -1,13 +1,13 @@ -import type { Writable } from 'svelte/store'; -import type { Address, Hex } from '@rainlanguage/raindex'; +import type { Writable } from "svelte/store"; +import type { Address, Hex } from "@rainlanguage/raindex"; export interface AppStoresInterface { - selectedChainIds: Writable; - showInactiveOrders: Writable; - orderHash: Writable; - hideZeroBalanceVaults: Writable; - hideInactiveOrdersVaults: Writable; - activeTokens: Writable; - activeRaindexAddresses: Writable; - ownerFilter: Writable
    ; + selectedChainIds: Writable; + showInactiveOrders: Writable; + orderHash: Writable; + hideZeroBalanceVaults: Writable; + hideInactiveOrdersVaults: Writable; + activeTokens: Writable; + activeRaindexAddresses: Writable; + ownerFilter: Writable
    ; } diff --git a/packages/ui-components/src/lib/types/modal.ts b/packages/ui-components/src/lib/types/modal.ts index e9dcbdc8f6..5837d88208 100644 --- a/packages/ui-components/src/lib/types/modal.ts +++ b/packages/ui-components/src/lib/types/modal.ts @@ -1,49 +1,49 @@ -import type { Float, RaindexOrder, RaindexVault } from '@rainlanguage/raindex'; -import type { VaultActionArgs } from './transaction'; -import type { Hex } from 'viem'; +import type { Float, RaindexOrder, RaindexVault } from "@rainlanguage/raindex"; +import type { VaultActionArgs } from "./transaction"; +import type { Hex } from "viem"; export type VaultActionModalProps = { - open: boolean; - args: VaultActionArgs; - onSubmit: (amount: Float) => void; + open: boolean; + args: VaultActionArgs; + onSubmit: (amount: Float) => void; }; export type DisclaimerModalProps = { - open: boolean; - onAccept: () => void; + open: boolean; + onAccept: () => void; }; export type TransactionConfirmationProps = { - open: boolean; - // A title for the modal - modalTitle: string; - // Close the modal after transaction is confirmed (for approvals that precede deposits) - closeOnConfirm?: boolean; - args: { - // Chain ID for switching chains. - chainId: number; - // Address to send the transaction to. - toAddress: Hex; - // Function to call when the transaction is confirmed in wallet. - onConfirm: (hash: Hex) => void; - // Entity to generate calldata for (optional, not used for approval transactions when adding orders). - entity?: RaindexOrder | RaindexVault; - // Calldata for the transaction. - calldata: string; - }; + open: boolean; + // A title for the modal + modalTitle: string; + // Close the modal after transaction is confirmed (for approvals that precede deposits) + closeOnConfirm?: boolean; + args: { + // Chain ID for switching chains. + chainId: number; + // Address to send the transaction to. + toAddress: Hex; + // Function to call when the transaction is confirmed in wallet. + onConfirm: (hash: Hex) => void; + // Entity to generate calldata for (optional, not used for approval transactions when adding orders). + entity?: RaindexOrder | RaindexVault; + // Calldata for the transaction. + calldata: string; + }; }; export type QuoteDebugModalHandler = ( - order: RaindexOrder, - inputIOIndex: number, - outputIOIndex: number, - pair: string, - blockNumber?: bigint + order: RaindexOrder, + inputIOIndex: number, + outputIOIndex: number, + pair: string, + blockNumber?: bigint, ) => void; export type DebugTradeModalHandler = (hash: string, rpcUrls: string[]) => void; export type HandleTransactionConfirmationModal = ( - props: TransactionConfirmationProps, - options?: { timeout?: number } + props: TransactionConfirmationProps, + options?: { timeout?: number }, ) => Promise<{ success: boolean; hash?: string }>; diff --git a/packages/ui-components/src/lib/types/order.ts b/packages/ui-components/src/lib/types/order.ts index 6ed866e242..a1c12bab03 100644 --- a/packages/ui-components/src/lib/types/order.ts +++ b/packages/ui-components/src/lib/types/order.ts @@ -1,12 +1,12 @@ -import type { NameAndDescriptionCfg } from '@rainlanguage/raindex'; +import type { NameAndDescriptionCfg } from "@rainlanguage/raindex"; export type ValidOrderDetail = { - details: NameAndDescriptionCfg; - name: string; - dotrain: string; + details: NameAndDescriptionCfg; + name: string; + dotrain: string; }; export type InvalidOrderDetail = { - name: string; - error: string; + name: string; + error: string; }; diff --git a/packages/ui-components/src/lib/types/toast.ts b/packages/ui-components/src/lib/types/toast.ts index 18aa8b4354..d12cac13c5 100644 --- a/packages/ui-components/src/lib/types/toast.ts +++ b/packages/ui-components/src/lib/types/toast.ts @@ -1,13 +1,13 @@ // Define the Toast interface export interface ToastProps { - message: string; - detail?: string; - type: 'success' | 'error' | 'warning' | 'info'; - color: 'green' | 'red' | 'yellow' | 'blue'; - links?: ToastLink[]; + message: string; + detail?: string; + type: "success" | "error" | "warning" | "info"; + color: "green" | "red" | "yellow" | "blue"; + links?: ToastLink[]; } export type ToastLink = { - link: string; - label: string; + link: string; + label: string; }; diff --git a/packages/ui-components/src/lib/types/tokenBalance.ts b/packages/ui-components/src/lib/types/tokenBalance.ts index 6a47d7d99c..f21f20ebe0 100644 --- a/packages/ui-components/src/lib/types/tokenBalance.ts +++ b/packages/ui-components/src/lib/types/tokenBalance.ts @@ -1,7 +1,7 @@ -import type { AccountBalance } from '@rainlanguage/raindex'; +import type { AccountBalance } from "@rainlanguage/raindex"; export interface TokenBalance { - value: AccountBalance; - loading: boolean; - error: string; + value: AccountBalance; + loading: boolean; + error: string; } diff --git a/packages/ui-components/src/lib/types/transaction.ts b/packages/ui-components/src/lib/types/transaction.ts index 16e5f03bbc..df4f484e31 100644 --- a/packages/ui-components/src/lib/types/transaction.ts +++ b/packages/ui-components/src/lib/types/transaction.ts @@ -1,7 +1,7 @@ -import type { Hex } from 'viem'; -import type { RaindexVault } from '@rainlanguage/raindex'; -import type { ToastLink } from './toast'; -import type { TransactionStoreState } from '$lib/models/Transaction'; +import type { Hex } from "viem"; +import type { RaindexVault } from "@rainlanguage/raindex"; +import type { ToastLink } from "./toast"; +import type { TransactionStoreState } from "$lib/models/Transaction"; /** * Context provided to the indexing function, allowing it to update @@ -9,14 +9,14 @@ import type { TransactionStoreState } from '$lib/models/Transaction'; * knowing the specifics of what's being indexed. */ export type IndexingContext = { - /** Update the transaction state (status, errorDetails, links) */ - updateState: (partialState: Partial) => void; - /** Callback to invoke on successful indexing */ - onSuccess: () => void; - /** Callback to invoke on indexing failure */ - onError: () => void; - /** Current toast links (useful for prepending new links) */ - links: ToastLink[]; + /** Update the transaction state (status, errorDetails, links) */ + updateState: (partialState: Partial) => void; + /** Callback to invoke on successful indexing */ + onSuccess: () => void; + /** Callback to invoke on indexing failure */ + onError: () => void; + /** Current toast links (useful for prepending new links) */ + links: ToastLink[]; }; /** @@ -27,57 +27,57 @@ export type IndexingContext = { export type AwaitIndexingFn = (ctx: IndexingContext) => Promise; export type VaultActionArgs = { - vault: RaindexVault; - onDeposit?: () => void; - account: Hex; + vault: RaindexVault; + onDeposit?: () => void; + account: Hex; }; export enum TransactionName { - REMOVAL = 'Order Removal', - WITHDRAWAL = 'Vault Withdrawal', - WITHDRAWAL_MULTIPLE = 'Vaults Withdrawal', - APPROVAL = 'Token Approval', - DEPOSIT = 'Vault Deposit', - TAKE_ORDER = 'Take Order' + REMOVAL = "Order Removal", + WITHDRAWAL = "Vault Withdrawal", + WITHDRAWAL_MULTIPLE = "Vaults Withdrawal", + APPROVAL = "Token Approval", + DEPOSIT = "Vault Deposit", + TAKE_ORDER = "Take Order", } export enum TransactionStatusMessage { - IDLE = 'Idle', - STARTING = 'Starting transaction...', - CHECKING_ALLOWANCE = 'Checking your allowance...', - PENDING_WALLET = 'Waiting for wallet confirmation...', - PENDING_APPROVAL = 'Approving token spend...', - PENDING_RECEIPT = 'Waiting for transaction receipt...', - PENDING_DEPLOYMENT = 'Deploying your order...', - PENDING_WITHDRAWAL = 'Withdrawing tokens...', - PENDING_DEPOSIT = 'Depositing tokens...', - PENDING_SUBGRAPH = 'Awaiting transaction indexing...', - SUCCESS = 'Transaction confirmed', - ERROR = 'Something went wrong' + IDLE = "Idle", + STARTING = "Starting transaction...", + CHECKING_ALLOWANCE = "Checking your allowance...", + PENDING_WALLET = "Waiting for wallet confirmation...", + PENDING_APPROVAL = "Approving token spend...", + PENDING_RECEIPT = "Waiting for transaction receipt...", + PENDING_DEPLOYMENT = "Deploying your order...", + PENDING_WITHDRAWAL = "Withdrawing tokens...", + PENDING_DEPOSIT = "Depositing tokens...", + PENDING_SUBGRAPH = "Awaiting transaction indexing...", + SUCCESS = "Transaction confirmed", + ERROR = "Something went wrong", } export enum TransactionStoreErrorMessage { - SWITCH_CHAIN_FAILED = 'Failed to switch chain.', - SUBGRAPH_TIMEOUT_ERROR = 'The subgraph took too long to respond. Your transaction may still be processing.', - SUBGRAPH_FAILED = 'Failed to index transaction.', - RECEIPT_FAILED = 'Failed to get transaction receipt.' + SWITCH_CHAIN_FAILED = "Failed to switch chain.", + SUBGRAPH_TIMEOUT_ERROR = "The subgraph took too long to respond. Your transaction may still be processing.", + SUBGRAPH_FAILED = "Failed to index transaction.", + RECEIPT_FAILED = "Failed to get transaction receipt.", } export type InternalTransactionArgs = { - chainId: number; - txHash: Hex; - queryKey: string; + chainId: number; + txHash: Hex; + queryKey: string; }; export type TransactionArgs = InternalTransactionArgs & { - name: string; - // Used for toast notifications upon final completion/failure - errorMessage: string; - successMessage: string; - queryKey: string; - toastLinks: ToastLink[]; - // Optional indexing function called after receipt confirmation. - // TransactionStore doesn't know what this function does - it just calls it. - // The function handles updating state, success/error callbacks, and links. - awaitIndexingFn?: AwaitIndexingFn; + name: string; + // Used for toast notifications upon final completion/failure + errorMessage: string; + successMessage: string; + queryKey: string; + toastLinks: ToastLink[]; + // Optional indexing function called after receipt confirmation. + // TransactionStore doesn't know what this function does - it just calls it. + // The function handles updating state, success/error callbacks, and links. + awaitIndexingFn?: AwaitIndexingFn; }; diff --git a/packages/ui-components/src/lib/utils/breadcrumbs.ts b/packages/ui-components/src/lib/utils/breadcrumbs.ts index da57db1d42..601ef3fcd2 100644 --- a/packages/ui-components/src/lib/utils/breadcrumbs.ts +++ b/packages/ui-components/src/lib/utils/breadcrumbs.ts @@ -1,14 +1,14 @@ export interface BreadCrumb { - label: string; - href: string; + label: string; + href: string; } export function generateBreadcrumbs(path: string): BreadCrumb[] { - const crumbs = path.split('/'); - return crumbs - .map((c, i) => ({ - label: c, - href: crumbs.slice(0, i + 1).join('/') - })) - .slice(1, -1); + const crumbs = path.split("/"); + return crumbs + .map((c, i) => ({ + label: c, + href: crumbs.slice(0, i + 1).join("/"), + })) + .slice(1, -1); } diff --git a/packages/ui-components/src/lib/utils/codeMirrorThemes.ts b/packages/ui-components/src/lib/utils/codeMirrorThemes.ts index ed99c3cd62..a87eacff05 100644 --- a/packages/ui-components/src/lib/utils/codeMirrorThemes.ts +++ b/packages/ui-components/src/lib/utils/codeMirrorThemes.ts @@ -1,88 +1,94 @@ -import { createTheme } from 'thememirror'; -import { tags } from '@lezer/highlight'; +import { createTheme } from "thememirror"; +import { tags } from "@lezer/highlight"; // configured to resemble vscode default light theme export const lightCodeMirrorTheme = createTheme({ - variant: 'light', - settings: { - background: '#ffffff', - foreground: '#001080', - caret: '#000000', - selection: '#add6ff', - lineHighlight: '#77777740', - gutterBackground: '#eeeeee', - gutterForeground: '#237893' - }, - styles: [ - { tag: tags.comment, color: '#008001' }, - { tag: tags.variableName, color: '#0070c1' }, - { tag: [tags.string, tags.special(tags.brace)], color: '#b55b00' }, - { tag: tags.number, color: '#00b97b' }, - { tag: tags.bool, color: '#0000ff' }, - { tag: tags.null, color: '#0000ff' }, - { tag: tags.unit, color: '#0000ff' }, - { tag: tags.keyword, color: '#af01db' }, - { tag: tags.operator, color: '#000000' }, - { tag: tags.className, color: '#257f99' }, - { tag: tags.meta, color: '#0950a9' }, - { tag: tags.definition(tags.typeName), color: '#257f99' }, - { tag: tags.angleBracket, color: '#213CF1' }, - { tag: tags.brace, color: '#213CF1' }, - { tag: tags.bracket, color: '#213CF1' }, - { tag: tags.squareBracket, color: '#213CF1' }, - { tag: tags.paren, color: '#213CF1' }, - { tag: tags.punctuation, color: '#464646' }, - { tag: tags.separator, color: '#464646' }, - { tag: tags.typeName, color: '#257f99' }, - { tag: tags.tagName, color: '#800000' }, - { tag: tags.attributeName, color: '#eb3d36' }, - { tag: tags.attributeValue, color: '#444444' }, - { tag: tags.content, color: '#b55b00' }, - { tag: [tags.propertyName, tags.definition(tags.propertyName)], color: '#0469ff' }, - { tag: tags.labelName, color: '#4fc4ff' }, - { tag: tags.deleted, color: '#cc0000' } - ] + variant: "light", + settings: { + background: "#ffffff", + foreground: "#001080", + caret: "#000000", + selection: "#add6ff", + lineHighlight: "#77777740", + gutterBackground: "#eeeeee", + gutterForeground: "#237893", + }, + styles: [ + { tag: tags.comment, color: "#008001" }, + { tag: tags.variableName, color: "#0070c1" }, + { tag: [tags.string, tags.special(tags.brace)], color: "#b55b00" }, + { tag: tags.number, color: "#00b97b" }, + { tag: tags.bool, color: "#0000ff" }, + { tag: tags.null, color: "#0000ff" }, + { tag: tags.unit, color: "#0000ff" }, + { tag: tags.keyword, color: "#af01db" }, + { tag: tags.operator, color: "#000000" }, + { tag: tags.className, color: "#257f99" }, + { tag: tags.meta, color: "#0950a9" }, + { tag: tags.definition(tags.typeName), color: "#257f99" }, + { tag: tags.angleBracket, color: "#213CF1" }, + { tag: tags.brace, color: "#213CF1" }, + { tag: tags.bracket, color: "#213CF1" }, + { tag: tags.squareBracket, color: "#213CF1" }, + { tag: tags.paren, color: "#213CF1" }, + { tag: tags.punctuation, color: "#464646" }, + { tag: tags.separator, color: "#464646" }, + { tag: tags.typeName, color: "#257f99" }, + { tag: tags.tagName, color: "#800000" }, + { tag: tags.attributeName, color: "#eb3d36" }, + { tag: tags.attributeValue, color: "#444444" }, + { tag: tags.content, color: "#b55b00" }, + { + tag: [tags.propertyName, tags.definition(tags.propertyName)], + color: "#0469ff", + }, + { tag: tags.labelName, color: "#4fc4ff" }, + { tag: tags.deleted, color: "#cc0000" }, + ], }); // configured to resemble vscode default dark theme export const darkCodeMirrorTheme = createTheme({ - variant: 'dark', - settings: { - background: '#1e1e1e', - foreground: '#d4d4d4', - caret: '#d4d4d4', - selection: '#ffffff', - lineHighlight: '#99999940', - gutterBackground: '#282828', - gutterForeground: '#858585' - }, - styles: [ - { tag: [tags.comment, tags.lineComment], color: '#6c9e57' }, - { tag: tags.variableName, color: '#9cdcfe' }, - { tag: [tags.string, tags.special(tags.brace)], color: '#ce9178' }, - { tag: tags.number, color: '#B6CFA9' }, - { tag: tags.bool, color: '#4fc4ff' }, - { tag: tags.null, color: '#4fc4ff' }, - { tag: tags.unit, color: '#608FC2' }, - { tag: tags.keyword, color: '#d18dcc' }, - { tag: tags.operator, color: '#d4d4d4' }, - { tag: tags.className, color: '#4dcab1' }, - { tag: tags.meta, color: '#608FC2' }, - { tag: tags.definition(tags.typeName), color: '#4fcfb5' }, - { tag: tags.angleBracket, color: '#F9D849' }, - { tag: tags.brace, color: '#F9D849' }, - { tag: tags.bracket, color: '#F9D849' }, - { tag: tags.squareBracket, color: '#F9D849' }, - { tag: tags.paren, color: '#F9D849' }, - { tag: tags.punctuation, color: '#d4d4d4' }, - { tag: tags.separator, color: '#d4d4d4' }, - { tag: tags.typeName, color: '#4ecdb4' }, - { tag: tags.tagName, color: '#59a3df' }, - { tag: tags.attributeName, color: '#ffffff' }, - { tag: tags.attributeValue, color: '#ffffff' }, - { tag: tags.content, color: '#ce9178' }, - { tag: [tags.propertyName, tags.definition(tags.propertyName)], color: '#608FC2' }, - { tag: tags.labelName, color: '#4fc4ff' }, - { tag: tags.deleted, color: '#c86464' } - ] + variant: "dark", + settings: { + background: "#1e1e1e", + foreground: "#d4d4d4", + caret: "#d4d4d4", + selection: "#ffffff", + lineHighlight: "#99999940", + gutterBackground: "#282828", + gutterForeground: "#858585", + }, + styles: [ + { tag: [tags.comment, tags.lineComment], color: "#6c9e57" }, + { tag: tags.variableName, color: "#9cdcfe" }, + { tag: [tags.string, tags.special(tags.brace)], color: "#ce9178" }, + { tag: tags.number, color: "#B6CFA9" }, + { tag: tags.bool, color: "#4fc4ff" }, + { tag: tags.null, color: "#4fc4ff" }, + { tag: tags.unit, color: "#608FC2" }, + { tag: tags.keyword, color: "#d18dcc" }, + { tag: tags.operator, color: "#d4d4d4" }, + { tag: tags.className, color: "#4dcab1" }, + { tag: tags.meta, color: "#608FC2" }, + { tag: tags.definition(tags.typeName), color: "#4fcfb5" }, + { tag: tags.angleBracket, color: "#F9D849" }, + { tag: tags.brace, color: "#F9D849" }, + { tag: tags.bracket, color: "#F9D849" }, + { tag: tags.squareBracket, color: "#F9D849" }, + { tag: tags.paren, color: "#F9D849" }, + { tag: tags.punctuation, color: "#d4d4d4" }, + { tag: tags.separator, color: "#d4d4d4" }, + { tag: tags.typeName, color: "#4ecdb4" }, + { tag: tags.tagName, color: "#59a3df" }, + { tag: tags.attributeName, color: "#ffffff" }, + { tag: tags.attributeValue, color: "#ffffff" }, + { tag: tags.content, color: "#ce9178" }, + { + tag: [tags.propertyName, tags.definition(tags.propertyName)], + color: "#608FC2", + }, + { tag: tags.labelName, color: "#4fc4ff" }, + { tag: tags.deleted, color: "#c86464" }, + ], }); diff --git a/packages/ui-components/src/lib/utils/configHelpers.ts b/packages/ui-components/src/lib/utils/configHelpers.ts index f4d5e0a120..8ca5a3fe08 100644 --- a/packages/ui-components/src/lib/utils/configHelpers.ts +++ b/packages/ui-components/src/lib/utils/configHelpers.ts @@ -1,26 +1,26 @@ -import type { AccountCfg } from '@rainlanguage/raindex'; +import type { AccountCfg } from "@rainlanguage/raindex"; export function getAccountsAsOptions(accounts?: Map) { - if (!accounts) return {}; - return Object.fromEntries( - Array.from(accounts.entries()).map(([key, value]) => [key, value.address]) - ); + if (!accounts) return {}; + return Object.fromEntries( + Array.from(accounts.entries()).map(([key, value]) => [key, value.address]), + ); } if (import.meta.vitest) { - const { expect, it, describe } = import.meta.vitest; + const { expect, it, describe } = import.meta.vitest; - describe('getAccountsAsOptions', () => { - it('should return the correct accounts as options', () => { - const accounts = new Map([ - ['account1', { address: '0x1234567890abcdef', key: 'account1' }], - ['account2', { address: '0xabcdef1234567890', key: 'account2' }] - ]); - const result = getAccountsAsOptions(accounts); - expect(result).toEqual({ - account1: '0x1234567890abcdef', - account2: '0xabcdef1234567890' - }); - }); - }); + describe("getAccountsAsOptions", () => { + it("should return the correct accounts as options", () => { + const accounts = new Map([ + ["account1", { address: "0x1234567890abcdef", key: "account1" }], + ["account2", { address: "0xabcdef1234567890", key: "account2" }], + ]); + const result = getAccountsAsOptions(accounts); + expect(result).toEqual({ + account1: "0x1234567890abcdef", + account2: "0xabcdef1234567890", + }); + }); + }); } diff --git a/packages/ui-components/src/lib/utils/constructHashLink.ts b/packages/ui-components/src/lib/utils/constructHashLink.ts index 10ed0d6b74..f4983bc117 100644 --- a/packages/ui-components/src/lib/utils/constructHashLink.ts +++ b/packages/ui-components/src/lib/utils/constructHashLink.ts @@ -1,11 +1,16 @@ -import type { Address, RaindexOrder, RaindexOrderAsIO, RaindexVault } from '@rainlanguage/raindex'; -import fc from 'fast-check'; -import { test } from '@fast-check/vitest'; +import type { + Address, + RaindexOrder, + RaindexOrderAsIO, + RaindexVault, +} from "@rainlanguage/raindex"; +import fc from "fast-check"; +import { test } from "@fast-check/vitest"; type OrderOrVault = RaindexOrder | RaindexOrderAsIO | RaindexVault; function isOrder(obj: OrderOrVault): obj is RaindexOrder | RaindexOrderAsIO { - return obj && 'orderHash' in obj; + return obj && "orderHash" in obj; } /** * Constructs a link path for an order or vault based on its type and network @@ -16,18 +21,20 @@ function isOrder(obj: OrderOrVault): obj is RaindexOrder | RaindexOrderAsIO { * @returns The constructed link path */ export function constructHashLink( - orderOrVault: OrderOrVault, - type: 'orders' | 'vaults', - chainId: number, - raindexAddress: Address + orderOrVault: OrderOrVault, + type: "orders" | "vaults", + chainId: number, + raindexAddress: Address, ): string { - if (!orderOrVault) { - return `/${type}`; - } + if (!orderOrVault) { + return `/${type}`; + } - const slug = isOrder(orderOrVault) ? orderOrVault.orderHash : (orderOrVault as RaindexVault).id; + const slug = isOrder(orderOrVault) + ? orderOrVault.orderHash + : (orderOrVault as RaindexVault).id; - return `/${type}/${chainId}-${raindexAddress}-${slug}`; + return `/${type}/${chainId}-${raindexAddress}-${slug}`; } /** @@ -36,8 +43,8 @@ export function constructHashLink( * @returns True if the order is active, false otherwise */ export function isOrderOrVaultActive(orderOrVault: OrderOrVault): boolean { - const _isOrder = isOrder(orderOrVault); - return _isOrder ? (orderOrVault as RaindexOrderAsIO).active : false; + const _isOrder = isOrder(orderOrVault); + return _isOrder ? (orderOrVault as RaindexOrderAsIO).active : false; } /** @@ -46,101 +53,111 @@ export function isOrderOrVaultActive(orderOrVault: OrderOrVault): boolean { * @returns The hash value */ export function extractHash(orderOrVault: OrderOrVault): string { - const _isOrder = isOrder(orderOrVault); - return _isOrder - ? (orderOrVault as RaindexOrder).orderHash - : (orderOrVault as RaindexVault)?.id || ''; + const _isOrder = isOrder(orderOrVault); + return _isOrder + ? (orderOrVault as RaindexOrder).orderHash + : (orderOrVault as RaindexVault)?.id || ""; } if (import.meta.vitest) { - const { expect, it, describe } = import.meta.vitest; + const { expect, it, describe } = import.meta.vitest; - describe('constructHashLink', () => { - test.prop([ - fc.record({ - orderHash: fc.string(), - active: fc.boolean() - }), - fc.oneof(fc.constant('orders'), fc.constant('vaults')), - fc.integer(), - fc.string() - ])('constructs correct link for orders', (order, type, chainId, raindexAddress) => { - const result = constructHashLink( - order as RaindexOrder, - type, - chainId, - raindexAddress as Address - ); - expect(result).toBe(`/${type}/${chainId}-${raindexAddress}-${order.orderHash}`); - }); + describe("constructHashLink", () => { + test.prop([ + fc.record({ + orderHash: fc.string(), + active: fc.boolean(), + }), + fc.oneof(fc.constant("orders"), fc.constant("vaults")), + fc.integer(), + fc.string(), + ])( + "constructs correct link for orders", + (order, type, chainId, raindexAddress) => { + const result = constructHashLink( + order as RaindexOrder, + type, + chainId, + raindexAddress as Address, + ); + expect(result).toBe( + `/${type}/${chainId}-${raindexAddress}-${order.orderHash}`, + ); + }, + ); - test.prop([ - fc.record({ - id: fc.string(), - owner: fc.string() - }), - fc.oneof(fc.constant('orders'), fc.constant('vaults')), - fc.integer(), - fc.string() - ])('constructs correct link for vaults', (vault, type, chainId, raindexAddress) => { - const result = constructHashLink( - vault as RaindexVault, - type, - chainId, - raindexAddress as Address - ); - expect(result).toBe(`/${type}/${chainId}-${raindexAddress}-${vault.id}`); - }); - }); + test.prop([ + fc.record({ + id: fc.string(), + owner: fc.string(), + }), + fc.oneof(fc.constant("orders"), fc.constant("vaults")), + fc.integer(), + fc.string(), + ])( + "constructs correct link for vaults", + (vault, type, chainId, raindexAddress) => { + const result = constructHashLink( + vault as RaindexVault, + type, + chainId, + raindexAddress as Address, + ); + expect(result).toBe( + `/${type}/${chainId}-${raindexAddress}-${vault.id}`, + ); + }, + ); + }); - describe('isOrderOrVaultActive', () => { - test.prop([ - fc.record({ - orderHash: fc.string(), - active: fc.boolean() - }) - ])('returns correct active status for orders', (order) => { - const result = isOrderOrVaultActive(order as RaindexOrderAsIO); - expect(result).toBe(order.active); - }); + describe("isOrderOrVaultActive", () => { + test.prop([ + fc.record({ + orderHash: fc.string(), + active: fc.boolean(), + }), + ])("returns correct active status for orders", (order) => { + const result = isOrderOrVaultActive(order as RaindexOrderAsIO); + expect(result).toBe(order.active); + }); - test.prop([ - fc.record({ - id: fc.string(), - owner: fc.string() - }) - ])('returns false for vaults', (vault) => { - const result = isOrderOrVaultActive(vault as RaindexVault); - expect(result).toBe(false); - }); - }); + test.prop([ + fc.record({ + id: fc.string(), + owner: fc.string(), + }), + ])("returns false for vaults", (vault) => { + const result = isOrderOrVaultActive(vault as RaindexVault); + expect(result).toBe(false); + }); + }); - describe('extractHash', () => { - test.prop([ - fc.record({ - orderHash: fc.string(), - active: fc.boolean() - }) - ])('extracts hash from orders', (order) => { - const result = extractHash(order as RaindexOrder); - expect(result).toBe(order.orderHash); - }); + describe("extractHash", () => { + test.prop([ + fc.record({ + orderHash: fc.string(), + active: fc.boolean(), + }), + ])("extracts hash from orders", (order) => { + const result = extractHash(order as RaindexOrder); + expect(result).toBe(order.orderHash); + }); - test.prop([ - fc.record({ - id: fc.string(), - owner: fc.string() - }) - ])('extracts hash from vaults', (vault) => { - const result = extractHash(vault as RaindexVault); - expect(result).toBe(vault.id); - }); + test.prop([ + fc.record({ + id: fc.string(), + owner: fc.string(), + }), + ])("extracts hash from vaults", (vault) => { + const result = extractHash(vault as RaindexVault); + expect(result).toBe(vault.id); + }); - it('handles undefined vault id', () => { - // Create a partial vault object with undefined id - const vault = { id: undefined } as unknown as RaindexVault; - const result = extractHash(vault); - expect(result).toBe(''); - }); - }); + it("handles undefined vault id", () => { + // Create a partial vault object with undefined id + const vault = { id: undefined } as unknown as RaindexVault; + const result = extractHash(vault); + expect(result).toBe(""); + }); + }); } diff --git a/packages/ui-components/src/lib/utils/getNetworkName.ts b/packages/ui-components/src/lib/utils/getNetworkName.ts index 02d57fa2b2..d9a72c3d40 100644 --- a/packages/ui-components/src/lib/utils/getNetworkName.ts +++ b/packages/ui-components/src/lib/utils/getNetworkName.ts @@ -1,15 +1,15 @@ -import * as chains from 'viem/chains'; +import * as chains from "viem/chains"; export function getNetworkName(chainId: number): string | undefined { - const chain = Object.values(chains).find((chain) => chain.id === chainId); - return chain?.name; + const chain = Object.values(chains).find((chain) => chain.id === chainId); + return chain?.name; } if (import.meta.vitest) { - describe('getNetworkName', () => { - it('should return the network name for a given chain id', () => { - expect(getNetworkName(1)).toBe('Ethereum'); - expect(getNetworkName(137)).toBe('Polygon'); - }); - }); + describe("getNetworkName", () => { + it("should return the network name for a given chain id", () => { + expect(getNetworkName(1)).toBe("Ethereum"); + expect(getNetworkName(137)).toBe("Polygon"); + }); + }); } diff --git a/packages/ui-components/src/lib/utils/hex.ts b/packages/ui-components/src/lib/utils/hex.ts index 5ca8d47f13..2fb0ff23f4 100644 --- a/packages/ui-components/src/lib/utils/hex.ts +++ b/packages/ui-components/src/lib/utils/hex.ts @@ -1,4 +1,4 @@ -import { toHex } from 'viem'; +import { toHex } from "viem"; export const HEX_INPUT_REGEX = /^(0x)?([0-9a-f]+)?$/; diff --git a/packages/ui-components/src/lib/utils/lightweightChartsThemes.ts b/packages/ui-components/src/lib/utils/lightweightChartsThemes.ts index 97a9dfb192..1ff7202f5d 100644 --- a/packages/ui-components/src/lib/utils/lightweightChartsThemes.ts +++ b/packages/ui-components/src/lib/utils/lightweightChartsThemes.ts @@ -1,40 +1,40 @@ -import { ColorType } from 'lightweight-charts'; +import { ColorType } from "lightweight-charts"; export interface ChartTheme { - layout: { - textColor: string; - background: { - type: ColorType; - color: string; - }; - }; - grid: { - vertLines: { - color: string; - }; - horzLines: { - color: string; - }; - }; + layout: { + textColor: string; + background: { + type: ColorType; + color: string; + }; + }; + grid: { + vertLines: { + color: string; + }; + horzLines: { + color: string; + }; + }; } export const darkChartTheme = { - layout: { - textColor: 'white', - background: { type: ColorType.Solid, color: 'transparent' } - }, - grid: { - vertLines: { color: '#484848' }, - horzLines: { color: '#484848' } - } + layout: { + textColor: "white", + background: { type: ColorType.Solid, color: "transparent" }, + }, + grid: { + vertLines: { color: "#484848" }, + horzLines: { color: "#484848" }, + }, }; export const lightChartTheme = { - layout: { - textColor: 'black', - background: { type: ColorType.Solid, color: 'transparent' } - }, - grid: { - vertLines: { color: '#ECECEC' }, - horzLines: { color: '#ECECEC' } - } + layout: { + textColor: "black", + background: { type: ColorType.Solid, color: "transparent" }, + }, + grid: { + vertLines: { color: "#ECECEC" }, + horzLines: { color: "#ECECEC" }, + }, }; diff --git a/packages/ui-components/src/lib/utils/number.ts b/packages/ui-components/src/lib/utils/number.ts index e6b2184513..e815ea557a 100644 --- a/packages/ui-components/src/lib/utils/number.ts +++ b/packages/ui-components/src/lib/utils/number.ts @@ -1,4 +1,4 @@ -import { formatUnits } from 'viem'; +import { formatUnits } from "viem"; /** * Converts a bigint string value to a percentage with optionally given number of decimal points @@ -7,16 +7,21 @@ import { formatUnits } from 'viem'; * @param decimalPoint - (optional) The number of digits to keep after "." in final result, defaults to valueDecimals */ export function bigintStringToPercentage( - value: string, - valueDecimals: number, - finalDecimalsDigits?: number + value: string, + valueDecimals: number, + finalDecimalsDigits?: number, ): string { - const finalDecimals = - typeof finalDecimalsDigits !== 'undefined' ? finalDecimalsDigits : valueDecimals; - let valueString = formatUnits(BigInt(value) * 100n, valueDecimals); - const index = valueString.indexOf('.'); - if (index > -1) { - valueString = valueString.substring(0, finalDecimals === 0 ? index : index + finalDecimals + 1); - } - return valueString; + const finalDecimals = + typeof finalDecimalsDigits !== "undefined" + ? finalDecimalsDigits + : valueDecimals; + let valueString = formatUnits(BigInt(value) * 100n, valueDecimals); + const index = valueString.indexOf("."); + if (index > -1) { + valueString = valueString.substring( + 0, + finalDecimals === 0 ? index : index + finalDecimals + 1, + ); + } + return valueString; } diff --git a/packages/ui-components/src/lib/utils/tokens.ts b/packages/ui-components/src/lib/utils/tokens.ts index f4e0c2a1d5..51d932b358 100644 --- a/packages/ui-components/src/lib/utils/tokens.ts +++ b/packages/ui-components/src/lib/utils/tokens.ts @@ -1,5 +1,5 @@ -import type { RaindexVaultToken } from '@rainlanguage/raindex'; +import type { RaindexVaultToken } from "@rainlanguage/raindex"; export function getTokenDisplayName(token: RaindexVaultToken): string { - return token.symbol || token.name || 'Unknown Token'; + return token.symbol || token.name || "Unknown Token"; } diff --git a/packages/ui-components/src/lib/utils/vaultBalanceChangeLabels.ts b/packages/ui-components/src/lib/utils/vaultBalanceChangeLabels.ts index 6d4ed8a8cb..69cea7e026 100644 --- a/packages/ui-components/src/lib/utils/vaultBalanceChangeLabels.ts +++ b/packages/ui-components/src/lib/utils/vaultBalanceChangeLabels.ts @@ -1,25 +1,33 @@ import type { - RaindexVaultBalanceChangeType, - VaultBalanceChangeFilter -} from '@rainlanguage/raindex'; + RaindexVaultBalanceChangeType, + VaultBalanceChangeFilter, +} from "@rainlanguage/raindex"; -export const VAULT_BALANCE_CHANGE_LABELS: Record = { - deposit: 'Deposit', - withdrawal: 'Withdrawal', - takeOrder: 'Take order', - clear: 'Clear', - clearBounty: 'Clear Bounty', - unknown: 'Unknown' +export const VAULT_BALANCE_CHANGE_LABELS: Record< + RaindexVaultBalanceChangeType, + string +> = { + deposit: "Deposit", + withdrawal: "Withdrawal", + takeOrder: "Take order", + clear: "Clear", + clearBounty: "Clear Bounty", + unknown: "Unknown", }; -export const VAULT_BALANCE_CHANGE_FILTER_LABELS: Record = { - deposit: 'Deposit', - withdrawal: 'Withdrawal', - takeOrder: 'Take order', - clear: 'Clear', - clearBounty: 'Clear Bounty' +export const VAULT_BALANCE_CHANGE_FILTER_LABELS: Record< + VaultBalanceChangeFilter, + string +> = { + deposit: "Deposit", + withdrawal: "Withdrawal", + takeOrder: "Take order", + clear: "Clear", + clearBounty: "Clear Bounty", }; -export function labelForVaultBalanceChangeType(type: RaindexVaultBalanceChangeType): string { - return VAULT_BALANCE_CHANGE_LABELS[type] ?? type; +export function labelForVaultBalanceChangeType( + type: RaindexVaultBalanceChangeType, +): string { + return VAULT_BALANCE_CHANGE_LABELS[type] ?? type; } From fbab477fecce8fc905026013e2c780f12d8126bc Mon Sep 17 00:00:00 2001 From: David Meister Date: Wed, 20 May 2026 11:21:01 +0000 Subject: [PATCH 67/69] fix: clean up stale prettier entries in package-lock.json Root package.json had prettier deps removed in an earlier branch commit but npm install wasnt re-run, leaving the entries in package-lock.json. Re-run picked up the change. --- package-lock.json | 94 +---------------------------------------------- 1 file changed, 1 insertion(+), 93 deletions(-) diff --git a/package-lock.json b/package-lock.json index d7606c347b..13ba9e950f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -56,9 +56,6 @@ "lodash": "4.17.21", "mockttp": "3.15.4", "postcss": "8.5.2", - "prettier": "3.3.3", - "prettier-plugin-svelte": "3.2.8", - "prettier-plugin-tailwindcss": "0.6.8", "publint": "0.2.12", "svelte": "4.2.19", "svelte-check": "3.8.6", @@ -13791,6 +13788,7 @@ "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -13814,96 +13812,6 @@ "node": ">=6.0.0" } }, - "node_modules/prettier-plugin-svelte": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.2.8.tgz", - "integrity": "sha512-PAHmmU5cGZdnhW4mWhmvxuG2PVbbHIxUuPOdUKvfE+d4Qt2d29iU5VWrPdsaW5YqVEE0nqhlvN4eoKmVMpIF3Q==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "prettier": "^3.0.0", - "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0" - } - }, - "node_modules/prettier-plugin-tailwindcss": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.8.tgz", - "integrity": "sha512-dGu3kdm7SXPkiW4nzeWKCl3uoImdd5CTZEJGxyypEPL37Wj0HT2pLqjrvSei1nTeuQfO4PUfjeW5cTUNRLZ4sA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.21.3" - }, - "peerDependencies": { - "@ianvs/prettier-plugin-sort-imports": "*", - "@prettier/plugin-pug": "*", - "@shopify/prettier-plugin-liquid": "*", - "@trivago/prettier-plugin-sort-imports": "*", - "@zackad/prettier-plugin-twig-melody": "*", - "prettier": "^3.0", - "prettier-plugin-astro": "*", - "prettier-plugin-css-order": "*", - "prettier-plugin-import-sort": "*", - "prettier-plugin-jsdoc": "*", - "prettier-plugin-marko": "*", - "prettier-plugin-multiline-arrays": "*", - "prettier-plugin-organize-attributes": "*", - "prettier-plugin-organize-imports": "*", - "prettier-plugin-sort-imports": "*", - "prettier-plugin-style-order": "*", - "prettier-plugin-svelte": "*" - }, - "peerDependenciesMeta": { - "@ianvs/prettier-plugin-sort-imports": { - "optional": true - }, - "@prettier/plugin-pug": { - "optional": true - }, - "@shopify/prettier-plugin-liquid": { - "optional": true - }, - "@trivago/prettier-plugin-sort-imports": { - "optional": true - }, - "@zackad/prettier-plugin-twig-melody": { - "optional": true - }, - "prettier-plugin-astro": { - "optional": true - }, - "prettier-plugin-css-order": { - "optional": true - }, - "prettier-plugin-import-sort": { - "optional": true - }, - "prettier-plugin-jsdoc": { - "optional": true - }, - "prettier-plugin-marko": { - "optional": true - }, - "prettier-plugin-multiline-arrays": { - "optional": true - }, - "prettier-plugin-organize-attributes": { - "optional": true - }, - "prettier-plugin-organize-imports": { - "optional": true - }, - "prettier-plugin-sort-imports": { - "optional": true - }, - "prettier-plugin-style-order": { - "optional": true - }, - "prettier-plugin-svelte": { - "optional": true - } - } - }, "node_modules/pretty-format": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", From e764d9d67e01c01751d44192b7ada587a62bae6e Mon Sep 17 00:00:00 2001 From: David Meister Date: Wed, 20 May 2026 12:12:10 +0000 Subject: [PATCH 68/69] fix: bump REGISTRY_URL to rain.strategies v6+raindexes+builder commit (rainlanguage/rain.strategies#105) --- packages/webapp/src/lib/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webapp/src/lib/constants.ts b/packages/webapp/src/lib/constants.ts index c26e8bd5f8..21983dfe21 100644 --- a/packages/webapp/src/lib/constants.ts +++ b/packages/webapp/src/lib/constants.ts @@ -1,2 +1,2 @@ export const REGISTRY_URL = - 'https://raw.githubusercontent.com/rainlanguage/rain.strategies/b59db7f06eb24746a21968c44d4ccd368d64495c/registry'; + "https://raw.githubusercontent.com/rainlanguage/rain.strategies/342ee3c75f390318481e9ca0367aad9311bee9e2/registry"; From 5fc5209d8c6a38bdacb3d7babad0442afcb59bf2 Mon Sep 17 00:00:00 2001 From: David Meister Date: Wed, 20 May 2026 13:57:38 +0000 Subject: [PATCH 69/69] fix: bump REGISTRY_URL to 805c3097 (rain.strategies#106) --- packages/webapp/src/lib/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webapp/src/lib/constants.ts b/packages/webapp/src/lib/constants.ts index 21983dfe21..d216542a87 100644 --- a/packages/webapp/src/lib/constants.ts +++ b/packages/webapp/src/lib/constants.ts @@ -1,2 +1,2 @@ export const REGISTRY_URL = - "https://raw.githubusercontent.com/rainlanguage/rain.strategies/342ee3c75f390318481e9ca0367aad9311bee9e2/registry"; + "https://raw.githubusercontent.com/rainlanguage/rain.strategies/805c30972423a9e0cd3d51171344f209011bce22/registry";