From a430cdc1e5b133ddce372e9f559747a1ba8109d9 Mon Sep 17 00:00:00 2001 From: GrandSchtroumpf Date: Fri, 26 Jan 2024 16:21:06 +0100 Subject: [PATCH 1/8] feat(carbon-defi) add carbon defi in apps --- src/apps/carbon-defi/assets/logo.png | Bin 0 -> 130571 bytes src/apps/carbon-defi/carbon-defi.module.ts | 11 + .../contracts/abis/carbon-controller.json | 1758 ++++++++++++++++ .../carbon-defi/contracts/abis/voucher.json | 942 +++++++++ src/apps/carbon-defi/contracts/index.ts | 4 + .../contracts/viem.contract-factory.ts | 22 + .../contracts/viem/CarbonController.ts | 1772 +++++++++++++++++ .../carbon-defi/contracts/viem/Voucher.ts | 956 +++++++++ src/apps/carbon-defi/contracts/viem/index.ts | 9 + ...defi.strategy.contract-position-fetcher.ts | 142 ++ 10 files changed, 5616 insertions(+) create mode 100644 src/apps/carbon-defi/assets/logo.png create mode 100644 src/apps/carbon-defi/carbon-defi.module.ts create mode 100644 src/apps/carbon-defi/contracts/abis/carbon-controller.json create mode 100644 src/apps/carbon-defi/contracts/abis/voucher.json create mode 100644 src/apps/carbon-defi/contracts/index.ts create mode 100644 src/apps/carbon-defi/contracts/viem.contract-factory.ts create mode 100644 src/apps/carbon-defi/contracts/viem/CarbonController.ts create mode 100644 src/apps/carbon-defi/contracts/viem/Voucher.ts create mode 100644 src/apps/carbon-defi/contracts/viem/index.ts create mode 100644 src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts diff --git a/src/apps/carbon-defi/assets/logo.png b/src/apps/carbon-defi/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..8c0eabe770d885715a7c2cac79e5309a6e98a6d1 GIT binary patch literal 130571 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%0Df7{Ob6 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�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 literal 0 HcmV?d00001 diff --git a/src/apps/carbon-defi/carbon-defi.module.ts b/src/apps/carbon-defi/carbon-defi.module.ts new file mode 100644 index 000000000..4bc6d6b4d --- /dev/null +++ b/src/apps/carbon-defi/carbon-defi.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; + +import { AbstractApp } from '~app/app.dynamic-module'; + +import { CarbonDefiViemContractFactory } from './contracts'; +import { EthereumCarbonDefiStrategyContractPositionFetcher } from './ethereum/carbon-defi.strategy.contract-position-fetcher'; + +@Module({ + providers: [CarbonDefiViemContractFactory, EthereumCarbonDefiStrategyContractPositionFetcher], +}) +export class CarbonDefiAppModule extends AbstractApp() { } diff --git a/src/apps/carbon-defi/contracts/abis/carbon-controller.json b/src/apps/carbon-defi/contracts/abis/carbon-controller.json new file mode 100644 index 000000000..875c106df --- /dev/null +++ b/src/apps/carbon-defi/contracts/abis/carbon-controller.json @@ -0,0 +1,1758 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [], + "name": "AccessDenied", + "type": "error" + }, + { + "inputs": [], + "name": "AlreadyInitialized", + "type": "error" + }, + { + "inputs": [], + "name": "BalanceMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DeadlineExpired", + "type": "error" + }, + { + "inputs": [], + "name": "GreaterThanMaxInput", + "type": "error" + }, + { + "inputs": [], + "name": "IdenticalAddresses", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientCapacity", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientNativeTokenReceived", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidIndices", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRate", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTradeActionAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTradeActionStrategyId", + "type": "error" + }, + { + "inputs": [], + "name": "LowerThanMinReturn", + "type": "error" + }, + { + "inputs": [], + "name": "NativeAmountMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "OrderDisabled", + "type": "error" + }, + { + "inputs": [], + "name": "OutDated", + "type": "error" + }, + { + "inputs": [], + "name": "Overflow", + "type": "error" + }, + { + "inputs": [], + "name": "PairAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "PairDoesNotExist", + "type": "error" + }, + { + "inputs": [], + "name": "UnknownDelegator", + "type": "error" + }, + { + "inputs": [], + "name": "UnnecessaryNativeTokenReceived", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroValue", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "Token", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "FeesWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint128", + "name": "pairId", + "type": "uint128" + }, + { + "indexed": true, + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "Token", + "name": "token1", + "type": "address" + } + ], + "name": "PairCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "Token", + "name": "token1", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "prevFeePPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "newFeePPM", + "type": "uint32" + } + ], + "name": "PairTradingFeePPMUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "Token", + "name": "token1", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct Order", + "name": "order0", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct Order", + "name": "order1", + "type": "tuple" + } + ], + "name": "StrategyCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "Token", + "name": "token1", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct Order", + "name": "order0", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct Order", + "name": "order1", + "type": "tuple" + } + ], + "name": "StrategyDeleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "Token", + "name": "token1", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct Order", + "name": "order0", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct Order", + "name": "order1", + "type": "tuple" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "reason", + "type": "uint8" + } + ], + "name": "StrategyUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "trader", + "type": "address" + }, + { + "indexed": true, + "internalType": "Token", + "name": "sourceToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "Token", + "name": "targetToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "sourceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "targetAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "tradingFeeAmount", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "bool", + "name": "byTargetAmount", + "type": "bool" + } + ], + "name": "TokensTraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "prevFeePPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "newFeePPM", + "type": "uint32" + } + ], + "name": "TradingFeePPMUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "token", + "type": "address" + } + ], + "name": "accumulatedFees", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "sourceToken", + "type": "address" + }, + { + "internalType": "Token", + "name": "targetToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "strategyId", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "amount", + "type": "uint128" + } + ], + "internalType": "struct TradeAction[]", + "name": "tradeActions", + "type": "tuple[]" + } + ], + "name": "calculateTradeSourceAmount", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "sourceToken", + "type": "address" + }, + { + "internalType": "Token", + "name": "targetToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "strategyId", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "amount", + "type": "uint128" + } + ], + "internalType": "struct TradeAction[]", + "name": "tradeActions", + "type": "tuple[]" + } + ], + "name": "calculateTradeTargetAmount", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "controllerType", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "internalType": "Token", + "name": "token1", + "type": "address" + } + ], + "name": "createPair", + "outputs": [ + { + "components": [ + { + "internalType": "uint128", + "name": "id", + "type": "uint128" + }, + { + "internalType": "Token[2]", + "name": "tokens", + "type": "address[2]" + } + ], + "internalType": "struct Pair", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "internalType": "Token", + "name": "token1", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "internalType": "struct Order[2]", + "name": "orders", + "type": "tuple[2]" + } + ], + "name": "createStrategy", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "strategyId", + "type": "uint256" + } + ], + "name": "deleteStrategy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "internalType": "Token", + "name": "token1", + "type": "address" + } + ], + "name": "pair", + "outputs": [ + { + "components": [ + { + "internalType": "uint128", + "name": "id", + "type": "uint128" + }, + { + "internalType": "Token[2]", + "name": "tokens", + "type": "address[2]" + } + ], + "internalType": "struct Pair", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "internalType": "Token", + "name": "token1", + "type": "address" + } + ], + "name": "pairTradingFeePPM", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pairs", + "outputs": [ + { + "internalType": "Token[2][]", + "name": "", + "type": "address[2][]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "postUpgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "roleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "roleEmergencyStopper", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "roleFeesManager", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "internalType": "Token", + "name": "token1", + "type": "address" + }, + { + "internalType": "uint32", + "name": "newPairTradingFeePPM", + "type": "uint32" + } + ], + "name": "setPairTradingFeePPM", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "newTradingFeePPM", + "type": "uint32" + } + ], + "name": "setTradingFeePPM", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "internalType": "Token", + "name": "token1", + "type": "address" + }, + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "endIndex", + "type": "uint256" + } + ], + "name": "strategiesByPair", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "Token[2]", + "name": "tokens", + "type": "address[2]" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "internalType": "struct Order[2]", + "name": "orders", + "type": "tuple[2]" + } + ], + "internalType": "struct Strategy[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "internalType": "Token", + "name": "token1", + "type": "address" + } + ], + "name": "strategiesByPairCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "strategy", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "Token[2]", + "name": "tokens", + "type": "address[2]" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "internalType": "struct Order[2]", + "name": "orders", + "type": "tuple[2]" + } + ], + "internalType": "struct Strategy", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "sourceToken", + "type": "address" + }, + { + "internalType": "Token", + "name": "targetToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "strategyId", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "amount", + "type": "uint128" + } + ], + "internalType": "struct TradeAction[]", + "name": "tradeActions", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "minReturn", + "type": "uint128" + } + ], + "name": "tradeBySourceAmount", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "sourceToken", + "type": "address" + }, + { + "internalType": "Token", + "name": "targetToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "strategyId", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "amount", + "type": "uint128" + } + ], + "internalType": "struct TradeAction[]", + "name": "tradeActions", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "maxInput", + "type": "uint128" + } + ], + "name": "tradeByTargetAmount", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "tradingFeePPM", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "strategyId", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "internalType": "struct Order[2]", + "name": "currentOrders", + "type": "tuple[2]" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "internalType": "struct Order[2]", + "name": "newOrders", + "type": "tuple[2]" + } + ], + "name": "updateStrategy", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "withdrawFees", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + } +] \ No newline at end of file diff --git a/src/apps/carbon-defi/contracts/abis/voucher.json b/src/apps/carbon-defi/contracts/abis/voucher.json new file mode 100644 index 000000000..781a1213d --- /dev/null +++ b/src/apps/carbon-defi/contracts/abis/voucher.json @@ -0,0 +1,942 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [], + "name": "AccessDenied", + "type": "error" + }, + { + "inputs": [], + "name": "AlreadyInitialized", + "type": "error" + }, + { + "inputs": [], + "name": "BatchNotSupported", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidIndices", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "newBaseExtension", + "type": "string" + } + ], + "name": "BaseExtensionUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "newBaseURI", + "type": "string" + } + ], + "name": "BaseURIUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "newUseGlobalURI", + "type": "bool" + } + ], + "name": "UseGlobalURIUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "newUseGlobalURI", + "type": "bool" + }, + { + "internalType": "string", + "name": "newBaseURI", + "type": "string" + }, + { + "internalType": "string", + "name": "newBaseExtension", + "type": "string" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "postUpgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "roleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "roleMinter", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "newBaseExtension", + "type": "string" + } + ], + "name": "setBaseExtension", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "newBaseURI", + "type": "string" + } + ], + "name": "setBaseURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "endIndex", + "type": "uint256" + } + ], + "name": "tokensByOwner", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "newUseGlobalURI", + "type": "bool" + } + ], + "name": "useGlobalURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + } +] \ No newline at end of file diff --git a/src/apps/carbon-defi/contracts/index.ts b/src/apps/carbon-defi/contracts/index.ts new file mode 100644 index 000000000..b506a3b64 --- /dev/null +++ b/src/apps/carbon-defi/contracts/index.ts @@ -0,0 +1,4 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ + export * from './viem.contract-factory'; diff --git a/src/apps/carbon-defi/contracts/viem.contract-factory.ts b/src/apps/carbon-defi/contracts/viem.contract-factory.ts new file mode 100644 index 000000000..c40dcf0e8 --- /dev/null +++ b/src/apps/carbon-defi/contracts/viem.contract-factory.ts @@ -0,0 +1,22 @@ +import { Injectable, Inject } from '@nestjs/common'; + +import { IAppToolkit, APP_TOOLKIT } from '~app-toolkit/app-toolkit.interface'; +import { Network } from '~types/network.interface'; + +import { CarbonController__factory, Voucher__factory } from './viem'; + +@Injectable() +export class CarbonDefiViemContractFactory { + constructor(@Inject(APP_TOOLKIT) protected readonly appToolkit: IAppToolkit) { } + + carbonController() { + const address = '0xc537e898cd774e2dcba3b14ea6f34c93d5ea45e1'; + const network = Network.ETHEREUM_MAINNET; + return CarbonController__factory.connect(address, this.appToolkit.getViemNetworkProvider(network)); + } + voucher() { + const address = '0x3660f04b79751e31128f6378eac70807e38f554e'; + const network = Network.ETHEREUM_MAINNET; + return Voucher__factory.connect(address, this.appToolkit.getViemNetworkProvider(network)); + } +} diff --git a/src/apps/carbon-defi/contracts/viem/CarbonController.ts b/src/apps/carbon-defi/contracts/viem/CarbonController.ts new file mode 100644 index 000000000..d99153503 --- /dev/null +++ b/src/apps/carbon-defi/contracts/viem/CarbonController.ts @@ -0,0 +1,1772 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import { getContract, GetContractReturnType, PublicClient } from 'viem'; + +export const carbonControllerAbi = [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [], + "name": "AccessDenied", + "type": "error" + }, + { + "inputs": [], + "name": "AlreadyInitialized", + "type": "error" + }, + { + "inputs": [], + "name": "BalanceMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DeadlineExpired", + "type": "error" + }, + { + "inputs": [], + "name": "GreaterThanMaxInput", + "type": "error" + }, + { + "inputs": [], + "name": "IdenticalAddresses", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientCapacity", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientNativeTokenReceived", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidIndices", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRate", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTradeActionAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTradeActionStrategyId", + "type": "error" + }, + { + "inputs": [], + "name": "LowerThanMinReturn", + "type": "error" + }, + { + "inputs": [], + "name": "NativeAmountMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "OrderDisabled", + "type": "error" + }, + { + "inputs": [], + "name": "OutDated", + "type": "error" + }, + { + "inputs": [], + "name": "Overflow", + "type": "error" + }, + { + "inputs": [], + "name": "PairAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "PairDoesNotExist", + "type": "error" + }, + { + "inputs": [], + "name": "UnknownDelegator", + "type": "error" + }, + { + "inputs": [], + "name": "UnnecessaryNativeTokenReceived", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroValue", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "Token", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "FeesWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint128", + "name": "pairId", + "type": "uint128" + }, + { + "indexed": true, + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "Token", + "name": "token1", + "type": "address" + } + ], + "name": "PairCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "Token", + "name": "token1", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "prevFeePPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "newFeePPM", + "type": "uint32" + } + ], + "name": "PairTradingFeePPMUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "Token", + "name": "token1", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct Order", + "name": "order0", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct Order", + "name": "order1", + "type": "tuple" + } + ], + "name": "StrategyCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "Token", + "name": "token1", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct Order", + "name": "order0", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct Order", + "name": "order1", + "type": "tuple" + } + ], + "name": "StrategyDeleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "indexed": true, + "internalType": "Token", + "name": "token1", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct Order", + "name": "order0", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "indexed": false, + "internalType": "struct Order", + "name": "order1", + "type": "tuple" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "reason", + "type": "uint8" + } + ], + "name": "StrategyUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "trader", + "type": "address" + }, + { + "indexed": true, + "internalType": "Token", + "name": "sourceToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "Token", + "name": "targetToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "sourceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "targetAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "tradingFeeAmount", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "bool", + "name": "byTargetAmount", + "type": "bool" + } + ], + "name": "TokensTraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "prevFeePPM", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "newFeePPM", + "type": "uint32" + } + ], + "name": "TradingFeePPMUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "token", + "type": "address" + } + ], + "name": "accumulatedFees", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "sourceToken", + "type": "address" + }, + { + "internalType": "Token", + "name": "targetToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "strategyId", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "amount", + "type": "uint128" + } + ], + "internalType": "struct TradeAction[]", + "name": "tradeActions", + "type": "tuple[]" + } + ], + "name": "calculateTradeSourceAmount", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "sourceToken", + "type": "address" + }, + { + "internalType": "Token", + "name": "targetToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "strategyId", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "amount", + "type": "uint128" + } + ], + "internalType": "struct TradeAction[]", + "name": "tradeActions", + "type": "tuple[]" + } + ], + "name": "calculateTradeTargetAmount", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "controllerType", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "internalType": "Token", + "name": "token1", + "type": "address" + } + ], + "name": "createPair", + "outputs": [ + { + "components": [ + { + "internalType": "uint128", + "name": "id", + "type": "uint128" + }, + { + "internalType": "Token[2]", + "name": "tokens", + "type": "address[2]" + } + ], + "internalType": "struct Pair", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "internalType": "Token", + "name": "token1", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "internalType": "struct Order[2]", + "name": "orders", + "type": "tuple[2]" + } + ], + "name": "createStrategy", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "strategyId", + "type": "uint256" + } + ], + "name": "deleteStrategy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "internalType": "Token", + "name": "token1", + "type": "address" + } + ], + "name": "pair", + "outputs": [ + { + "components": [ + { + "internalType": "uint128", + "name": "id", + "type": "uint128" + }, + { + "internalType": "Token[2]", + "name": "tokens", + "type": "address[2]" + } + ], + "internalType": "struct Pair", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "internalType": "Token", + "name": "token1", + "type": "address" + } + ], + "name": "pairTradingFeePPM", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pairs", + "outputs": [ + { + "internalType": "Token[2][]", + "name": "", + "type": "address[2][]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "postUpgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "roleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "roleEmergencyStopper", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "roleFeesManager", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "internalType": "Token", + "name": "token1", + "type": "address" + }, + { + "internalType": "uint32", + "name": "newPairTradingFeePPM", + "type": "uint32" + } + ], + "name": "setPairTradingFeePPM", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "newTradingFeePPM", + "type": "uint32" + } + ], + "name": "setTradingFeePPM", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "internalType": "Token", + "name": "token1", + "type": "address" + }, + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "endIndex", + "type": "uint256" + } + ], + "name": "strategiesByPair", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "Token[2]", + "name": "tokens", + "type": "address[2]" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "internalType": "struct Order[2]", + "name": "orders", + "type": "tuple[2]" + } + ], + "internalType": "struct Strategy[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "token0", + "type": "address" + }, + { + "internalType": "Token", + "name": "token1", + "type": "address" + } + ], + "name": "strategiesByPairCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "strategy", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "Token[2]", + "name": "tokens", + "type": "address[2]" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "internalType": "struct Order[2]", + "name": "orders", + "type": "tuple[2]" + } + ], + "internalType": "struct Strategy", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "sourceToken", + "type": "address" + }, + { + "internalType": "Token", + "name": "targetToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "strategyId", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "amount", + "type": "uint128" + } + ], + "internalType": "struct TradeAction[]", + "name": "tradeActions", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "minReturn", + "type": "uint128" + } + ], + "name": "tradeBySourceAmount", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "sourceToken", + "type": "address" + }, + { + "internalType": "Token", + "name": "targetToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "strategyId", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "amount", + "type": "uint128" + } + ], + "internalType": "struct TradeAction[]", + "name": "tradeActions", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "maxInput", + "type": "uint128" + } + ], + "name": "tradeByTargetAmount", + "outputs": [ + { + "internalType": "uint128", + "name": "", + "type": "uint128" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "tradingFeePPM", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "strategyId", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "internalType": "struct Order[2]", + "name": "currentOrders", + "type": "tuple[2]" + }, + { + "components": [ + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "internalType": "struct Order[2]", + "name": "newOrders", + "type": "tuple[2]" + } + ], + "name": "updateStrategy", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "Token", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "withdrawFees", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + } +] as const; + +export type CarbonController = typeof carbonControllerAbi; +export type CarbonControllerContract = GetContractReturnType; + +export class CarbonController__factory { + static connect(address: string, client: PublicClient) { + return getContract({ address, abi: carbonControllerAbi, publicClient: client }); + } +} diff --git a/src/apps/carbon-defi/contracts/viem/Voucher.ts b/src/apps/carbon-defi/contracts/viem/Voucher.ts new file mode 100644 index 000000000..b275ade88 --- /dev/null +++ b/src/apps/carbon-defi/contracts/viem/Voucher.ts @@ -0,0 +1,956 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import { getContract, GetContractReturnType, PublicClient } from 'viem'; + +export const voucherAbi = [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [], + "name": "AccessDenied", + "type": "error" + }, + { + "inputs": [], + "name": "AlreadyInitialized", + "type": "error" + }, + { + "inputs": [], + "name": "BatchNotSupported", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidIndices", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "newBaseExtension", + "type": "string" + } + ], + "name": "BaseExtensionUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "newBaseURI", + "type": "string" + } + ], + "name": "BaseURIUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "newUseGlobalURI", + "type": "bool" + } + ], + "name": "UseGlobalURIUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "newUseGlobalURI", + "type": "bool" + }, + { + "internalType": "string", + "name": "newBaseURI", + "type": "string" + }, + { + "internalType": "string", + "name": "newBaseExtension", + "type": "string" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "postUpgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "roleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "roleMinter", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "newBaseExtension", + "type": "string" + } + ], + "name": "setBaseExtension", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "newBaseURI", + "type": "string" + } + ], + "name": "setBaseURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "startIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "endIndex", + "type": "uint256" + } + ], + "name": "tokensByOwner", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "newUseGlobalURI", + "type": "bool" + } + ], + "name": "useGlobalURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + } +] as const; + +export type Voucher = typeof voucherAbi; +export type VoucherContract = GetContractReturnType; + +export class Voucher__factory { + static connect(address: string, client: PublicClient) { + return getContract({ address, abi: voucherAbi, publicClient: client }); + } +} diff --git a/src/apps/carbon-defi/contracts/viem/index.ts b/src/apps/carbon-defi/contracts/viem/index.ts new file mode 100644 index 000000000..3cfdbb767 --- /dev/null +++ b/src/apps/carbon-defi/contracts/viem/index.ts @@ -0,0 +1,9 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ + +export type { CarbonController } from './CarbonController'; +export type { Voucher } from './Voucher'; + +export { CarbonController__factory } from './CarbonController'; +export { Voucher__factory } from './Voucher'; diff --git a/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts b/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts new file mode 100644 index 000000000..39d103254 --- /dev/null +++ b/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts @@ -0,0 +1,142 @@ +import { Inject } from '@nestjs/common'; +import { BigNumberish } from 'ethers'; +import { sumBy } from 'lodash'; + +import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; +import { ETH_ADDR_ALIAS, ZERO_ADDRESS } from '~app-toolkit/constants/address'; +import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; +import { drillBalance } from '~app-toolkit/helpers/drill-balance.helper'; +import { ContractPositionBalance } from '~position/position-balance.interface'; +import { ContractPosition, MetaType } from '~position/position.interface'; +import { ContractPositionTemplatePositionFetcher } from '~position/template/contract-position.template.position-fetcher'; +import { + DefaultContractPositionDefinition, + UnderlyingTokenDefinition, + GetTokenBalancesParams, + GetTokenDefinitionsParams, + GetDisplayPropsParams, + GetDataPropsParams, +} from '~position/template/contract-position.template.types'; + +import { CarbonDefiViemContractFactory } from '../contracts'; +import { CarbonController } from '../contracts/viem/CarbonController'; + +interface Order { + y: bigint; + z: bigint; + A: bigint; + B: bigint; +} + +interface Strategy { + id: bigint; + owner: string; + tokens: readonly [string, string]; + orders: readonly [Order, Order]; +} + +interface StrategyDefinition extends DefaultContractPositionDefinition { + strategy: Strategy; +} + +type StrategyProps = { + strategy: Strategy; +}; + +function isActiveStrategy(strategy: Strategy) { + const [buy, sell] = strategy.orders; + return !!buy.A || !!buy.B || !!sell.A || !!sell.B; +} + +@PositionTemplate() +export class EthereumCarbonDefiStrategyContractPositionFetcher extends ContractPositionTemplatePositionFetcher< + CarbonController, + StrategyProps, + StrategyDefinition +> { + groupId = 'strategy'; + groupLabel = 'Carbon Defi'; + + constructor( + @Inject(APP_TOOLKIT) protected readonly appToolkit: IAppToolkit, + @Inject(CarbonDefiViemContractFactory) protected readonly factory: CarbonDefiViemContractFactory, + ) { + super(appToolkit); + } + + getContract() { + return this.factory.carbonController(); + } + + override async getDataProps(params: GetDataPropsParams) { + return { strategy: params.definition.strategy }; + } + + override async filterPositionsForAddress( + address: string, + positions: ContractPosition[], + ): Promise[]> { + return positions.filter(position => { + const owner = position.dataProps.strategy.owner; + return owner.toLowerCase() === address.toLowerCase(); + }); + } + + // Override the getBalance query to keep token with budget set to 0 + override async getBalances(address: string): Promise[]> { + const multicall = this.appToolkit.getViemMulticall(this.network); + if (address === ZERO_ADDRESS) return []; + + const contractPositions = await this.getPositionsForBalances(); + const filteredPositions = await this.filterPositionsForAddress(address, contractPositions); + + const balances = await Promise.all( + filteredPositions.map(async contractPosition => { + const contract = multicall.wrap(this.getContract()); + const balancesRaw = await this.getTokenBalancesPerPosition({ address, contract, contractPosition, multicall }); + const tokens = contractPosition.tokens.map((cp, idx) => + drillBalance(cp, balancesRaw[idx]?.toString() ?? '0', { isDebt: cp.metaType === MetaType.BORROWED }), + ); + return { + ...contractPosition, + balanceUSD: sumBy(tokens, t => t.balanceUSD), + tokens, + }; + }), + ); + + return balances; + } + + async getLabel(params: GetDisplayPropsParams): Promise { + const tokens = params.contractPosition.tokens; + return `${tokens[0].symbol} / ${tokens[1].symbol}`; + } + + async getDefinitions(): Promise { + const contract = this.getContract(); + const address = contract.address; + const pairs = await contract.read.pairs(); + const getStrategies = pairs.map(pair => contract.read.strategiesByPair([...pair, BigInt(0), BigInt(0)])); + const strategies = await Promise.all(getStrategies).then(matrix => matrix.flat()); + return strategies.filter(isActiveStrategy).map(strategy => ({ address, strategy: strategy })); + } + + async getTokenDefinitions( + params: GetTokenDefinitionsParams, + ): Promise { + return params.definition.strategy.tokens.map(address => ({ + address: address.toLowerCase().replace(ETH_ADDR_ALIAS, ZERO_ADDRESS), + metaType: MetaType.SUPPLIED, + network: this.network, + })); + } + + async getTokenBalancesPerPosition( + params: GetTokenBalancesParams, + ): Promise { + const strategy = params.contractPosition.dataProps.strategy; + const [buy, sell] = strategy.orders; + return [buy.y, sell.y]; + } +} From 5ef4bfc3b3b82646bcc5bf79a92c11fe66c141ae Mon Sep 17 00:00:00 2001 From: GrandSchtroumpf Date: Mon, 29 Jan 2024 10:17:36 +0100 Subject: [PATCH 2/8] refactor(request changes) --- .../carbon-defi/contracts/viem.contract-factory.ts | 10 ++++------ .../carbon-defi.strategy.contract-position-fetcher.ts | 7 +++++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/apps/carbon-defi/contracts/viem.contract-factory.ts b/src/apps/carbon-defi/contracts/viem.contract-factory.ts index c40dcf0e8..c2cdc090b 100644 --- a/src/apps/carbon-defi/contracts/viem.contract-factory.ts +++ b/src/apps/carbon-defi/contracts/viem.contract-factory.ts @@ -5,18 +5,16 @@ import { Network } from '~types/network.interface'; import { CarbonController__factory, Voucher__factory } from './viem'; +type ContractOpts = { address: string; network: Network; }; + @Injectable() export class CarbonDefiViemContractFactory { constructor(@Inject(APP_TOOLKIT) protected readonly appToolkit: IAppToolkit) { } - carbonController() { - const address = '0xc537e898cd774e2dcba3b14ea6f34c93d5ea45e1'; - const network = Network.ETHEREUM_MAINNET; + carbonController({ address, network }: ContractOpts) { return CarbonController__factory.connect(address, this.appToolkit.getViemNetworkProvider(network)); } - voucher() { - const address = '0x3660f04b79751e31128f6378eac70807e38f554e'; - const network = Network.ETHEREUM_MAINNET; + voucher({ address, network }: ContractOpts) { return Voucher__factory.connect(address, this.appToolkit.getViemNetworkProvider(network)); } } diff --git a/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts b/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts index 39d103254..9d2de2b4c 100644 --- a/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts +++ b/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts @@ -17,6 +17,7 @@ import { GetDisplayPropsParams, GetDataPropsParams, } from '~position/template/contract-position.template.types'; +import { Network } from '~types'; import { CarbonDefiViemContractFactory } from '../contracts'; import { CarbonController } from '../contracts/viem/CarbonController'; @@ -54,7 +55,6 @@ export class EthereumCarbonDefiStrategyContractPositionFetcher extends ContractP StrategyProps, StrategyDefinition > { - groupId = 'strategy'; groupLabel = 'Carbon Defi'; constructor( @@ -65,7 +65,10 @@ export class EthereumCarbonDefiStrategyContractPositionFetcher extends ContractP } getContract() { - return this.factory.carbonController(); + return this.factory.carbonController({ + address: '0xc537e898cd774e2dcba3b14ea6f34c93d5ea45e1', + network: Network.ETHEREUM_MAINNET, + }); } override async getDataProps(params: GetDataPropsParams) { From e6464c4516bb88b081ba81de2c77f02b32e7c74a Mon Sep 17 00:00:00 2001 From: GrandSchtroumpf Date: Wed, 31 Jan 2024 10:26:28 +0100 Subject: [PATCH 3/8] refactor(carbon-defi) use customContractPosition --- ...defi.strategy.contract-position-fetcher.ts | 100 ++++++++++-------- 1 file changed, 53 insertions(+), 47 deletions(-) diff --git a/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts b/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts index 9d2de2b4c..ac279b7d7 100644 --- a/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts +++ b/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts @@ -6,17 +6,16 @@ import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; import { ETH_ADDR_ALIAS, ZERO_ADDRESS } from '~app-toolkit/constants/address'; import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; import { drillBalance } from '~app-toolkit/helpers/drill-balance.helper'; -import { ContractPositionBalance } from '~position/position-balance.interface'; -import { ContractPosition, MetaType } from '~position/position.interface'; -import { ContractPositionTemplatePositionFetcher } from '~position/template/contract-position.template.position-fetcher'; +import { ContractPositionBalance, RawContractPositionBalance } from '~position/position-balance.interface'; +import { MetaType } from '~position/position.interface'; import { DefaultContractPositionDefinition, UnderlyingTokenDefinition, - GetTokenBalancesParams, GetTokenDefinitionsParams, GetDisplayPropsParams, GetDataPropsParams, } from '~position/template/contract-position.template.types'; +import { CustomContractPositionTemplatePositionFetcher } from '~position/template/custom-contract-position.template.position-fetcher'; import { Network } from '~types'; import { CarbonDefiViemContractFactory } from '../contracts'; @@ -50,7 +49,7 @@ function isActiveStrategy(strategy: Strategy) { } @PositionTemplate() -export class EthereumCarbonDefiStrategyContractPositionFetcher extends ContractPositionTemplatePositionFetcher< +export class EthereumCarbonDefiStrategyContractPositionFetcher extends CustomContractPositionTemplatePositionFetcher< CarbonController, StrategyProps, StrategyDefinition @@ -75,42 +74,6 @@ export class EthereumCarbonDefiStrategyContractPositionFetcher extends ContractP return { strategy: params.definition.strategy }; } - override async filterPositionsForAddress( - address: string, - positions: ContractPosition[], - ): Promise[]> { - return positions.filter(position => { - const owner = position.dataProps.strategy.owner; - return owner.toLowerCase() === address.toLowerCase(); - }); - } - - // Override the getBalance query to keep token with budget set to 0 - override async getBalances(address: string): Promise[]> { - const multicall = this.appToolkit.getViemMulticall(this.network); - if (address === ZERO_ADDRESS) return []; - - const contractPositions = await this.getPositionsForBalances(); - const filteredPositions = await this.filterPositionsForAddress(address, contractPositions); - - const balances = await Promise.all( - filteredPositions.map(async contractPosition => { - const contract = multicall.wrap(this.getContract()); - const balancesRaw = await this.getTokenBalancesPerPosition({ address, contract, contractPosition, multicall }); - const tokens = contractPosition.tokens.map((cp, idx) => - drillBalance(cp, balancesRaw[idx]?.toString() ?? '0', { isDebt: cp.metaType === MetaType.BORROWED }), - ); - return { - ...contractPosition, - balanceUSD: sumBy(tokens, t => t.balanceUSD), - tokens, - }; - }), - ); - - return balances; - } - async getLabel(params: GetDisplayPropsParams): Promise { const tokens = params.contractPosition.tokens; return `${tokens[0].symbol} / ${tokens[1].symbol}`; @@ -135,11 +98,54 @@ export class EthereumCarbonDefiStrategyContractPositionFetcher extends ContractP })); } - async getTokenBalancesPerPosition( - params: GetTokenBalancesParams, - ): Promise { - const strategy = params.contractPosition.dataProps.strategy; - const [buy, sell] = strategy.orders; - return [buy.y, sell.y]; + async getBalances(address: string): Promise[]> { + if (address === ZERO_ADDRESS) return []; + + const positions = await this.getPositions(); + const balances: ContractPositionBalance[] = []; + for (const position of positions) { + const { owner, orders } = position.dataProps.strategy; + if (owner.toLowerCase() !== address.toLowerCase()) continue; + const tokens = [ + drillBalance(position.tokens[0], orders[0].y.toString() ?? '0'), + drillBalance(position.tokens[1], orders[1].y.toString() ?? '0'), + ]; + balances.push({ + ...position, + balanceUSD: sumBy(tokens, t => t.balanceUSD), + tokens, + }); + } + return balances; + } + + async getRawBalances(address: string): Promise { + if (address === ZERO_ADDRESS) return []; + + const positions = await this.getPositions(); + const balances: RawContractPositionBalance[] = []; + for (const position of positions) { + const { owner, orders } = position.dataProps.strategy; + if (owner.toLowerCase() !== address.toLowerCase()) continue; + balances.push({ + key: this.appToolkit.getPositionKey(position), + tokens: [ + { + key: this.appToolkit.getPositionKey(position.tokens[0]), + balance: orders[0].y.toString(), + }, + { + key: this.appToolkit.getPositionKey(position.tokens[1]), + balance: orders[1].y.toString(), + }, + ], + }); + } + return balances; + } + + // Unused since CustomContractPositionTemplatePositionFetcher forces Promise output while it can be sync + async getTokenBalancesPerPosition(): Promise { + return []; } } From 13958c7ece1d99bdcab5e41ead162c352029da16 Mon Sep 17 00:00:00 2001 From: GrandSchtroumpf Date: Wed, 31 Jan 2024 10:34:36 +0100 Subject: [PATCH 4/8] refactor(cardbon-defi) use getAppContractPositions --- ...-defi.strategy.contract-position-fetcher.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts b/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts index ac279b7d7..80a5049e4 100644 --- a/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts +++ b/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts @@ -7,7 +7,7 @@ import { ETH_ADDR_ALIAS, ZERO_ADDRESS } from '~app-toolkit/constants/address'; import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; import { drillBalance } from '~app-toolkit/helpers/drill-balance.helper'; import { ContractPositionBalance, RawContractPositionBalance } from '~position/position-balance.interface'; -import { MetaType } from '~position/position.interface'; +import { ContractPosition, MetaType } from '~position/position.interface'; import { DefaultContractPositionDefinition, UnderlyingTokenDefinition, @@ -101,7 +101,12 @@ export class EthereumCarbonDefiStrategyContractPositionFetcher extends CustomCon async getBalances(address: string): Promise[]> { if (address === ZERO_ADDRESS) return []; - const positions = await this.getPositions(); + const positions = await this.appToolkit.getAppContractPositions({ + appId: this.appId, + network: this.network, + groupIds: [this.groupId], + }); + const balances: ContractPositionBalance[] = []; for (const position of positions) { const { owner, orders } = position.dataProps.strategy; @@ -122,13 +127,18 @@ export class EthereumCarbonDefiStrategyContractPositionFetcher extends CustomCon async getRawBalances(address: string): Promise { if (address === ZERO_ADDRESS) return []; - const positions = await this.getPositions(); + const positions = await this.appToolkit.getAppContractPositions({ + appId: this.appId, + network: this.network, + groupIds: [this.groupId], + }); + const balances: RawContractPositionBalance[] = []; for (const position of positions) { const { owner, orders } = position.dataProps.strategy; if (owner.toLowerCase() !== address.toLowerCase()) continue; balances.push({ - key: this.appToolkit.getPositionKey(position), + key: this.appToolkit.getPositionKey(position as ContractPosition), tokens: [ { key: this.appToolkit.getPositionKey(position.tokens[0]), From 8af03c6beb8a1aa131228128c3d1296fbd957e05 Mon Sep 17 00:00:00 2001 From: GrandSchtroumpf Date: Wed, 31 Jan 2024 10:43:42 +0100 Subject: [PATCH 5/8] fix(carbon-defi) use type instead of interface --- .../carbon-defi.strategy.contract-position-fetcher.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts b/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts index 80a5049e4..fd5195ae8 100644 --- a/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts +++ b/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts @@ -7,7 +7,7 @@ import { ETH_ADDR_ALIAS, ZERO_ADDRESS } from '~app-toolkit/constants/address'; import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; import { drillBalance } from '~app-toolkit/helpers/drill-balance.helper'; import { ContractPositionBalance, RawContractPositionBalance } from '~position/position-balance.interface'; -import { ContractPosition, MetaType } from '~position/position.interface'; +import { MetaType } from '~position/position.interface'; import { DefaultContractPositionDefinition, UnderlyingTokenDefinition, @@ -35,9 +35,9 @@ interface Strategy { orders: readonly [Order, Order]; } -interface StrategyDefinition extends DefaultContractPositionDefinition { +type StrategyDefinition = DefaultContractPositionDefinition & { strategy: Strategy; -} +}; type StrategyProps = { strategy: Strategy; @@ -138,7 +138,7 @@ export class EthereumCarbonDefiStrategyContractPositionFetcher extends CustomCon const { owner, orders } = position.dataProps.strategy; if (owner.toLowerCase() !== address.toLowerCase()) continue; balances.push({ - key: this.appToolkit.getPositionKey(position as ContractPosition), + key: this.appToolkit.getPositionKey(position), tokens: [ { key: this.appToolkit.getPositionKey(position.tokens[0]), From 4afe7d6d1eff585843459ae401893f714b697814 Mon Sep 17 00:00:00 2001 From: GrandSchtroumpf Date: Wed, 31 Jan 2024 10:45:04 +0100 Subject: [PATCH 6/8] fix(carbon-defi) use NotImplementedException --- .../carbon-defi.strategy.contract-position-fetcher.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts b/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts index fd5195ae8..2a51ca48c 100644 --- a/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts +++ b/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts @@ -1,5 +1,4 @@ -import { Inject } from '@nestjs/common'; -import { BigNumberish } from 'ethers'; +import { Inject, NotImplementedException } from '@nestjs/common'; import { sumBy } from 'lodash'; import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; @@ -155,7 +154,7 @@ export class EthereumCarbonDefiStrategyContractPositionFetcher extends CustomCon } // Unused since CustomContractPositionTemplatePositionFetcher forces Promise output while it can be sync - async getTokenBalancesPerPosition(): Promise { - return []; + getTokenBalancesPerPosition(): never { + throw new NotImplementedException(); } } From 7d477dbe34e3a78041117ad304b0413c19cbc955 Mon Sep 17 00:00:00 2001 From: GrandSchtroumpf Date: Fri, 2 Feb 2024 10:21:48 +0100 Subject: [PATCH 7/8] refactor(carbon-defi) do not put balance in dataProps --- ...defi.strategy.contract-position-fetcher.ts | 70 ++++++++++--------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts b/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts index 2a51ca48c..7ac51f06f 100644 --- a/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts +++ b/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts @@ -12,7 +12,6 @@ import { UnderlyingTokenDefinition, GetTokenDefinitionsParams, GetDisplayPropsParams, - GetDataPropsParams, } from '~position/template/contract-position.template.types'; import { CustomContractPositionTemplatePositionFetcher } from '~position/template/custom-contract-position.template.position-fetcher'; import { Network } from '~types'; @@ -27,23 +26,18 @@ interface Order { B: bigint; } -interface Strategy { - id: bigint; +type StrategyDefinition = DefaultContractPositionDefinition & { + /** Used to generate the key, and to keep the strategy id around */ + positionKey: bigint; owner: string; tokens: readonly [string, string]; - orders: readonly [Order, Order]; -} - -type StrategyDefinition = DefaultContractPositionDefinition & { - strategy: Strategy; }; - type StrategyProps = { - strategy: Strategy; + positionKey: bigint; + owner: string; }; -function isActiveStrategy(strategy: Strategy) { - const [buy, sell] = strategy.orders; +function isActiveStrategy([buy, sell]: readonly [Order, Order]) { return !!buy.A || !!buy.B || !!sell.A || !!sell.B; } @@ -69,8 +63,9 @@ export class EthereumCarbonDefiStrategyContractPositionFetcher extends CustomCon }); } - override async getDataProps(params: GetDataPropsParams) { - return { strategy: params.definition.strategy }; + override async getDataProps(params) { + const { owner, positionKey } = params.definition; + return { owner, positionKey }; } async getLabel(params: GetDisplayPropsParams): Promise { @@ -84,13 +79,18 @@ export class EthereumCarbonDefiStrategyContractPositionFetcher extends CustomCon const pairs = await contract.read.pairs(); const getStrategies = pairs.map(pair => contract.read.strategiesByPair([...pair, BigInt(0), BigInt(0)])); const strategies = await Promise.all(getStrategies).then(matrix => matrix.flat()); - return strategies.filter(isActiveStrategy).map(strategy => ({ address, strategy: strategy })); + const definitions: StrategyDefinition[] = []; + for (const { id, owner, tokens, orders } of strategies) { + if (!isActiveStrategy(orders)) continue; + definitions.push({ address, positionKey: id, owner, tokens }); + } + return definitions; } async getTokenDefinitions( params: GetTokenDefinitionsParams, ): Promise { - return params.definition.strategy.tokens.map(address => ({ + return params.definition.tokens.map(address => ({ address: address.toLowerCase().replace(ETH_ADDR_ALIAS, ZERO_ADDRESS), metaType: MetaType.SUPPLIED, network: this.network, @@ -99,44 +99,46 @@ export class EthereumCarbonDefiStrategyContractPositionFetcher extends CustomCon async getBalances(address: string): Promise[]> { if (address === ZERO_ADDRESS) return []; - + const controller = this.getContract(); const positions = await this.appToolkit.getAppContractPositions({ appId: this.appId, network: this.network, groupIds: [this.groupId], }); + const ownedPositions = positions.filter(position => { + return position.dataProps.owner.toLowerCase() === address.toLowerCase(); + }); - const balances: ContractPositionBalance[] = []; - for (const position of positions) { - const { owner, orders } = position.dataProps.strategy; - if (owner.toLowerCase() !== address.toLowerCase()) continue; + const getAllBalances = ownedPositions.map(async position => { + const { orders } = await controller.read.strategy([position.dataProps.positionKey]); const tokens = [ drillBalance(position.tokens[0], orders[0].y.toString() ?? '0'), drillBalance(position.tokens[1], orders[1].y.toString() ?? '0'), ]; - balances.push({ + return { ...position, balanceUSD: sumBy(tokens, t => t.balanceUSD), tokens, - }); - } - return balances; + }; + }); + return Promise.all(getAllBalances); } async getRawBalances(address: string): Promise { if (address === ZERO_ADDRESS) return []; - + const controller = this.getContract(); const positions = await this.appToolkit.getAppContractPositions({ appId: this.appId, network: this.network, groupIds: [this.groupId], }); + const ownedPositions = positions.filter(position => { + return position.dataProps.owner.toLowerCase() === address.toLowerCase(); + }); - const balances: RawContractPositionBalance[] = []; - for (const position of positions) { - const { owner, orders } = position.dataProps.strategy; - if (owner.toLowerCase() !== address.toLowerCase()) continue; - balances.push({ + const getAllBalances = ownedPositions.map(async position => { + const { orders } = await controller.read.strategy([position.dataProps.positionKey]); + return { key: this.appToolkit.getPositionKey(position), tokens: [ { @@ -148,9 +150,9 @@ export class EthereumCarbonDefiStrategyContractPositionFetcher extends CustomCon balance: orders[1].y.toString(), }, ], - }); - } - return balances; + }; + }); + return Promise.all(getAllBalances); } // Unused since CustomContractPositionTemplatePositionFetcher forces Promise output while it can be sync From 649fc1423cc267268ba9c0307bda52599b55bd98 Mon Sep 17 00:00:00 2001 From: GrandSchtroumpf Date: Thu, 15 Feb 2024 18:08:23 +0100 Subject: [PATCH 8/8] update active strategy filter --- .../ethereum/carbon-defi.strategy.contract-position-fetcher.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts b/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts index 7ac51f06f..7751277ce 100644 --- a/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts +++ b/src/apps/carbon-defi/ethereum/carbon-defi.strategy.contract-position-fetcher.ts @@ -38,7 +38,7 @@ type StrategyProps = { }; function isActiveStrategy([buy, sell]: readonly [Order, Order]) { - return !!buy.A || !!buy.B || !!sell.A || !!sell.B; + return !!buy.y || !!sell.y; } @PositionTemplate()