diff --git a/typescript/aqua/LICENSE b/typescript/aqua/LICENSE deleted file mode 100644 index 1a2fef7..0000000 --- a/typescript/aqua/LICENSE +++ /dev/null @@ -1,105 +0,0 @@ -DEGENSOFT AQUA SOURCE LICENSE (Aqua-Source-1.1) -Copyright © 2025 Degensoft Ltd. All rights reserved. -SPDX-License-Identifier: LicenseRef-Degensoft-Aqua-Source-1.1 - -Aqua License — Summary (non-binding): You may read, use, deploy, and call Aqua (Core/Router/App). If you Modify and distribute/deploy the Modified version, you must release your changes under this same license. NO Commercial License is required until you cross a Commercial Trigger (e.g., Charged Fees > US$100,000 in any rolling 12-month period or in any single calendar month, or Liquidity Under Control > US$10,000,000). This summary is for convenience only. - - - -1) Definitions -1.1 “Licensed Work” means the Aqua stack as released in this repository, including: (a) the Aqua protocol core, Aqua Router, Aqua App (strategy runner), and all related smart contracts, source code, bytecode/object code, ABIs, deployment scripts, configuration, test suites, example strategies, simulators, developer tooling, SDK snippets, schemas, and interface specifications (including any “Aqua Manifest” or similar artifacts); (b) all documentation and technical specifications published by Degensoft; and (c) all updates, patches, and new versions of the foregoing that Degensoft publishes under this license. - -1.2 “Charged Fees” means all monetary or in-kind value (fiat, crypto, tokens, credits, rebates, or other consideration) that You or Your Affiliates directly or indirectly receive or accrue in connection with operating, offering, or providing access to any product or service that is powered by, routed through, or materially enabled by the Licensed Work, including without limitation: (a) swap/trade/execution fees, positive-slippage capture, spreads, mark-ups, retained priority/tips; (b) maker/taker rebates, order-flow payments, routing/referral/affiliate fees, MEV/builder/bundle payments and other extractable-value shares; (c) subscription, seat, usage, API, or platform fees attributable to the Licensed Work; (d) performance/incentive/carried-interest fees, revenue shares, or similar participation; and (e) token grants, rewards, airdrops, distributions, or rebates received by or for You or Your Affiliates in consideration of or tied to such operations. Charged Fees are measured on a gross-receipts basis at fair-market value in USD when received or accrued, include amounts received by agents/designees or wallets You control, and must be reasonably allocated for bundles. Anti-avoidance: relabeling, splitting, routing through Affiliates/Related Parties, offsetting, or deferring does not exclude amounts; Affiliates/common control are aggregated; the Control or Benefit Principle applies. - -1.3 “Commercial License” means a separate written agreement between Degensoft and You (and/or Your Affiliates), that grants You the right to engage in Commercial Use of the Licensed Work subject to negotiated terms, conditions, and fees. - -1.4 “Control or Benefit Principle” means triggers and obligations apply where you or your Affiliates control the relevant activity or benefit economically from it (directly or through agents/DAOs under your direction). - -1.5 “Rolling Year” means any period of twelve (12) consecutive months measured on a rolling basis. - -1.6 “Liquidity Under Control (LUC)” means the aggregate fair-market USD value of real, non-synthetic, non-levered, withdrawable assets that Your (or Your Affiliates’/agents’) products, services, or code can instruct or cause to be moved or committed via the Licensed Work (e.g., wallet balances under automated control, committed liquidity, or programmatic authorization) at the time assessed. - -1.7 “Modification.” means any change to, or work based on or incorporating, the Licensed Work, including static/dynamic linking, proxy/delegatecall composition, bundled plug-ins/adapters/modules, instruction sets executing in the same virtual machine/address space, or artifacts shipped/deployed together as one product. - -1.8 “You” (and “Your”) means the individual or legal entity exercising rights under this license, and its Affiliates. “Affiliates” are entities controlling, controlled by, or under common control with a party, directly or indirectly. - -2) Grant -2.1 Subject to Sections 3–11, Degensoft grants you and your Affiliates a worldwide, non-exclusive license to use, copy, and distribute unmodified source/object forms of the Licensed Work. - -2.2 Pure Caller Use (Integration-Only / Non-Modifying). Pure Caller Use means building or operating products or services that interact with the Licensed Work solely by forming calldata, submitting transactions, or reading state through published ABIs, APIs, or RPC endpoints, without distributing any Modified Work and without providing strategy-building or execution as a service for third parties. Pure Caller Use is permitted under this License and does not, by itself, trigger any payment obligations or Commercial License. However, if in connection with Pure Caller Use You or Your Affiliates (a) charge or retain any fees, spreads, rebates, incentives, or other consideration; (b) meet any Trigger in Section 5.2; such use constitutes Commercial Use and requires obtaining a Commercial License from Degensoft. Even where Pure Caller Use is not met, see §5.3 for the current enforcement waiver applicable to Volume Activities. - -2.3 Audit/Research Safe Harbor. Security auditors and researchers may compile, test, and report on the Licensed Work in the course of good-faith security review. - -2.4 For any distribution, public display, public performance, publication, reporting, disclosure, or other public communication of any portion of the Licensed Work or any analysis, results, or outputs derived from the Licensed Work, You must preserve all existing copyright, license, and attribution notices included in the Licensed Work and must include a reasonable attribution identifying the source as “Aqua — © Degensoft Ltd 2025” (or any successor notice included in the Licensed Work). - -3) Copyleft for Modifications & Extensions -3.1 If you Modify or distribute any portion of the Licensed Work, you must: - -A. Publish under this same license (LicenseRef-Degensoft-Aqua-Source-1.1), at no charge, complete corresponding source of any portions of Your work that modify, extend, incorporate, or otherwise rely on the Licensed Work; - -B. Preserve existing copyright, license, and third-party notices; - -C. Add prominent attribution: “Powered by Aqua — © Degensoft Ltd 2025” in repository README and UI where applicable; - -D. Clearly mark changes and date of change; - -E. Provide build and deployment instructions sufficient for reproducibility. - -3.2 This copyleft covers all forms of Modification, combination, or use of the Licensed Work in or with other code, products, or systems. - -3.3 The obligations in §§3.1 A-B apply only to components that are derivative of the Licensed Work. Independent code that simply calls, interfaces with, or is distributed alongside the Licensed Work is not subject to this requirement. - -4) Non-Commercial Free Use -Non-commercial use (including experimentation, prototyping, hackathons, research, community pilots) is free of charge, subject to Section 3 for any Modifications; and provided that such use does not constitute or involve any activity described in Section 5. - -5) Commercial Triggers -5.1 Commercial Use: Any Commercial Use of the Licensed Work requires a Commercial License from Degensoft, unless otherwise expressly stated. Commercial Use means any use of the Licensed Work that provides, enables, or is integrated into any product, service, system, workflow, or operation from which You or Your Affiliates derive, or reasonably expect to derive, monetary or in-kind commercial value, directly or indirectly, including through Charged Fees or other consideration. - -5.2 Without limiting §5.1, You (and Your Affiliates) must obtain a Commercial License from Degensoft if any of the following occur: - -A. Aggregated Fees Trigger: Your aggregated Charged Fees attributable to usage of the Licensed Work exceed USD 100,000 in any Rolling Year. -B. LUC Trigger: Your LUC exceeds USD 10,000,000 at any time. -C. Operator/Liquidity Provider Direct-Use: You (or Your Affiliate) operate instruction programs or services that directly exercise the Licensed Work (bypassing 1inch/Aqua/Degensoft or other permitted/licensed interfaces) to capture fees or value and, in doing so, satisfy Triggers A or B above. -You must aggregate commonly-controlled/Affiliated entities; no disaggregation, white-labeling, or similar structuring to avoid a Trigger is permitted. The Control or Benefit Principle applies. - -5.3. Notwithstanding §§ 5.1 - 5.2, Degensoft presently waives enforcement of the Commercial Triggers for parties whose activities consist primarily of routing order flow, aggregation, arbitrage, or market-making through the Licensed Work (“Volume Activities”), including where such parties (i) trade with their own or third-party capital and/or (ii) charge or retain fees, spreads, rebates, or other compensation. This waiver is not a license, creates no reliance rights, and is revocable by Degensoft at any time in its sole discretion, including with respect to existing users, by (a) public notice in the project repository or (b) direct notice. Upon notice of revocation, you must within ten (10) days cease the Volume Activities or obtain a Commercial License; continued use thereafter constitutes an unauthorized Commercial Use and entitles Degensoft to pursue all remedies available. This waiver does not excuse past breaches unrelated to this subsection. - -5.4 Crossing any Trigger or any other Commercial Use requires you to contact Degensoft within 15 days at license@degensoft.com to execute Commercial License. Commercial License terms are confidential and may change. - -6) Audit -Once per year, Degensoft may request an independent revenue/LUC audit (under NDA) at Degensoft’s expense; if under-reporting exceeds 5%, You reimburse reasonable audit costs in addition to other remedies. Degensoft may also request an additional attestation “for cause” (objective indications of a Trigger). You must reasonably cooperate with any such attestation, including providing accurate records, logs, and other information reasonably necessary - -7) Additional Intellectual Property Terms -7.1 Patents. Degensoft grants a limited, non-exclusive, worldwide license under Degensoft’s patent claims that read on the Licensed Work solely to the extent necessary to exercise the rights expressly granted to You under this License. Nothing in this License grants You any right to patent, claim, or seek protection for (a) the Licensed Work (whether modified or unmodified), (b) any Modification of the Licensed Work, or (c) any work or system that incorporates, combines with, or depends on the Licensed Work. This patent license terminates if you (or your Affiliates) stop using the Licensed Work or assert any patent claim against Degensoft or compliant users of the Licensed Work. No implied patent license is granted beyond this clause. - -7.2 Trademarks & Branding. Trademarks. No rights are granted to use any Degensoft/ Aqua/ 1inch names, logos, or trademarks, or any “Powered by Aqua” or similar designation, except solely to make truthful statements of compatibility or integration. Any use must comply with Degensoft’s brand guidelines and may require separate written permission. - -7.3 Except as expressly granted, no other rights (by implication, estoppel, or otherwise) are granted, copyrights, patents, trade secrets, trademarks, or other IP. - -7.4. You must not suggest Degensoft endorses or certifies Your product absent a written agreement. - -8) Warranty & Liability -THE LICENSED WORK IS PROVIDED BY DEGENSOFT “AS IS” AND “AS AVAILABLE,” WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND THAT OPERATION WILL BE UNINTERRUPTED OR ERROR-FREE. TO THE MAXIMUM EXTENT PERMITTED BY LAW, DEGENSOFT ITS AFFILIATES AND CONTRIBUTORS SHALL NOT BE LIABLE FOR INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, EXEMPLARY, OR PUNITIVE DAMAGES, OR LOST PROFITS/REVENUE/GOODWILL, ARISING FROM OR RELATED TO THIS LICENSE OR THE LICENSED WORK, EVEN IF ADVISED OF THE POSSIBILITY. - -Nothing in this Section limits Degensoft’s ability to seek injunctive relief without bond in addition to other remedies or to enforce Your obligations under this License. - -9) Termination -Material breach, including any breach of §§ 2-9, not cured within 15 days of notice terminates this License. Prior compliant distributions survive. Sections 2.4, 3, 8, 10, 11.3 survive termination. - -10) Governing Law; Venue; Injunctions -This License is governed by the laws of the State of New York, excluding conflict rules. The parties submit to the exclusive jurisdiction and venue of the state and federal courts located in New York County, New York (SDNY). Each party consents to injunctive relief (including specific performance) for actual or threatened breach. - -11) Notices; Third-Party Components; Assignment; Entire Agreement -11.1 Notices. Legal or any other notices to Degensoft: legal@degensoft.com (subject: “Aqua-Source-1.1 Notice”). - -11.2 Third-Party Components. Portions of the Licensed Work may incorporate, bundle, or reference third-party components governed by their own licenses. You must comply with those third-party terms; nothing in this License limits rights granted by those licenses. Preserve all third-party copyright and license notices. A list of such components and licenses is provided in THIRD_PARTY_NOTICES (and/or in file headers) and may be updated from time to time. - -11.3 Assignment. You may not assign this License (by law or otherwise) without Degensoft’s prior written consent; any unauthorized assignment is void. Degensoft may assign freely. - -11.4 Entire Agreement. This License is the entire agreement for the Licensed Work and supersedes prior understandings. If any provision is unenforceable, it will be modified to the minimum extent necessary to be enforceable; the remainder stays in effect. No waiver is effective unless in writing. - -12) Versioning -Degensoft may publish new or updated versions of this License from time to time. Each -release of the Licensed Work is governed by the license version identified in the -repository for that release. Degensoft may also re-release the Licensed Work, or any -portion of it, under different license terms in future releases. \ No newline at end of file diff --git a/typescript/aqua/README.md b/typescript/aqua/README.md deleted file mode 100644 index 05325c5..0000000 --- a/typescript/aqua/README.md +++ /dev/null @@ -1,490 +0,0 @@ -# @1inch/aqua-sdk - TypeScript SDK for 1inch Aqua Protocol - -A TypeScript SDK for encoding, decoding, and interacting with the 1inch Aqua Protocol smart contract. This SDK provides utilities for building transactions and parsing events for the Aqua Protocol's core operations. - -## Overview - -The Aqua Protocol is a decentralized protocol for liquidity management. This SDK simplifies integration by providing: - -- **Encoding/Decoding**: Build typed call data for `ship`, `dock` operations -- **Event Parsing**: Decode and parse `Pushed`, `Pulled`, `Shipped`, and `Docked` events -- **Multi-Chain Support**: Pre-configured addresses for 10+ blockchain networks - -For detailed protocol documentation, see the [Aqua Protocol Documentation](https://github.com/1inch/aqua#table-of-contents). - -## Installation - -```bash -pnpm add @1inch/aqua-sdk -``` - -## Quick Start - -```typescript -import { - AquaProtocolContract, - AQUA_CONTRACT_ADDRESSES, - Address, - HexString, - NetworkEnum -} from '@1inch/aqua-sdk' - -// Initialize the contract -const contractAddress = AQUA_CONTRACT_ADDRESSES[NetworkEnum.ETHEREUM] -const aqua = new AquaProtocolContract(contractAddress) - -// Build a ship transaction -const shipTx = aqua.ship({ - app: new Address('0x...'), - strategy: new HexString('0x...'), - amountsAndTokens: [ - { - token: new Address('0x...'), - amount: 1000000000000000000n, // 1 token with 18 decimals - }, - ], -}) - -// Use the transaction data -console.log(shipTx) // { to: '0x...', data: '0x...', value: 0n } -``` - -## Core Operations - -### Ship - -Initiates a liquidity strategy by setting virtual token balances for it. - -```typescript -const shipTx = aqua.ship({ - app: new Address('0x...'), - strategy: new HexString('0x...'), - amountsAndTokens: [ - { - token: new Address('0x...'), - amount: 1000000000000000000n, - }, - ], -}) -``` - -**Parameters:** -- `app` - Address of the application contract -- `strategy` - Strategy bytes containing execution logic -- `amountsAndTokens` - Array of token addresses and amounts to ship - -**Returns:** `CallInfo` object with encoded transaction data - -### Dock - -Completes a liquidity strategy by removing virtual token balances from it. - -```typescript -const strategyHash = AquaProtocolContract.calculateStrategyHash(strategy) - -const dockTx = aqua.dock({ - app: new Address('0x...'), - strategyHash: strategyHash, - tokens: [ - new Address('0x...'), - new Address('0x...'), - ], -}) -``` - -**Parameters:** -- `app` - Address of the application contract -- `strategyHash` - Keccak256 hash of the strategy bytes -- `tokens` - Array of token addresses to withdraw - -**Returns:** `CallInfo` object with encoded transaction data - -## Event Parsing - -### Pushed Event - -Emitted when funds are pushed to a strategy/wallet. - -```typescript -import { PushedEvent } from '@1inch/aqua-sdk' - -const log = { data: '0x...', topics: ['0x...'] } -const event = PushedEvent.fromLog(log) - -console.log(event.maker) // Address -console.log(event.app) // Address -console.log(event.strategyHash) // HexString -console.log(event.token) // Address -console.log(event.amount) // bigint -``` - -### Pulled Event - -Emitted when funds are pulled from a strategy/wallet. - -```typescript -import { PulledEvent } from '@1inch/aqua-sdk' - -const event = PulledEvent.fromLog(log) -``` - -### Shipped Event - -Emitted when a liquidity strategy is initiated. - -```typescript -import { ShippedEvent } from '@1inch/aqua-sdk' - -const event = ShippedEvent.fromLog(log) -``` - -### Docked Event - -Emitted when a liquidity strategy is closed. - -```typescript -import { DockedEvent } from '@1inch/aqua-sdk' - -const event = DockedEvent.fromLog(log) -``` - -## Utility Functions - -### Calculate Strategy Hash - -Convert strategy bytes to their keccak256 hash. - -```typescript -import { AquaProtocolContract } from '@1inch/aqua-sdk' -import { HexString } from '@1inch/sdk-core' - -const strategy = new HexString('0x...') -const hash = AquaProtocolContract.calculateStrategyHash(strategy) -``` - -### Encode Call Data - -Manually encode function call data if needed. - -```typescript -import { AquaProtocolContract } from '@1inch/aqua-sdk' - -const encodedShip = AquaProtocolContract.encodeShipCallData({ - app: new Address('0x...'), - strategy: new HexString('0x...'), - amountsAndTokens: [ /* ... */ ], -}) - -const encodedDock = AquaProtocolContract.encodeDockCallData({ - app: new Address('0x...'), - strategyHash: new HexString('0x...'), - tokens: [ /* ... */ ], -}) -``` - -## Supported Networks - -The SDK includes pre-configured contract addresses for the following networks: - -| Network | Chain ID | Address | -|---------|----------|---------| -| Ethereum | 1 | [0x499943e74fb0ce105688beee8ef2abec5d936d31](https://etherscan.io/address/0x499943e74fb0ce105688beee8ef2abec5d936d31) | -| BNB Chain | 56 | [0x499943e74fb0ce105688beee8ef2abec5d936d31](https://bscscan.com/address/0x499943e74fb0ce105688beee8ef2abec5d936d31) | -| Polygon | 137 | [0x499943e74fb0ce105688beee8ef2abec5d936d31](https://polygonscan.com/address/0x499943e74fb0ce105688beee8ef2abec5d936d31) | -| Arbitrum | 42161 | [0x499943e74fb0ce105688beee8ef2abec5d936d31](https://arbiscan.io/address/0x499943e74fb0ce105688beee8ef2abec5d936d31) | -| Avalanche | 43114 | [0x499943e74fb0ce105688beee8ef2abec5d936d31](http://snowscan.xyz/address/0x499943e74fb0ce105688beee8ef2abec5d936d31) | -| Gnosis | 100 | [0x499943e74fb0ce105688beee8ef2abec5d936d31](https://gnosisscan.io/address/0x499943e74fb0ce105688beee8ef2abec5d936d31) | -| Coinbase Base | 8453 | [0x499943e74fb0ce105688beee8ef2abec5d936d31](https://basescan.org/address/0x499943e74fb0ce105688beee8ef2abec5d936d31) | -| Optimism | 10 | [0x499943e74fb0ce105688beee8ef2abec5d936d31](https://optimistic.etherscan.io/address/0x499943e74fb0ce105688beee8ef2abec5d936d31) | -| zkSync Era | 324 | [0x499943e74fb0ce105688beee8ef2abec5d936d31](https://era.zksync.network/address/0x499943e74fb0ce105688beee8ef2abec5d936d31) | -| Linea | 59144 | [0x499943e74fb0ce105688beee8ef2abec5d936d31](https://lineascan.build/address/0x499943e74fb0ce105688beee8ef2abec5d936d31) | -| Unichain | 1301 | [0x499943e74fb0ce105688beee8ef2abec5d936d31](https://uniscan.xyz/address/0x499943e74fb0ce105688beee8ef2abec5d936d31) | -| Sonic | 146 | [0x499943e74fb0ce105688beee8ef2abec5d936d31](https://sonicscan.org/address/0x499943e74fb0ce105688beee8ef2abec5d936d31) | - -Access addresses using: - -```typescript -import { AQUA_CONTRACT_ADDRESSES } from '@1inch/aqua-sdk' -import { NetworkEnum } from '@1inch/sdk-core' - -const ethereumAddress = AQUA_CONTRACT_ADDRESSES[NetworkEnum.ETHEREUM] -const arbitrumAddress = AQUA_CONTRACT_ADDRESSES[NetworkEnum.ARBITRUM] -``` - -## API Reference - -### Exports - -The SDK exports: - -- **[`AquaProtocolContract`](./src/aqua-protocol-contract/aqua-protocol-contract.ts)** - Main contract class for encoding, decoding, and building transactions -- **[`AQUA_CONTRACT_ADDRESSES`](./src/aqua-protocol-contract/constants.ts)** - Pre-configured contract addresses by network -- **[`ABI`](./src/abi/)** - Contract ABI exports -- **[Types](./src/aqua-protocol-contract/types.ts)**: - - `ShipArgs` - - `DockArgs` - - `AmountsAndTokens` - - `EventAction` -- **[Event Classes](./src/aqua-protocol-contract/events/)**: - - `PushedEvent` - - `PulledEvent` - - `ShippedEvent` - - `DockedEvent` - -## Real-Life Examples - -### Example 1: Ship Liquidity to [XYCSwap.sol](https://github.com/1inch/aqua/blob/0637013a51cd56851f7b143a1f4500fdc93726cc/src/apps/XYCSwap.sol) aqua app - -Initialize a liquidity strategy by depositing tokens into Aqua's virtual balance system. - -```typescriptimport { AquaProtocolContract, Address, HexString, AQUA_CONTRACT_ADDRESSES, NetworkEnum } from '@1inch/aqua-sdk' -import { encodeAbiParameters, parseUnits, http, createWalletClient, isHex } from 'viem' -import { privateKeyToAccount, privateKeyToAddress } from 'viem/accounts' -import { mainnet } from 'viem/chains' -import assert from 'assert' -import 'dotenv/config' - -const makerPrivateKey = process.env.MAKER_PRIVATE_KEY - -assert(isHex(makerPrivateKey)) -const maker = privateKeyToAddress(makerPrivateKey) -const app = '0xTODO_REPLACE' -const WETH = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' -const USDC = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' - -// Define strategy based on the smart contract app structure. Each Aqua app can have it's own strategy schema -const strategyData = { - maker, - token0: WETH, - token1: USDC, - feeBps: 0n, - salt: '0x0000000000000000000000000000000000000000000000000000000000000001' -} as const - -// Encode strategy as bytes -const strategy = encodeAbiParameters( - [ - { - name: 'strategy', - type: 'tuple', - components: [ - { name: 'maker', type: 'address' }, - { name: 'token0', type: 'address' }, - { name: 'token1', type: 'address' }, - { name: 'feeBps', type: 'uint256' }, - { name: 'salt', type: 'bytes32' } - ] - } - ], - [strategyData] -) - -console.log('Encoded strategy:', strategy) - -// Initialize Aqua contract -const aqua = new AquaProtocolContract(AQUA_CONTRACT_ADDRESSES[NetworkEnum.ETHEREUM]) - -// Create ship transaction -const shipTx = aqua.ship({ - app: new Address(app), - strategy: new HexString(strategy), - amountsAndTokens: [ - { - token: new Address(USDC), - amount: parseUnits('4000', 6) - }, - { - token: new Address(WETH), - amount: parseUnits('1', 18) - } - ] -}) - -// Send transaction -const wallet = createWalletClient({ - chain: mainnet, - transport: http(), - account: privateKeyToAccount(makerPrivateKey) -}) - -await wallet.sendTransaction(shipTx) - -``` - -**Full test example:** [tests/aqua.spec.ts - should ship](https://github.com/1inch/sdks/blob/master/typescript/aqua/tests/aqua.spec.ts#L27) - -### Example 2: Execute a Swap through [XYCSwap.sol](https://github.com/1inch/aqua/blob/0637013a51cd56851f7b143a1f4500fdc93726cc/src/apps/XYCSwap.sol) aqua app - -Execute a swap against liquidity provided through Aqua. [TestTrader.sol](https://github.com/1inch/sdks/blob/0a276af00b91b287cc4c4f04402c44e02afffa44/contracts/src/aqua/TestTrader.sol#L7) helper contract is used as an approve holder and router. - -```typescript -import { - parseUnits, - http, - createWalletClient, - isHex, - encodeFunctionData, - decodeAbiParameters, - publicActions -} from 'viem' -import { privateKeyToAccount } from 'viem/accounts' -import { mainnet } from 'viem/chains' -import assert from 'assert' -import 'dotenv/config' - -const takerPrivateKey = process.env.TAKER_PRIVATE_KEY - -assert(isHex(takerPrivateKey)) -const USDC = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' -const app = '0xTODOReplace' -const routerAddress = '0xTestTraderAddress' - -const strategy = '0x' // parsed from ship events or fetched from api - -// Send transaction -const wallet = createWalletClient({ - chain: mainnet, - transport: http(), - account: privateKeyToAccount(takerPrivateKey) -}).extend(publicActions) - -// decode data based on specified by app format -const [strategyData] = decodeAbiParameters( - [ - { - type: 'tuple', - components: [ - { name: 'maker', type: 'address' }, - { name: 'token0', type: 'address' }, - { name: 'token1', type: 'address' }, - { name: 'feeBps', type: 'uint256' }, - { name: 'salt', type: 'bytes32' } - ] - } - ], - strategy -) - -// Define swap parameters -const srcAmount = parseUnits('10', 6) // 10 USDC -const srcToken = USDC -const isZeroForOne = strategyData.token0 === srcToken - -// Encode the swap call to helper Router contract -const swapData = encodeFunctionData({ - abi: [ - { - type: 'function', - name: 'swap', - inputs: [ - { - name: 'app', - type: 'address' - }, - { - name: 'strategy', - type: 'tuple', - components: [ - { name: 'maker', type: 'address' }, - { name: 'token0', type: 'address' }, - { name: 'token1', type: 'address' }, - { name: 'feeBps', type: 'uint256' }, - { name: 'salt', type: 'bytes32' } - ] - }, - { name: 'zeroForOne', type: 'bool' }, - { name: 'amountIn', type: 'uint256' } - ], - outputs: [{ name: 'amountOut', type: 'uint256' }], - stateMutability: 'nonpayable' - } - ], - functionName: 'swap', - args: [app, strategyData, isZeroForOne, srcAmount] -}) - -// give erc20 approve to routerAddress -await wallet.writeContract({ - abi: [ - { - type: 'function', - name: 'approve', - inputs: [ - { name: 'spender', type: 'address', internalType: 'address' }, - { name: 'value', type: 'uint256', internalType: 'uint256' } - ], - outputs: [{ name: '', type: 'bool', internalType: 'bool' }], - stateMutability: 'nonpayable' - } - ], - address: srcToken, - account: wallet.account, - functionName: 'approve', - chain: wallet.chain, - args: [routerAddress, srcAmount] -}) - -// Execute swap -const swapTx = await wallet.sendTransaction({ - to: routerAddress, - data: swapData -}) - -await wallet.waitForTransactionReceipt({ hash: swapTx }) -``` - -**Full test example:** [tests/aqua.spec.ts - should swap](https://github.com/1inch/sdks/blob/master/typescript/aqua/tests/aqua.spec.ts#L142) - -### Example 3: Dock Liquidity - -Withdraw all liquidity from a strategy and close it. - -```typescript -import { AquaProtocolContract, Address, HexString, AQUA_CONTRACT_ADDRESSES, NetworkEnum } from '@1inch/aqua-sdk' -import { http, createWalletClient, isHex } from 'viem' -import { privateKeyToAccount } from 'viem/accounts' -import { mainnet } from 'viem/chains' -import assert from 'assert' -import 'dotenv/config' - -const makerPrivateKey = process.env.MAKER_PRIVATE_KEY - -assert(isHex(makerPrivateKey)) -const app = '0xTODO_REPLACE' -const WETH = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' -const USDC = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' - -const strategy = '0x' // parsed from ship events or fetched from api - -// Initialize Aqua contract -const aqua = new AquaProtocolContract(AQUA_CONTRACT_ADDRESSES[NetworkEnum.ETHEREUM]) - -// Create ship transaction -const shipTx = aqua.dock({ - app: new Address(app), - strategyHash: AquaProtocolContract.calculateStrategyHash(new HexString(strategy)), - tokens: [new Address(USDC), new Address(WETH)] -}) - -// Send transaction -const wallet = createWalletClient({ - chain: mainnet, - transport: http(), - account: privateKeyToAccount(makerPrivateKey) -}) - -await wallet.sendTransaction(shipTx) - -// After transaction is confirmed, all virtual balances are withdrawn -// and the strategy is closed -``` - -**Full test example:** [tests/aqua.spec.ts - should dock](https://github.com/1inch/sdks/blob/master/typescript/aqua/tests/aqua.spec.ts#L320) - -## License - -This SDK is provided under the terms described in [LICENSE](./LICENSE) and [THIRD_PARTY_NOTICES](./THIRD_PARTY_NOTICES). - -For any licensing questions or requests, contact: -- license@degensoft.com -- legal@degensoft.com diff --git a/typescript/aqua/THIRD_PARTY_NOTICES b/typescript/aqua/THIRD_PARTY_NOTICES deleted file mode 100644 index 8e76251..0000000 --- a/typescript/aqua/THIRD_PARTY_NOTICES +++ /dev/null @@ -1,63 +0,0 @@ -THIRD-PARTY SOFTWARE NOTICES AND INFORMATION -=========================================== - -This project includes third-party software components that are licensed under -open source licenses. The following notices are provided for informational -purposes and to comply with the applicable license terms. - -Only dependencies licensed under MIT or Apache-style licenses are listed here. - -------------------------------------------------------------------------------- -1. viem -------------------------------------------------------------------------------- - -Name: viem -Version: 2.39.0 -License: MIT License -Project URL: https://viem.sh -Source: https://github.com/wevm/viem - -MIT License - -Copyright (c) 2023-present weth, LLC - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -------------------------------------------------------------------------------- -2. tslib -------------------------------------------------------------------------------- - -Name: tslib -Version: 2.8.1 -License: Copyright (c) Microsoft Corporation (permissive license) -Project URL: https://github.com/microsoft/tslib -Source: https://github.com/microsoft/tslib - -Copyright (c) Microsoft Corporation. - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. diff --git a/typescript/aqua/eslint.config.mjs b/typescript/aqua/eslint.config.mjs deleted file mode 100644 index a162ad5..0000000 --- a/typescript/aqua/eslint.config.mjs +++ /dev/null @@ -1,16 +0,0 @@ -// @ts-expect-error no types -import licenseHeader from 'eslint-plugin-license-header' -import config from '../eslint.config.mjs' - -export default [ - ...config, - { - files: ['./src/**'], - plugins: { - 'license-header': licenseHeader, - }, - rules: { - 'license-header/header': ['error', './license-header.txt'], - }, - }, -] diff --git a/typescript/aqua/license-header.txt b/typescript/aqua/license-header.txt deleted file mode 100644 index a9b9d66..0000000 --- a/typescript/aqua/license-header.txt +++ /dev/null @@ -1 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-Degensoft-Aqua-Source-1.1 \ No newline at end of file diff --git a/typescript/aqua/package.json b/typescript/aqua/package.json deleted file mode 100644 index 02642b9..0000000 --- a/typescript/aqua/package.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "name": "@1inch/aqua-sdk", - "version": "0.1.0", - "description": "1inch Aqua Protocol SDK", - "author": "@1inch", - "license": "LicenseRef-Degensoft-Aqua-Source-1.1", - "repository": { - "type": "git", - "url": "ssh://git@github.com:1inch/sdks.git" - }, - "main": "./dist/index.js", - "module": "./dist/index.mjs", - "types": "./dist/index.d.ts", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.mjs", - "require": "./dist/index.js" - }, - "./package.json": "./package.json" - }, - "files": [ - "dist", - "LICENSE", - "README.md", - "package.json" - ], - "scripts": { - "build": "rm -rf dist && tsdown", - "test": "vitest run", - "test:e2e": "vitest run --config vitest.e2e.config.mts", - "test:watch": "vitest watch", - "test:coverage": "vitest run --coverage", - "lint": "eslint src", - "lint:fix": "eslint src --fix", - "format": "prettier --write \"src/**/*.ts\"", - "format:check": "prettier --check \"src/**/*.ts\"", - "type-check": "tsc --noEmit", - "clean": "rimraf dist coverage", - "changelog:generate": "changelog generate -a" - }, - "dependencies": { - "@1inch/sdk-core": "workspace:*", - "tslib": "^2.8.1", - "viem": "^2.39.3" - }, - "devDependencies": { - "@types/node": "^22.19.1", - "dotenv": "17.2.3", - "eslint-plugin-license-header": "0.8.0", - "tsdown": "^0.16.6", - "typescript": "^5.9.3", - "vitest": "^3.2.4" - }, - "publishConfig": { - "access": "public" - }, - "volta": { - "node": "22.13.1" - } -} diff --git a/typescript/aqua/project.json b/typescript/aqua/project.json deleted file mode 100644 index 33cf381..0000000 --- a/typescript/aqua/project.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "name": "aqua", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "sourceRoot": "{projectRoot}/src", - "projectType": "library", - "tags": ["typescript", "sdk"], - "targets": { - "build": { - "executor": "nx:run-commands", - "options": { - "cwd": "typescript/aqua", - "commands": ["tsdown"] - } - }, - "test": { - "executor": "@nx/vitest:test", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "passWithNoTests": true, - "coverage": true - } - }, - "test:e2e": { - "executor": "@nx/vitest:test", - "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], - "options": { - "passWithNoTests": true, - "coverage": false, - "config": "{projectRoot}/vitest.e2e.config.mts" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": ["{projectRoot}/**/*.ts"], - "eslintConfig": "typescript/eslint.config.mjs" - }, - "outputs": ["{options.outputFile}"] - }, - "type-check": { - "executor": "nx:run-commands", - "options": { - "command": "tsc --noEmit -p typescript/aqua/tsconfig.json" - } - } - } -} diff --git a/typescript/aqua/src/abi/Aqua.abi.ts b/typescript/aqua/src/abi/Aqua.abi.ts deleted file mode 100644 index 9d3a5e1..0000000 --- a/typescript/aqua/src/abi/Aqua.abi.ts +++ /dev/null @@ -1,182 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-Degensoft-Aqua-Source-1.1 - -export const AQUA_ABI = [ - { - type: 'function', - name: 'dock', - inputs: [ - { name: 'app', type: 'address', internalType: 'address' }, - { name: 'strategyHash', type: 'bytes32', internalType: 'bytes32' }, - { name: 'tokens', type: 'address[]', internalType: 'address[]' }, - ], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'pull', - inputs: [ - { name: 'maker', type: 'address', internalType: 'address' }, - { name: 'strategyHash', type: 'bytes32', internalType: 'bytes32' }, - { name: 'token', type: 'address', internalType: 'address' }, - { name: 'amount', type: 'uint256', internalType: 'uint256' }, - { name: 'to', type: 'address', internalType: 'address' }, - ], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'push', - inputs: [ - { name: 'maker', type: 'address', internalType: 'address' }, - { name: 'app', type: 'address', internalType: 'address' }, - { name: 'strategyHash', type: 'bytes32', internalType: 'bytes32' }, - { name: 'token', type: 'address', internalType: 'address' }, - { name: 'amount', type: 'uint256', internalType: 'uint256' }, - ], - outputs: [], - stateMutability: 'nonpayable', - }, - { - type: 'function', - name: 'rawBalances', - inputs: [ - { name: 'maker', type: 'address', internalType: 'address' }, - { name: 'app', type: 'address', internalType: 'address' }, - { name: 'strategyHash', type: 'bytes32', internalType: 'bytes32' }, - { name: 'token', type: 'address', internalType: 'address' }, - ], - outputs: [ - { name: 'balance', type: 'uint248', internalType: 'uint248' }, - { name: 'tokensCount', type: 'uint8', internalType: 'uint8' }, - ], - stateMutability: 'view', - }, - { - type: 'function', - name: 'safeBalances', - inputs: [ - { name: 'maker', type: 'address', internalType: 'address' }, - { name: 'app', type: 'address', internalType: 'address' }, - { name: 'strategyHash', type: 'bytes32', internalType: 'bytes32' }, - { name: 'token0', type: 'address', internalType: 'address' }, - { name: 'token1', type: 'address', internalType: 'address' }, - ], - outputs: [ - { name: 'balance0', type: 'uint256', internalType: 'uint256' }, - { name: 'balance1', type: 'uint256', internalType: 'uint256' }, - ], - stateMutability: 'view', - }, - { - type: 'function', - name: 'ship', - inputs: [ - { name: 'app', type: 'address', internalType: 'address' }, - { name: 'strategy', type: 'bytes', internalType: 'bytes' }, - { name: 'tokens', type: 'address[]', internalType: 'address[]' }, - { name: 'amounts', type: 'uint256[]', internalType: 'uint256[]' }, - ], - outputs: [{ name: 'strategyHash', type: 'bytes32', internalType: 'bytes32' }], - stateMutability: 'nonpayable', - }, - { - type: 'event', - name: 'Docked', - inputs: [ - { name: 'maker', type: 'address', indexed: false, internalType: 'address' }, - { name: 'app', type: 'address', indexed: false, internalType: 'address' }, - { name: 'strategyHash', type: 'bytes32', indexed: false, internalType: 'bytes32' }, - ], - anonymous: false, - }, - { - type: 'event', - name: 'Pulled', - inputs: [ - { name: 'maker', type: 'address', indexed: false, internalType: 'address' }, - { name: 'app', type: 'address', indexed: false, internalType: 'address' }, - { name: 'strategyHash', type: 'bytes32', indexed: false, internalType: 'bytes32' }, - { name: 'token', type: 'address', indexed: false, internalType: 'address' }, - { name: 'amount', type: 'uint256', indexed: false, internalType: 'uint256' }, - ], - anonymous: false, - }, - { - type: 'event', - name: 'Pushed', - inputs: [ - { name: 'maker', type: 'address', indexed: false, internalType: 'address' }, - { name: 'app', type: 'address', indexed: false, internalType: 'address' }, - { name: 'strategyHash', type: 'bytes32', indexed: false, internalType: 'bytes32' }, - { name: 'token', type: 'address', indexed: false, internalType: 'address' }, - { name: 'amount', type: 'uint256', indexed: false, internalType: 'uint256' }, - ], - anonymous: false, - }, - { - type: 'event', - name: 'Shipped', - inputs: [ - { name: 'maker', type: 'address', indexed: false, internalType: 'address' }, - { name: 'app', type: 'address', indexed: false, internalType: 'address' }, - { name: 'strategyHash', type: 'bytes32', indexed: false, internalType: 'bytes32' }, - { name: 'strategy', type: 'bytes', indexed: false, internalType: 'bytes' }, - ], - anonymous: false, - }, - { - type: 'error', - name: 'DockingShouldCloseAllTokens', - inputs: [ - { name: 'app', type: 'address', internalType: 'address' }, - { name: 'strategyHash', type: 'bytes32', internalType: 'bytes32' }, - ], - }, - { - type: 'error', - name: 'MaxNumberOfTokensExceeded', - inputs: [ - { name: 'tokensCount', type: 'uint256', internalType: 'uint256' }, - { name: 'maxTokensCount', type: 'uint256', internalType: 'uint256' }, - ], - }, - { - type: 'error', - name: 'PushToNonActiveStrategyPrevented', - inputs: [ - { name: 'maker', type: 'address', internalType: 'address' }, - { name: 'app', type: 'address', internalType: 'address' }, - { name: 'strategyHash', type: 'bytes32', internalType: 'bytes32' }, - { name: 'token', type: 'address', internalType: 'address' }, - ], - }, - { - type: 'error', - name: 'SafeBalancesForTokenNotInActiveStrategy', - inputs: [ - { name: 'maker', type: 'address', internalType: 'address' }, - { name: 'app', type: 'address', internalType: 'address' }, - { name: 'strategyHash', type: 'bytes32', internalType: 'bytes32' }, - { name: 'token', type: 'address', internalType: 'address' }, - ], - }, - { - type: 'error', - name: 'SafeCastOverflowedUintDowncast', - inputs: [ - { name: 'bits', type: 'uint8', internalType: 'uint8' }, - { name: 'value', type: 'uint256', internalType: 'uint256' }, - ], - }, - { type: 'error', name: 'SafeTransferFromFailed', inputs: [] }, - { - type: 'error', - name: 'StrategiesMustBeImmutable', - inputs: [ - { name: 'app', type: 'address', internalType: 'address' }, - { name: 'strategyHash', type: 'bytes32', internalType: 'bytes32' }, - ], - }, -] as const diff --git a/typescript/aqua/src/abi/index.ts b/typescript/aqua/src/abi/index.ts deleted file mode 100644 index 13c9b7f..0000000 --- a/typescript/aqua/src/abi/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-Degensoft-Aqua-Source-1.1 - -export * from './Aqua.abi' diff --git a/typescript/aqua/src/aqua-protocol-contract/aqua-protocol-contract.test.ts b/typescript/aqua/src/aqua-protocol-contract/aqua-protocol-contract.test.ts deleted file mode 100644 index c69084f..0000000 --- a/typescript/aqua/src/aqua-protocol-contract/aqua-protocol-contract.test.ts +++ /dev/null @@ -1,119 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-Degensoft-Aqua-Source-1.1 - -import { describe, it, expect } from 'vitest' -import { Address, HexString } from '@1inch/sdk-core' -import type { DockArgs, ShipArgs } from './types' -import { AquaProtocolContract } from './aqua-protocol-contract' - -describe('AquaProtocolContract', () => { - const mockApp = Address.fromBigInt(1n) - const mockToken = Address.fromBigInt(3n) - const mockContractAddress = Address.fromBigInt(5n) - - const mockStrategy = new HexString('0x01020304') - const mockStrategyHash = AquaProtocolContract.calculateStrategyHash(mockStrategy) - const mockAmount = BigInt(1000) - const mockAmounts = [mockAmount, BigInt(2000)] - const mockTokens = [mockToken, Address.fromBigInt(6n)] - - describe('encodeShipCallData', () => { - it('should encode ship function call data correctly', () => { - const args: ShipArgs = { - app: mockApp, - strategy: mockStrategy, - amountsAndTokens: [ - { token: mockTokens[0], amount: mockAmounts[0] }, - { token: mockTokens[1], amount: mockAmounts[1] }, - ], - } - - const result = AquaProtocolContract.encodeShipCallData(args) - - expect(result).toBeDefined() - expect(result.toString()).toMatch(/^0x[0-9a-fA-F]+$/) - }) - }) - - describe('encodeDockCallData', () => { - it('should encode dock function call data correctly', () => { - const args: DockArgs = { - app: mockApp, - strategyHash: mockStrategyHash, - tokens: mockTokens, - } - - const result = AquaProtocolContract.encodeDockCallData(args) - - expect(result).toBeDefined() - expect(result.toString()).toMatch(/^0x[0-9a-fA-F]+$/) - }) - }) - - describe('buildShipTx', () => { - it('should build ship transaction correctly', () => { - const args: ShipArgs = { - app: mockApp, - strategy: mockStrategy, - amountsAndTokens: [ - { token: mockTokens[0], amount: mockAmounts[0] }, - { token: mockTokens[1], amount: mockAmounts[1] }, - ], - } - - const tx = AquaProtocolContract.buildShipTx(mockContractAddress, args) - - expect(tx).toBeDefined() - expect(tx.to).toBe(mockContractAddress.toString()) - expect(tx.data.startsWith('0x')).toBe(true) - expect(tx.value).toBe(0n) - }) - }) - - describe('buildDockTx', () => { - it('should build dock transaction correctly', () => { - const args: DockArgs = { - app: mockApp, - strategyHash: mockStrategyHash, - tokens: mockTokens, - } - - const tx = AquaProtocolContract.buildDockTx(mockContractAddress, args) - - expect(tx).toBeDefined() - expect(tx.to).toBe(mockContractAddress.toString()) - expect(tx.data.startsWith('0x')).toBe(true) - expect(tx.value).toBe(0n) - }) - }) - - describe('calculateStrategyHash', () => { - it('should calculate strategy hash correctly', () => { - const strategy = new HexString('0x01020304') - - const hash = AquaProtocolContract.calculateStrategyHash(strategy) - - expect(hash).toBeDefined() - expect(hash.toString()).toMatch(/^0x[0-9a-fA-F]+$/) - expect(hash.toString().length).toBe(66) - }) - - it('should produce consistent hashes for the same input', () => { - const strategy = new HexString('0x01020304') - - const hash1 = AquaProtocolContract.calculateStrategyHash(strategy) - const hash2 = AquaProtocolContract.calculateStrategyHash(strategy) - - expect(hash1.toString()).toBe(hash2.toString()) - }) - - it('should produce different hashes for different inputs', () => { - const strategy1 = new HexString('0x01020304') - const strategy2 = new HexString('0x05060708') - - const hash1 = AquaProtocolContract.calculateStrategyHash(strategy1) - const hash2 = AquaProtocolContract.calculateStrategyHash(strategy2) - - expect(hash1.toString()).not.toBe(hash2.toString()) - }) - }) -}) diff --git a/typescript/aqua/src/aqua-protocol-contract/aqua-protocol-contract.ts b/typescript/aqua/src/aqua-protocol-contract/aqua-protocol-contract.ts deleted file mode 100644 index 9318ad3..0000000 --- a/typescript/aqua/src/aqua-protocol-contract/aqua-protocol-contract.ts +++ /dev/null @@ -1,103 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-Degensoft-Aqua-Source-1.1 - -import { encodeFunctionData, keccak256 } from 'viem' -import type { CallInfo, Address } from '@1inch/sdk-core' -import { HexString } from '@1inch/sdk-core' -import type { ShipArgs, DockArgs } from './types' -import { AQUA_ABI } from '../abi/Aqua.abi' - -/** - * Aqua Protocol Contract - Encoding/decoding for ship, dock, push, pull - * - * This class provides methods to encode and decode calldata for the Aqua Protocol - * smart contract's core functions. - */ -export class AquaProtocolContract { - constructor(public readonly address: Address) {} - - /** - * Encodes the calldata for the ship function - * @param args - Ship arguments containing app address, strategy, tokens, and amounts - * @returns Encoded calldata as HexString - * @see https://github.com/1inch/aqua-protocol/blob/master/src/Aqua.sol#L34 - */ - static encodeShipCallData(args: ShipArgs): HexString { - const { app, strategy, amountsAndTokens } = args - - const result = encodeFunctionData({ - abi: AQUA_ABI, - functionName: 'ship', - args: [ - app.toString(), - strategy.toString(), - amountsAndTokens.map(({ token }) => token.toString()), - amountsAndTokens.map(({ amount }) => amount), - ], - }) - - return new HexString(result) - } - - /** - * Encodes the calldata for the dock function - * @param args - Dock arguments containing app address, strategy hash, and tokens - * @returns Encoded calldata as HexString - * @see https://github.com/1inch/aqua-protocol/blob/master/src/Aqua.sol#L49 - */ - static encodeDockCallData(args: DockArgs): HexString { - const { app, strategyHash, tokens } = args - - const result = encodeFunctionData({ - abi: AQUA_ABI, - functionName: 'dock', - args: [app.toString(), strategyHash.toString(), tokens.map((t) => t.toString())], - }) - - return new HexString(result) - } - - /** - * Builds a complete transaction object for the ship function - * @param contractAddress - The Aqua protocol contract address - * @param params - Ship arguments - * @returns Transaction call info with to, data, and value fields - */ - static buildShipTx(contractAddress: Address, params: ShipArgs): CallInfo { - return { - to: contractAddress.toString(), - data: this.encodeShipCallData(params).toString(), - value: 0n, - } - } - - /** - * Builds a complete transaction object for the dock function - * @param contractAddress - The Aqua protocol contract address - * @param params - Dock arguments - * @returns Transaction call info with to, data, and value fields - */ - static buildDockTx(contractAddress: Address, params: DockArgs): CallInfo { - return { - to: contractAddress.toString(), - data: this.encodeDockCallData(params).toString(), - value: 0n, - } - } - - /** - * Calculate strategy hash from strategy bytes - * @param strategy Strategy bytes - * @returns Strategy hash - */ - static calculateStrategyHash(strategy: HexString): HexString { - return new HexString(keccak256(strategy.toString())) - } - - public ship(params: ShipArgs): CallInfo { - return AquaProtocolContract.buildShipTx(this.address, params) - } - - public dock(params: DockArgs): CallInfo { - return AquaProtocolContract.buildDockTx(this.address, params) - } -} diff --git a/typescript/aqua/src/aqua-protocol-contract/constants.ts b/typescript/aqua/src/aqua-protocol-contract/constants.ts deleted file mode 100644 index 6e18f4c..0000000 --- a/typescript/aqua/src/aqua-protocol-contract/constants.ts +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-Degensoft-Aqua-Source-1.1 - -import { Address, NetworkEnum } from '@1inch/sdk-core' - -/** - * Aqua Protocol contract addresses by chain ID - */ -export const AQUA_CONTRACT_ADDRESSES: Record = { - [NetworkEnum.ETHEREUM]: new Address('0x499943e74fb0ce105688beee8ef2abec5d936d31'), - [NetworkEnum.BINANCE]: new Address('0x499943e74fb0ce105688beee8ef2abec5d936d31'), - [NetworkEnum.POLYGON]: new Address('0x499943e74fb0ce105688beee8ef2abec5d936d31'), - [NetworkEnum.ARBITRUM]: new Address('0x499943e74fb0ce105688beee8ef2abec5d936d31'), - [NetworkEnum.AVALANCHE]: new Address('0x499943e74fb0ce105688beee8ef2abec5d936d31'), - [NetworkEnum.GNOSIS]: new Address('0x499943e74fb0ce105688beee8ef2abec5d936d31'), - [NetworkEnum.COINBASE]: new Address('0x499943e74fb0ce105688beee8ef2abec5d936d31'), - [NetworkEnum.OPTIMISM]: new Address('0x499943e74fb0ce105688beee8ef2abec5d936d31'), - [NetworkEnum.ZKSYNC]: new Address('0x499943e74fb0ce105688beee8ef2abec5d936d31'), - [NetworkEnum.LINEA]: new Address('0x499943e74fb0ce105688beee8ef2abec5d936d31'), - [NetworkEnum.UNICHAIN]: new Address('0x499943e74fb0ce105688beee8ef2abec5d936d31'), - [NetworkEnum.SONIC]: new Address('0x499943e74fb0ce105688beee8ef2abec5d936d31'), -} diff --git a/typescript/aqua/src/aqua-protocol-contract/events/docked-event.test.ts b/typescript/aqua/src/aqua-protocol-contract/events/docked-event.test.ts deleted file mode 100644 index c700ad8..0000000 --- a/typescript/aqua/src/aqua-protocol-contract/events/docked-event.test.ts +++ /dev/null @@ -1,123 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-Degensoft-Aqua-Source-1.1 - -import { describe, it, expect } from 'vitest' -import type { Log } from 'viem' -import { Address, HexString } from '@1inch/sdk-core' -import { trim0x } from '@1inch/byte-utils' -import { DockedEvent } from './docked-event' - -describe('DockedEvent', () => { - const mockMaker = '0x961da14c99217789106f0c246c0f66b49fe266ff' - const mockApp = '0x51b66446ebb060cb0571a6fcbccde855d091dc16' - const mockStrategyHash = '0x2d142ba44ee9104f8cd702bfe7520e64eb8531c5e4e4ded80c6a93cf5a3d113e' - - describe('constructor', () => { - it('should create DockedEvent instance', () => { - const event = new DockedEvent( - new Address(mockMaker), - new Address(mockApp), - new HexString(mockStrategyHash), - ) - - expect(event.maker.toString()).toBe(mockMaker.toLowerCase()) - expect(event.app.toString()).toBe(mockApp.toLowerCase()) - expect(event.strategyHash.toString()).toBe(mockStrategyHash) - }) - }) - - describe('fromLog', () => { - it('should decode valid docked event log from real blockchain data', () => { - const log: Log = { - address: '0xfa3c23da986b3596ee7177434ad8e4406068a3e5' as `0x${string}`, - topics: [ - '0xd173a1d140c154eb1ce9298d251d5eb8c4089cc2d16e70f1067bdc810c6fe004' as `0x${string}`, - ], - data: '0x0000000000000000000000008b83c50040c743e99bd47f4327bfcf7913c505b40000000000000000000000000cc85a15477539958d622a2735a3477d7d329c89fed4c945f2dc5747956337cf623dceacca130714540e70742e63456d3daf2400' as `0x${string}`, - blockNumber: 23841073n, - transactionHash: - '0xb4231e80752dac59d01480454fe85cde374ea087176158ba0ac8315aecf3fde0' as `0x${string}`, - transactionIndex: 0, - blockHash: - '0x23820c2a5de498bc0c87469392eac0c456ce3712ae3872cd32055b9a17a405c7' as `0x${string}`, - logIndex: 0, - removed: false, - } - - const event = DockedEvent.fromLog(log) - - expect(event.maker.toString()).toBe('0x8b83c50040c743e99bd47f4327bfcf7913c505b4') - expect(event.app.toString()).toBe('0x0cc85a15477539958d622a2735a3477d7d329c89') - expect(event.strategyHash.toString()).toBe( - '0xfed4c945f2dc5747956337cf623dceacca130714540e70742e63456d3daf2400', - ) - }) - - it('should decode valid docked event log', () => { - const log: Log = { - address: mockApp as `0x${string}`, - topics: [DockedEvent.TOPIC.toString() as `0x${string}`], - data: `0x${trim0x(mockMaker).padStart(64, '0')}${trim0x(mockApp).padStart(64, '0')}${trim0x(mockStrategyHash)}` as `0x${string}`, - blockNumber: 1n, - transactionHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - transactionIndex: 0, - blockHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - logIndex: 0, - removed: false, - } - - const event = DockedEvent.fromLog(log) - - expect(event.maker.toString()).toBe(mockMaker.toLowerCase()) - expect(event.app.toString()).toBe(mockApp.toLowerCase()) - expect(event.strategyHash.toString()).toBe(mockStrategyHash) - }) - - it('should throw on invalid topic', () => { - const log: Log = { - address: mockApp as `0x${string}`, - topics: ['0xdeadbeef' as `0x${string}`], - data: `0x${trim0x(mockMaker).padStart(64, '0')}${trim0x(mockApp).padStart(64, '0')}${trim0x(mockStrategyHash)}` as `0x${string}`, - blockNumber: 1n, - transactionHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - transactionIndex: 0, - blockHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - logIndex: 0, - removed: false, - } - - expect(() => DockedEvent.fromLog(log)).toThrow() - }) - - it('should throw on missing data', () => { - const log: Log = { - address: mockApp as `0x${string}`, - topics: [DockedEvent.TOPIC.toString() as `0x${string}`], - data: '0x' as `0x${string}`, - blockNumber: 1n, - transactionHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - transactionIndex: 0, - blockHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - logIndex: 0, - removed: false, - } - - expect(() => DockedEvent.fromLog(log)).toThrow() - }) - - it('should throw on invalid data format', () => { - const log: Log = { - address: mockApp as `0x${string}`, - topics: [DockedEvent.TOPIC.toString() as `0x${string}`], - data: '0xinvalid' as `0x${string}`, - blockNumber: 1n, - transactionHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - transactionIndex: 0, - blockHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - logIndex: 0, - removed: false, - } - - expect(() => DockedEvent.fromLog(log)).toThrow() - }) - }) -}) diff --git a/typescript/aqua/src/aqua-protocol-contract/events/docked-event.ts b/typescript/aqua/src/aqua-protocol-contract/events/docked-event.ts deleted file mode 100644 index 5f1a229..0000000 --- a/typescript/aqua/src/aqua-protocol-contract/events/docked-event.ts +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-Degensoft-Aqua-Source-1.1 - -import { decodeEventLog } from 'viem' -import { Address, HexString } from '@1inch/sdk-core' -import type { LogLike } from '@1inch/sdk-core' -import { AQUA_ABI } from '../../abi/Aqua.abi' - -export class DockedEvent { - public static TOPIC: HexString = new HexString( - '0xd173a1d140c154eb1ce9298d251d5eb8c4089cc2d16e70f1067bdc810c6fe004', - ) - - constructor( - public readonly maker: Address, - public readonly app: Address, - public readonly strategyHash: HexString, - ) {} - - /** - * Creates a DockedEvent from - * @throws Error if the log data is invalid or doesn't match the expected event structure - */ - static fromLog(log: LogLike): DockedEvent { - const decoded = decodeEventLog({ - abi: AQUA_ABI, - data: log.data, - topics: log.topics, - eventName: 'Docked', - }) - - const args = decoded.args - - return new DockedEvent( - new Address(args.maker), - new Address(args.app), - new HexString(args.strategyHash), - ) - } -} diff --git a/typescript/aqua/src/aqua-protocol-contract/events/index.ts b/typescript/aqua/src/aqua-protocol-contract/events/index.ts deleted file mode 100644 index d56cf95..0000000 --- a/typescript/aqua/src/aqua-protocol-contract/events/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-Degensoft-Aqua-Source-1.1 - -export { ShippedEvent } from './shipped-event' -export { DockedEvent } from './docked-event' -export { PulledEvent } from './pulled-event' -export { PushedEvent } from './pushed-event' diff --git a/typescript/aqua/src/aqua-protocol-contract/events/pulled-event.test.ts b/typescript/aqua/src/aqua-protocol-contract/events/pulled-event.test.ts deleted file mode 100644 index ec19135..0000000 --- a/typescript/aqua/src/aqua-protocol-contract/events/pulled-event.test.ts +++ /dev/null @@ -1,148 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-Degensoft-Aqua-Source-1.1 - -import { describe, it, expect } from 'vitest' -import type { Log } from 'viem' -import { Address, HexString } from '@1inch/sdk-core' -import { trim0x } from '@1inch/byte-utils' -import { PulledEvent } from './pulled-event' - -describe('PulledEvent', () => { - const mockMaker = '0x961da14c99217789106f0c246c0f66b49fe266ff' - const mockApp = '0x51b66446ebb060cb0571a6fcbccde855d091dc16' - const mockStrategyHash = '0x2d142ba44ee9104f8cd702bfe7520e64eb8531c5e4e4ded80c6a93cf5a3d113e' - const mockToken = '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913' - const mockAmount = 750000n - - describe('constructor', () => { - it('should create PulledEvent instance', () => { - const event = new PulledEvent( - new Address(mockMaker), - new Address(mockApp), - new HexString(mockStrategyHash), - new Address(mockToken), - mockAmount, - ) - - expect(event.maker.toString()).toBe(mockMaker.toLowerCase()) - expect(event.app.toString()).toBe(mockApp.toLowerCase()) - expect(event.strategyHash.toString()).toBe(mockStrategyHash) - expect(event.token.toString()).toBe(mockToken.toLowerCase()) - expect(event.amount).toBe(mockAmount) - }) - }) - - describe('fromLog', () => { - it('should decode valid pulled event log with realistic blockchain data', () => { - const log: Log = { - address: '0x51b66446Ebb060cb0571a6fcbCcde855D091DC16' as `0x${string}`, - topics: [PulledEvent.TOPIC.toString() as `0x${string}`], - data: '0x000000000000000000000000961da14c99217789106f0c246c0f66b49fe266ff00000000000000000000000051b66446ebb060cb0571a6fcbccde855d091dc162d142ba44ee9104f8cd702bfe7520e64eb8531c5e4e4ded80c6a93cf5a3d113e000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda0291300000000000000000000000000000000000000000000000000000000000b71b0' as `0x${string}`, - blockNumber: 38041057n, - transactionHash: ('0x' + '2'.padStart(64, '0')) as `0x${string}`, - transactionIndex: 0, - blockHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - logIndex: 0, - removed: false, - } - - const event = PulledEvent.fromLog(log) - - expect(event.maker.toString()).toBe('0x961da14c99217789106f0c246c0f66b49fe266ff') - expect(event.app.toString()).toBe('0x51b66446ebb060cb0571a6fcbccde855d091dc16') - expect(event.strategyHash.toString()).toBe( - '0x2d142ba44ee9104f8cd702bfe7520e64eb8531c5e4e4ded80c6a93cf5a3d113e', - ) - expect(event.token.toString()).toBe('0x833589fcd6edb6e08f4c7c32d4f71b54bda02913') - expect(event.amount).toBe(750000n) - }) - - it('should decode valid pulled event log', () => { - const log: Log = { - address: mockApp as `0x${string}`, - topics: [PulledEvent.TOPIC.toString() as `0x${string}`], - data: `0x${trim0x(mockMaker).padStart(64, '0')}${trim0x(mockApp).padStart(64, '0')}${trim0x(mockStrategyHash)}${trim0x(mockToken).padStart(64, '0')}${mockAmount.toString(16).padStart(64, '0')}` as `0x${string}`, - blockNumber: 1n, - transactionHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - transactionIndex: 0, - blockHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - logIndex: 0, - removed: false, - } - - const event = PulledEvent.fromLog(log) - - expect(event.maker.toString()).toBe(mockMaker.toLowerCase()) - expect(event.app.toString()).toBe(mockApp.toLowerCase()) - expect(event.strategyHash.toString()).toBe(mockStrategyHash) - expect(event.token.toString()).toBe(mockToken.toLowerCase()) - expect(event.amount).toBe(mockAmount) - }) - - it('should decode pulled event with large amount', () => { - const largeAmount = 1000000000000000000n - - const log: Log = { - address: mockApp as `0x${string}`, - topics: [PulledEvent.TOPIC.toString() as `0x${string}`], - data: `0x${trim0x(mockMaker).padStart(64, '0')}${trim0x(mockApp).padStart(64, '0')}${trim0x(mockStrategyHash)}${trim0x(mockToken).padStart(64, '0')}${largeAmount.toString(16).padStart(64, '0')}` as `0x${string}`, - blockNumber: 1n, - transactionHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - transactionIndex: 0, - blockHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - logIndex: 0, - removed: false, - } - - const event = PulledEvent.fromLog(log) - expect(event.amount).toBe(largeAmount) - }) - - it('should throw on invalid topic', () => { - const log: Log = { - address: mockApp as `0x${string}`, - topics: ['0xdeadbeef' as `0x${string}`], - data: `0x${'0'.padStart(320, '0')}` as `0x${string}`, - blockNumber: 1n, - transactionHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - transactionIndex: 0, - blockHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - logIndex: 0, - removed: false, - } - - expect(() => PulledEvent.fromLog(log)).toThrow() - }) - - it('should throw on missing data', () => { - const log: Log = { - address: mockApp as `0x${string}`, - topics: [PulledEvent.TOPIC.toString() as `0x${string}`], - data: '0x' as `0x${string}`, - blockNumber: 1n, - transactionHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - transactionIndex: 0, - blockHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - logIndex: 0, - removed: false, - } - - expect(() => PulledEvent.fromLog(log)).toThrow() - }) - - it('should throw on invalid data format', () => { - const log: Log = { - address: mockApp as `0x${string}`, - topics: [PulledEvent.TOPIC.toString() as `0x${string}`], - data: '0xinvalid' as `0x${string}`, - blockNumber: 1n, - transactionHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - transactionIndex: 0, - blockHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - logIndex: 0, - removed: false, - } - - expect(() => PulledEvent.fromLog(log)).toThrow() - }) - }) -}) diff --git a/typescript/aqua/src/aqua-protocol-contract/events/pulled-event.ts b/typescript/aqua/src/aqua-protocol-contract/events/pulled-event.ts deleted file mode 100644 index ea3c2b3..0000000 --- a/typescript/aqua/src/aqua-protocol-contract/events/pulled-event.ts +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-Degensoft-Aqua-Source-1.1 - -import { decodeEventLog } from 'viem' -import { Address, HexString } from '@1inch/sdk-core' -import type { LogLike } from '@1inch/sdk-core' -import { AQUA_ABI } from '../../abi/Aqua.abi' - -export class PulledEvent { - public static TOPIC: HexString = new HexString( - '0x3ad61047071575417c75e3311e5d46ff042e292b5dd8769ff18b4b254098ca7a', - ) - - constructor( - public readonly maker: Address, - public readonly app: Address, - public readonly strategyHash: HexString, - public readonly token: Address, - public readonly amount: bigint, - ) {} - - /** - * Creates a PulledEvent - * @throws Error if the log data is invalid or doesn't match the expected event structure - */ - static fromLog(log: LogLike): PulledEvent { - const decoded = decodeEventLog({ - abi: AQUA_ABI, - data: log.data, - topics: log.topics, - eventName: 'Pulled', - }) - - const args = decoded.args - - return new PulledEvent( - new Address(args.maker), - new Address(args.app), - new HexString(args.strategyHash), - new Address(args.token), - args.amount, - ) - } -} diff --git a/typescript/aqua/src/aqua-protocol-contract/events/pushed-event.test.ts b/typescript/aqua/src/aqua-protocol-contract/events/pushed-event.test.ts deleted file mode 100644 index f5a25b4..0000000 --- a/typescript/aqua/src/aqua-protocol-contract/events/pushed-event.test.ts +++ /dev/null @@ -1,173 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-Degensoft-Aqua-Source-1.1 - -import { describe, it, expect } from 'vitest' -import type { Log } from 'viem' -import { Address, HexString } from '@1inch/sdk-core' -import { PushedEvent } from './pushed-event' - -describe('PushedEvent', () => { - const mockMaker = '0x961da14c99217789106f0c246c0f66b49fe266ff' - const mockApp = '0x51b66446ebb060cb0571a6fcbccde855d091dc16' - const mockStrategyHash = '0x2d142ba44ee9104f8cd702bfe7520e64eb8531c5e4e4ded80c6a93cf5a3d113e' - const mockToken = '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913' - const mockAmount = 1000000n - - describe('constructor', () => { - it('should create PushedEvent instance', () => { - const event = new PushedEvent( - new Address(mockMaker), - new Address(mockApp), - new HexString(mockStrategyHash), - new Address(mockToken), - mockAmount, - ) - - expect(event.maker.toString()).toBe(mockMaker.toLowerCase()) - expect(event.app.toString()).toBe(mockApp.toLowerCase()) - expect(event.strategyHash.toString()).toBe(mockStrategyHash) - expect(event.token.toString()).toBe(mockToken.toLowerCase()) - expect(event.amount).toBe(mockAmount) - }) - }) - - describe('fromLog', () => { - it('should decode valid pushed event log from real blockchain data', () => { - const log: Log = { - address: '0x51b66446Ebb060cb0571a6fcbCcde855D091DC16' as `0x${string}`, - topics: [ - '0x3f18354abbd5306dd1665c2c90f614a4559e39dd620d04fbe5458e613b6588f3' as `0x${string}`, - ], - data: '0x000000000000000000000000961da14c99217789106f0c246c0f66b49fe266ff000000000000000000000000774d0b2991e1af5303ea6c054c78fa856d0f550c2d142ba44ee9104f8cd702bfe7520e64eb8531c5e4e4ded80c6a93cf5a3d113e000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda0291300000000000000000000000000000000000000000000000000000000000f4240' as `0x${string}`, - blockNumber: 38041056n, - transactionHash: - '0x3643966559066142bd0ed23dd9f7834087c7c7a95930219a59924c37b9e4a1bc' as `0x${string}`, - transactionIndex: 0, - blockHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - logIndex: 2, - removed: false, - } - - const event = PushedEvent.fromLog(log) - - expect(event.maker.toString()).toBe('0x961da14c99217789106f0c246c0f66b49fe266ff') - expect(event.app.toString()).toBe('0x774d0b2991e1af5303ea6c054c78fa856d0f550c') - expect(event.strategyHash.toString()).toBe( - '0x2d142ba44ee9104f8cd702bfe7520e64eb8531c5e4e4ded80c6a93cf5a3d113e', - ) - expect(event.token.toString()).toBe('0x833589fcd6edb6e08f4c7c32d4f71b54bda02913') - expect(event.amount).toBe(1000000n) - }) - - it('should decode multiple pushed events from same transaction', () => { - const logs: Log[] = [ - { - address: '0x51b66446ebb060cb0571a6fcbccde855d091dc16' as `0x${string}`, - topics: [ - '0x3f18354abbd5306dd1665c2c90f614a4559e39dd620d04fbe5458e613b6588f3' as `0x${string}`, - ], - data: '0x000000000000000000000000961da14c99217789106f0c246c0f66b49fe266ff000000000000000000000000774d0b2991e1af5303ea6c054c78fa856d0f550c2d142ba44ee9104f8cd702bfe7520e64eb8531c5e4e4ded80c6a93cf5a3d113e000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda0291300000000000000000000000000000000000000000000000000000000000f4240' as `0x${string}`, - blockNumber: 38041056n, - transactionHash: - '0x3643966559066142bd0ed23dd9f7834087c7c7a95930219a59924c37b9e4a1bc' as `0x${string}`, - transactionIndex: 0, - blockHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - logIndex: 0, - removed: false, - }, - { - address: '0x51b66446ebb060cb0571a6fcbccde855d091dc16' as `0x${string}`, - topics: [ - '0x3f18354abbd5306dd1665c2c90f614a4559e39dd620d04fbe5458e613b6588f3' as `0x${string}`, - ], - data: '0x000000000000000000000000961da14c99217789106f0c246c0f66b49fe266ff000000000000000000000000774d0b2991e1af5303ea6c054c78fa856d0f550c2d142ba44ee9104f8cd702bfe7520e64eb8531c5e4e4ded80c6a93cf5a3d113e000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913000000000000000000000000000000000000000000000000000000000001e848' as `0x${string}`, - blockNumber: 38041056n, - transactionHash: - '0x3643966559066142bd0ed23dd9f7834087c7c7a95930219a59924c37b9e4a1bc' as `0x${string}`, - transactionIndex: 0, - blockHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - logIndex: 1, - removed: false, - }, - { - address: '0x51b66446ebb060cb0571a6fcbccde855d091dc16' as `0x${string}`, - topics: [ - '0x3f18354abbd5306dd1665c2c90f614a4559e39dd620d04fbe5458e613b6588f3' as `0x${string}`, - ], - data: '0x000000000000000000000000961da14c99217789106f0c246c0f66b49fe266ff000000000000000000000000774d0b2991e1af5303ea6c054c78fa856d0f550c2d142ba44ee9104f8cd702bfe7520e64eb8531c5e4e4ded80c6a93cf5a3d113e000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913000000000000000000000000000000000000000000000000000000000002dc6c' as `0x${string}`, - blockNumber: 38041056n, - transactionHash: - '0x3643966559066142bd0ed23dd9f7834087c7c7a95930219a59924c37b9e4a1bc' as `0x${string}`, - transactionIndex: 0, - blockHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - logIndex: 2, - removed: false, - }, - ] - - const events = logs.map((log) => PushedEvent.fromLog(log)) - - expect(events).toHaveLength(3) - - events.forEach((event) => { - expect(event.maker.toString()).toBe('0x961da14c99217789106f0c246c0f66b49fe266ff') - expect(event.app.toString()).toBe('0x774d0b2991e1af5303ea6c054c78fa856d0f550c') - expect(event.strategyHash.toString()).toBe( - '0x2d142ba44ee9104f8cd702bfe7520e64eb8531c5e4e4ded80c6a93cf5a3d113e', - ) - expect(event.token.toString()).toBe('0x833589fcd6edb6e08f4c7c32d4f71b54bda02913') - }) - - expect(events[0].amount).toBe(1000000n) - expect(events[1].amount).toBe(125000n) - expect(events[2].amount).toBe(187500n) - }) - - it('should throw on invalid topic', () => { - const log: Log = { - address: mockApp as `0x${string}`, - topics: ['0xdeadbeef' as `0x${string}`], - data: `0x${'0'.padStart(320, '0')}` as `0x${string}`, - blockNumber: 1n, - transactionHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - transactionIndex: 0, - blockHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - logIndex: 0, - removed: false, - } - - expect(() => PushedEvent.fromLog(log)).toThrow() - }) - - it('should throw on missing data', () => { - const log: Log = { - address: mockApp as `0x${string}`, - topics: [PushedEvent.TOPIC.toString() as `0x${string}`], - data: '0x' as `0x${string}`, - blockNumber: 1n, - transactionHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - transactionIndex: 0, - blockHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - logIndex: 0, - removed: false, - } - - expect(() => PushedEvent.fromLog(log)).toThrow() - }) - - it('should throw on invalid data format', () => { - const log: Log = { - address: mockApp as `0x${string}`, - topics: [PushedEvent.TOPIC.toString() as `0x${string}`], - data: '0xnotvalid' as `0x${string}`, - blockNumber: 1n, - transactionHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - transactionIndex: 0, - blockHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - logIndex: 0, - removed: false, - } - - expect(() => PushedEvent.fromLog(log)).toThrow() - }) - }) -}) diff --git a/typescript/aqua/src/aqua-protocol-contract/events/pushed-event.ts b/typescript/aqua/src/aqua-protocol-contract/events/pushed-event.ts deleted file mode 100644 index 1c3ecb6..0000000 --- a/typescript/aqua/src/aqua-protocol-contract/events/pushed-event.ts +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-Degensoft-Aqua-Source-1.1 - -import type { LogLike } from '@1inch/sdk-core' -import { decodeEventLog } from 'viem' -import { Address, HexString } from '@1inch/sdk-core' -import { AQUA_ABI } from '../../abi/Aqua.abi' - -export class PushedEvent { - public static TOPIC: HexString = new HexString( - '0x3f18354abbd5306dd1665c2c90f614a4559e39dd620d04fbe5458e613b6588f3', - ) - - constructor( - public readonly maker: Address, - public readonly app: Address, - public readonly strategyHash: HexString, - public readonly token: Address, - public readonly amount: bigint, - ) {} - - /** - * Creates a PushedEvent - * @throws Error if the log data is invalid or doesn't match the expected event structure - */ - static fromLog(log: LogLike): PushedEvent { - const decoded = decodeEventLog({ - abi: AQUA_ABI, - data: log.data, - topics: log.topics, - eventName: 'Pushed', - }) - - const args = decoded.args - - return new PushedEvent( - new Address(args.maker), - new Address(args.app), - new HexString(args.strategyHash), - new Address(args.token), - args.amount, - ) - } -} diff --git a/typescript/aqua/src/aqua-protocol-contract/events/shipped-event.test.ts b/typescript/aqua/src/aqua-protocol-contract/events/shipped-event.test.ts deleted file mode 100644 index 0d79693..0000000 --- a/typescript/aqua/src/aqua-protocol-contract/events/shipped-event.test.ts +++ /dev/null @@ -1,113 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-Degensoft-Aqua-Source-1.1 - -import { describe, it, expect } from 'vitest' -import type { Log } from 'viem' -import { Address, HexString } from '@1inch/sdk-core' -import { ShippedEvent } from './shipped-event' - -describe('ShippedEvent', () => { - const mockMaker = '0x1234567890123456789012345678901234567890' - const mockApp = '0xabcdefabcdefabcdefabcdefabcdefabcdefabcd' - const mockStrategyHash = `0x${'0'.padStart(64, '0')}` - const mockStrategy = `0x${'1'.padStart(128, '1')}` - - describe('constructor', () => { - it('should create ShippedEvent instance', () => { - const event = new ShippedEvent( - new Address(mockMaker), - new Address(mockApp), - new HexString(mockStrategyHash), - new HexString(mockStrategy), - ) - - expect(event.maker.toString()).toBe(mockMaker.toLowerCase()) - expect(event.app.toString()).toBe(mockApp.toLowerCase()) - expect(event.strategyHash.toString()).toBe(mockStrategyHash) - expect(event.strategy.toString()).toBe(mockStrategy) - }) - }) - - describe('fromLog', () => { - it('should decode valid shipped event log', () => { - const log: Log = { - address: '0x774d0b2991e1af5303ea6c054c78fa856d0f550c' as `0x${string}`, - topics: [ - '0xdc3622e06fb145651f567d421c9ef261d71d43e3778b761907bc0d70d42e52b0' as `0x${string}`, - ], - data: '0x000000000000000000000000961da14c99217789106f0c246c0f66b49fe266ff000000000000000000000000774d0b2991e1af5303ea6c054c78fa856d0f550c2d142ba44ee9104f8cd702bfe7520e64eb8531c5e4e4ded80c6a93cf5a3d113e000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000961da14c99217789106f0c246c0f66b49fe266ff10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001e1504000186a010001414535441424c452d313736323837313434373737300000' as `0x${string}`, - blockNumber: 38041056n, - transactionHash: - '0x3643966559066142bd0ed23dd9f7834087c7c7a95930219a59924c37b9e4a1bc' as `0x${string}`, - transactionIndex: 0, - blockHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - logIndex: 0, - removed: false, - } - - const event = ShippedEvent.fromLog(log) - - expect(event.maker.toString()).toBe('0x961da14c99217789106f0c246c0f66b49fe266ff') - expect(event.app.toString()).toBe('0x774d0b2991e1af5303ea6c054c78fa856d0f550c') - expect(event.strategyHash.toString()).toBe( - '0x2d142ba44ee9104f8cd702bfe7520e64eb8531c5e4e4ded80c6a93cf5a3d113e', - ) - expect(event.strategy.toString().startsWith('0x')).toBe(true) - expect(event.strategy.toString()).toBe( - '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000961da14c99217789106f0c246c0f66b49fe266ff10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001e1504000186a010001414535441424c452d313736323837313434373737300000', - ) - }) - - it('should throw on invalid topic', () => { - const log: Log = { - address: '0x774d0b2991e1af5303ea6c054c78fa856d0f550c' as `0x${string}`, - topics: ['0x0000asadasd' as `0x${string}`], - data: '0x000000000000000000000000961da14c99217789106f0c246c0f66b49fe266ff000000000000000000000000774d0b2991e1af5303ea6c054c78fa856d0f550c2d142ba44ee9104f8cd702bfe7520e64eb8531c5e4e4ded80c6a93cf5a3d113e000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000961da14c99217789106f0c246c0f66b49fe266ff10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001e1504000186a010001414535441424c452d313736323837313434373737300000' as `0x${string}`, - blockNumber: 38041056n, - transactionHash: - '0x3643966559066142bd0ed23dd9f7834087c7c7a95930219a59924c37b9e4a1bc' as `0x${string}`, - transactionIndex: 0, - blockHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - logIndex: 0, - removed: false, - } - - expect(() => ShippedEvent.fromLog(log)).toThrow() - }) - - it('should throw on missing data', () => { - const log: Log = { - address: mockApp as `0x${string}`, - topics: [ShippedEvent.TOPIC.toString() as `0x${string}`], - data: '0x' as `0x${string}`, - blockNumber: 38041056n, - transactionHash: - '0x3643966559066142bd0ed23dd9f7834087c7c7a95930219a59924c37b9e4a1bc' as `0x${string}`, - transactionIndex: 0, - blockHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - logIndex: 0, - removed: false, - } - - expect(() => ShippedEvent.fromLog(log)).toThrow() - }) - - it('should throw on invalid data format', () => { - const log: Log = { - address: '0x774d0b2991e1af5303ea6c054c78fa856d0f550c' as `0x${string}`, - topics: [ - '0xdc3622e06fb145651f567d421c9ef261d71d43e3778b761907bc0d70d42e52b0' as `0x${string}`, - ], - data: '0xinvalid' as `0x${string}`, - blockNumber: 38041056n, - transactionHash: - '0x3643966559066142bd0ed23dd9f7834087c7c7a95930219a59924c37b9e4a1bc' as `0x${string}`, - transactionIndex: 0, - blockHash: `0x${'0'.padStart(64, '0')}` as `0x${string}`, - logIndex: 0, - removed: false, - } - - expect(() => ShippedEvent.fromLog(log)).toThrow() - }) - }) -}) diff --git a/typescript/aqua/src/aqua-protocol-contract/events/shipped-event.ts b/typescript/aqua/src/aqua-protocol-contract/events/shipped-event.ts deleted file mode 100644 index 94d05b1..0000000 --- a/typescript/aqua/src/aqua-protocol-contract/events/shipped-event.ts +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-Degensoft-Aqua-Source-1.1 - -import type { LogLike } from '@1inch/sdk-core' -import { decodeEventLog } from 'viem' -import { Address, HexString } from '@1inch/sdk-core' -import { AQUA_ABI } from '../../abi/Aqua.abi' - -export class ShippedEvent { - public static TOPIC: HexString = new HexString( - '0xdc3622e06fb145651f567d421c9ef261d71d43e3778b761907bc0d70d42e52b0', - ) - - constructor( - public readonly maker: Address, - public readonly app: Address, - public readonly strategyHash: HexString, - public readonly strategy: HexString, - ) {} - - /** - * Creates a ShippedEvent - * @throws Error if the log data is invalid or doesn't match the expected event structure - */ - static fromLog(log: LogLike): ShippedEvent { - const decoded = decodeEventLog({ - abi: AQUA_ABI, - data: log.data, - topics: log.topics, - eventName: 'Shipped', - }) - - const { maker, app, strategyHash, strategy } = decoded.args - - return new ShippedEvent( - new Address(maker), - new Address(app), - new HexString(strategyHash), - new HexString(strategy), - ) - } -} diff --git a/typescript/aqua/src/aqua-protocol-contract/index.ts b/typescript/aqua/src/aqua-protocol-contract/index.ts deleted file mode 100644 index 15e26b8..0000000 --- a/typescript/aqua/src/aqua-protocol-contract/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-Degensoft-Aqua-Source-1.1 - -export * from './aqua-protocol-contract' -export * from './types' -export * from './constants' -export * from './events' diff --git a/typescript/aqua/src/aqua-protocol-contract/types.ts b/typescript/aqua/src/aqua-protocol-contract/types.ts deleted file mode 100644 index 0831be9..0000000 --- a/typescript/aqua/src/aqua-protocol-contract/types.ts +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-Degensoft-Aqua-Source-1.1 - -import type { Address, HexString } from '@1inch/sdk-core' - -/** - * Aqua Protocol types for the 4 core methods - */ - -export type ShipArgs = { - app: Address - strategy: HexString - amountsAndTokens: AmountsAndTokens[] -} - -export type AmountsAndTokens = { - amount: bigint - token: Address -} - -export type DockArgs = { - app: Address - /** - * should be as keccak256(strategy) - */ - strategyHash: HexString - tokens: Address[] -} - -export type ShipDecodedResult = { - functionName: string - decodedArgs: ShipArgs -} diff --git a/typescript/aqua/src/index.ts b/typescript/aqua/src/index.ts deleted file mode 100644 index 08d1b43..0000000 --- a/typescript/aqua/src/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-Degensoft-Aqua-Source-1.1 - -export * from './aqua-protocol-contract' -export * as ABI from './abi' - -export { Address, HexString, NetworkEnum, CallInfo } from '@1inch/sdk-core' diff --git a/typescript/aqua/tests/aqua.spec.ts b/typescript/aqua/tests/aqua.spec.ts deleted file mode 100644 index c06b6fe..0000000 --- a/typescript/aqua/tests/aqua.spec.ts +++ /dev/null @@ -1,309 +0,0 @@ -/* eslint-disable max-lines-per-function */ -import 'dotenv/config' -import { Address, HexString } from '@1inch/sdk-core' -import type { Hex } from 'viem' -import { encodeAbiParameters, encodeFunctionData, parseUnits } from 'viem' -import { ADDRESSES } from '@1inch/sdk-core/test-utils' -import type { ReadyEvmFork } from './setup-evm.js' -import { setupEvm } from './setup-evm.js' - -import { AquaProtocolContract } from '../src/aqua-protocol-contract/aqua-protocol-contract.js' -import { AQUA_ABI } from '../src/abi/Aqua.abi.js' - -describe('Aqua', () => { - let forkNode: ReadyEvmFork - let liqProviderAddress: Hex - let swapperAddress: Hex - - const getAquaBalance = async ( - maker: Address | Hex, - app: Address | Hex, - strategyHash: Hex, - token: Address | Hex, - ): Promise => { - const [balance] = await forkNode.provider.readContract({ - address: forkNode.addresses.aqua, - abi: AQUA_ABI, - functionName: 'rawBalances', - args: [maker.toString() as Hex, app.toString() as Hex, strategyHash, token.toString() as Hex], - }) - - return balance - } - - beforeAll(async () => { - forkNode = await setupEvm({ chainId: 1 }) - liqProviderAddress = await forkNode.liqProvider.getAddress() - swapperAddress = await forkNode.swapper.getAddress() - }) - - test('should ship', async () => { - const aqua = new AquaProtocolContract(new Address(forkNode.addresses.aqua)) - const strategyData = { - maker: liqProviderAddress, - token0: ADDRESSES.WETH, - token1: ADDRESSES.USDC, - feeBps: 0n, - salt: '0x0000000000000000000000000000000000000000000000000000000000000001', - } as const - const strategy = encodeAbiParameters( - [ - { - name: 'strategy', - type: 'tuple', - components: [ - { name: 'maker', type: 'address' }, - { name: 'token0', type: 'address' }, - { name: 'token1', type: 'address' }, - { name: 'feeBps', type: 'uint256' }, - { name: 'salt', type: 'bytes32' }, - ], - }, - ], - [strategyData], - ) - const strategyHash = AquaProtocolContract.calculateStrategyHash( - new HexString(strategy), - ).toString() - - const liquidityProvider = forkNode.liqProvider - - const wethBalanceBefore = await getAquaBalance( - liqProviderAddress, - forkNode.addresses.xycSwap, - strategyHash, - ADDRESSES.WETH, - ) - const usdcBalanceBefore = await getAquaBalance( - liqProviderAddress, - forkNode.addresses.xycSwap, - strategyHash, - ADDRESSES.USDC, - ) - - const usdcAmount = parseUnits('1000', 6) - const wethAmount = parseUnits('1', 18) - - const tx = aqua.ship({ - app: new Address(forkNode.addresses.xycSwap), - strategy: new HexString(strategy), - amountsAndTokens: [ - { - amount: usdcAmount, - token: new Address(ADDRESSES.USDC), - }, - { - amount: wethAmount, - token: new Address(ADDRESSES.WETH), - }, - ], - }) - - await liquidityProvider.send(tx) - - const wethBalanceAfter = await getAquaBalance( - liqProviderAddress, - forkNode.addresses.xycSwap, - strategyHash, - ADDRESSES.WETH, - ) - const usdcBalanceAfter = await getAquaBalance( - liqProviderAddress, - forkNode.addresses.xycSwap, - strategyHash, - ADDRESSES.USDC, - ) - - expect(wethBalanceAfter).to.equal(wethBalanceBefore + wethAmount) - expect(usdcBalanceAfter).to.equal(usdcBalanceBefore + usdcAmount) - }) - - test('should swap', async () => { - const strategyData = { - maker: liqProviderAddress, - token0: ADDRESSES.WETH, - token1: ADDRESSES.USDC, - feeBps: 0n, - salt: '0x0000000000000000000000000000000000000000000000000000000000000001', - } as const - const strategy = encodeAbiParameters( - [ - { - name: 'strategy', - type: 'tuple', - components: [ - { name: 'maker', type: 'address' }, - { name: 'token0', type: 'address' }, - { name: 'token1', type: 'address' }, - { name: 'feeBps', type: 'uint256' }, - { name: 'salt', type: 'bytes32' }, - ], - }, - ], - [strategyData], - ) - const strategyHash = AquaProtocolContract.calculateStrategyHash( - new HexString(strategy), - ).toString() - - const swapper = forkNode.swapper - const providerWethBalanceBefore = await getAquaBalance( - liqProviderAddress, - forkNode.addresses.xycSwap, - strategyHash, - ADDRESSES.WETH, - ) - const providerUsdcBalanceBefore = await getAquaBalance( - liqProviderAddress, - forkNode.addresses.xycSwap, - strategyHash, - ADDRESSES.USDC, - ) - const swapperWethBalanceBefore = await swapper.tokenBalance(ADDRESSES.WETH) - const swapperUsdcBalanceBefore = await swapper.tokenBalance(ADDRESSES.USDC) - - const srcAmount = parseUnits('10', 6) - const srcToken = ADDRESSES.USDC - const isZeroForOne = (srcToken as string) == strategyData.token0 - - const encodedData = encodeFunctionData({ - abi: [ - { - type: 'function', - name: 'swap', - inputs: [ - { name: 'app', type: 'address', internalType: 'contract XYCSwap' }, - { - name: 'strategy', - type: 'tuple', - internalType: 'struct XYCSwap.Strategy', - components: [ - { name: 'maker', type: 'address', internalType: 'address' }, - { name: 'token0', type: 'address', internalType: 'address' }, - { name: 'token1', type: 'address', internalType: 'address' }, - { name: 'feeBps', type: 'uint256', internalType: 'uint256' }, - { name: 'salt', type: 'bytes32', internalType: 'bytes32' }, - ], - }, - { name: 'zeroForOne', type: 'bool', internalType: 'bool' }, - { name: 'amountIn', type: 'uint256', internalType: 'uint256' }, - ], - outputs: [{ name: 'amountOut', type: 'uint256', internalType: 'uint256' }], - stateMutability: 'nonpayable', - }, - ], - functionName: 'swap', - args: [forkNode.addresses.xycSwap, strategyData, isZeroForOne, srcAmount], - }) - - // Simulate the call to get the dstAmount - const simulateResult = await forkNode.provider.call({ - account: swapperAddress, - to: forkNode.addresses.testTrader, - value: 0n, - data: encodedData, - }) - - const dstAmount = BigInt(simulateResult.data || '0x0') - - const swapTx = await swapper.send({ - to: forkNode.addresses.testTrader, - value: 0n, - data: encodedData, - }) - - await forkNode.provider.waitForTransactionReceipt({ hash: swapTx.txHash }) - - const providerWethBalanceAfter = await getAquaBalance( - liqProviderAddress, - forkNode.addresses.xycSwap, - strategyHash, - ADDRESSES.WETH, - ) - const providerUsdcBalanceAfter = await getAquaBalance( - liqProviderAddress, - forkNode.addresses.xycSwap, - strategyHash, - ADDRESSES.USDC, - ) - expect(providerWethBalanceAfter).to.equal(providerWethBalanceBefore - dstAmount) - expect(providerUsdcBalanceAfter).to.equal(providerUsdcBalanceBefore + srcAmount) - - const swapperWethBalanceAfter = await swapper.tokenBalance(ADDRESSES.WETH) - const swapperUsdcBalanceAfter = await swapper.tokenBalance(ADDRESSES.USDC) - expect(swapperWethBalanceAfter).to.equal(swapperWethBalanceBefore + dstAmount) - expect(swapperUsdcBalanceAfter).to.equal(swapperUsdcBalanceBefore - srcAmount) - }) - - test('should dock', async () => { - const aqua = new AquaProtocolContract(new Address(forkNode.addresses.aqua)) - const strategyData = { - maker: liqProviderAddress, - token0: ADDRESSES.WETH, - token1: ADDRESSES.USDC, - feeBps: 0n, - salt: '0x0000000000000000000000000000000000000000000000000000000000000001', - } as const - const strategy = encodeAbiParameters( - [ - { - name: 'strategy', - type: 'tuple', - components: [ - { name: 'maker', type: 'address' }, - { name: 'token0', type: 'address' }, - { name: 'token1', type: 'address' }, - { name: 'feeBps', type: 'uint256' }, - { name: 'salt', type: 'bytes32' }, - ], - }, - ], - [strategyData], - ) - const strategyHash = AquaProtocolContract.calculateStrategyHash( - new HexString(strategy), - ).toString() - - const liquidityProvider = forkNode.liqProvider - - const wethBalanceBefore = await getAquaBalance( - liqProviderAddress, - forkNode.addresses.xycSwap, - strategyHash, - ADDRESSES.WETH, - ) - const usdcBalanceBefore = await getAquaBalance( - liqProviderAddress, - forkNode.addresses.xycSwap, - strategyHash, - ADDRESSES.USDC, - ) - - expect(wethBalanceBefore).to.greaterThan(0) - expect(usdcBalanceBefore).to.greaterThan(0) - - const tx = aqua.dock({ - app: new Address(forkNode.addresses.xycSwap), - strategyHash: new HexString(strategyHash), - tokens: [ADDRESSES.USDC, ADDRESSES.WETH].map((a) => new Address(a)), - }) - - await liquidityProvider.send(tx) - - const wethBalanceAfter = await getAquaBalance( - liqProviderAddress, - forkNode.addresses.xycSwap, - strategyHash, - ADDRESSES.WETH, - ) - const usdcBalanceAfter = await getAquaBalance( - liqProviderAddress, - forkNode.addresses.xycSwap, - strategyHash, - ADDRESSES.USDC, - ) - - expect(wethBalanceAfter).to.eq(0n) - expect(usdcBalanceAfter).to.eq(0n) - }) -}) diff --git a/typescript/aqua/tests/setup-evm.ts b/typescript/aqua/tests/setup-evm.ts deleted file mode 100644 index c7736db..0000000 --- a/typescript/aqua/tests/setup-evm.ts +++ /dev/null @@ -1,261 +0,0 @@ -/* eslint-disable no-console */ -import type { StartedTestContainer } from 'testcontainers' -import { GenericContainer } from 'testcontainers' -import { LogWaitStrategy } from 'testcontainers/build/wait-strategies/log-wait-strategy' -import type { - WalletClient, - Abi, - Transport, - Hex, - ContractConstructorArgs, - RpcSchema, - PublicRpcSchema, - Chain, - Account, - Prettify, - TestActions, - TestRpcSchema, - Client, - PublicActions, -} from 'viem' -import { - parseEther, - parseUnits, - createTestClient, - http, - createWalletClient, - publicActions, -} from 'viem' - -import { mainnet } from 'viem/chains' - -import Aqua from '@contracts/Aqua.sol/Aqua.json' -import TestTrader from '@contracts/TestTrader.sol/TestTrader.json' -import TestXYCSwap from '@contracts/TestXYCSwap.sol/TestXYCSwap.json' - -import { TestWallet, ADDRESSES } from '@1inch/sdk-core/test-utils' -import { privateKeyToAccount } from 'viem/accounts' - -export type EvmNodeConfig = { - chainId?: number - forkUrl?: string - forkHeader?: string -} - -export type ReadyEvmFork = { - chainId: number - localNode: StartedTestContainer - provider: _Client - addresses: TestAddresses - liqProvider: TestWallet - swapper: TestWallet -} - -// Setup evm fork with escrow factory contract and users with funds -// maker have WETH -// taker have USDC on resolver contract -export async function setupEvm(config: EvmNodeConfig): Promise { - const chainId = config.chainId || 1 - const forkUrl = config.forkUrl ?? (process.env.FORK_URL || 'https://eth.llamarpc.com') - const forkHeader = config.forkUrl ?? process.env.FORK_HEADER - - const { localNode, provider, transport, chain } = await startNode(chainId, forkUrl, forkHeader) - - const liqProvider = new TestWallet( - '0x37d5819e14a620d31d0ba9aab2b5154aa000c5519ae602158ddbe6369dca91fb', - transport, - chain, - ) - - const swapper = await TestWallet.fromAddress( - '0x1d83cc9b3Fe9Ee21c45282Bef1BEd27Dfa689EA2', - transport, - chain, - ) - const addresses = await deployContracts(transport, chain) - await setupBalances(liqProvider, swapper, transport, chain, addresses) - - return { - chainId, - addresses, - localNode, - provider, - liqProvider, - swapper, - } -} - -// Available Accounts -// ================== -// (0) 0x8b83C50040c743E99bD47F4327BFcf7913c505B4 (10000.000000000000000000 ETH) maker -// (1) 0x1d83cc9b3Fe9Ee21c45282Bef1BEd27Dfa689EA2 (10000.000000000000000000 ETH) taker -// (2) 0x07a4D77190De10f0D8bDEbBDCdc73853AE4cCdf6 (10000.000000000000000000 ETH) -// (3) 0x8b6Ffe431Cec18FED09b7CaFF804888EeF39D009 (10000.000000000000000000 ETH) -// (4) 0x2bf8553fbCd3580EaBfbF29F6D3AF2a412f38EC1 (10000.000000000000000000 ETH) -// (5) 0xB91be682Dd4fbF00aeE9Cc2FDBe765f1D0eA65AA (10000.000000000000000000 ETH) -// (6) 0xBDF48b349798BdD3C220F4c9FEf7c29C9201E50A (10000.000000000000000000 ETH) -// (7) 0xCBb5815C183295348E1C6603c28d0660E31Dda17 (10000.000000000000000000 ETH) -// (8) 0xfF989B7F90E304033f692C9b6613a70458D3Df22 (10000.000000000000000000 ETH) -// (9) 0xCCEEB333F0a8D9C064Ca32779D8544aaC0201c68 (10000.000000000000000000 ETH) deployer -// -// Private Keys -// ================== -// (0) 0x37d5819e14a620d31d0ba9aab2b5154aa000c5519ae602158ddbe6369dca91fb -// (1) 0xebaffe18fd4f341e6ae52d86b6c6d8fc68d8af0fecc8e43add42e1f6d6aa9808 -// (2) 0x2d6e2a0548113d7af8c7dd74be13aff61e0c71ea529c6e5270cdfe5f477587c1 -// (3) 0xf8577fae1ab233268121f4fba4f00e3792130bf516b5a94a425f5d468d0cf29e -// (4) 0x83190e27ec70886b3a9f4692fa157a79b061dee35c471efea84ce1837257b114 -// (5) 0x5b3a831f58aa3965ba0a70b8ed71c3b386544a3a3141f855997f81b8eed7f372 -// (6) 0x437ebdcdb8ca10cd263bd21b4da1fada08032474e676d2043d854322b125c226 -// (7) 0x7ce41c59ce82cb25399e64a1fe7f68a2239a7a8470abf4dd0e027417dd61e430 -// (8) 0x64892fbe089cc18dc545a44f233c4b58e6b1279f0a6659367ba1df6cec4ae477 -// (9) 0x3667482b9520ea17999acd812ad3db1ff29c12c006e756cdcb5fd6cc5d5a9b01 -async function startNode( - chainId: number, - forkUrl: string, - forkHeader?: string, -): Promise<{ - localNode: StartedTestContainer - provider: _Client - transport: Transport - chain: Chain -}> { - const innerPort = 8545 - const anvil = await new GenericContainer('ghcr.io/foundry-rs/foundry:v1.2.3') - .withExposedPorts(innerPort) - .withCommand([ - `anvil -f ${forkUrl} --fork-header "${forkHeader || 'x-test: test'}" --chain-id ${chainId} --mnemonic 'hat hat horse border print cancel subway heavy copy alert eternal mask' --host 0.0.0.0`, - ]) - // .withLogConsumer((s) => s.pipe(process.stdout)) - .withWaitStrategy(new LogWaitStrategy('Listening on 0.0.0.0:8545', 1)) - .withName(`anvil_aqua_tests_${chainId}_${Math.random()}`) - .start() - - const url = `http://127.0.0.1:${anvil.getMappedPort(innerPort)}` - - const chain = { ...mainnet, id: chainId } as typeof mainnet - const transport = http(url) - - return { - localNode: anvil, - provider: createTestClient<'anvil', typeof transport, typeof chain, undefined, PublicRpcSchema>( - { - transport, - mode: 'anvil', - chain, - }, - ).extend(publicActions) as unknown as _Client, - transport, - chain, - } -} - -async function deployContracts(transport: Transport, chain: Chain): Promise { - const deployer = createWalletClient({ - account: privateKeyToAccount( - '0x3667482b9520ea17999acd812ad3db1ff29c12c006e756cdcb5fd6cc5d5a9b01', - ), - transport, - chain, - }) - - const aqua = await deploy(Aqua as ContractParams, [], deployer) - const xycSwap = await deploy(TestXYCSwap as ContractParams, [aqua], deployer) - const testTrader = await deploy( - TestTrader as ContractParams, - [aqua, [ADDRESSES.WETH, ADDRESSES.USDC]], - deployer, - ) - - return { - aqua, - testTrader, - xycSwap, - } -} - -async function setupBalances( - liqProvider: TestWallet, - swapper: TestWallet, - transport: Transport, - chain: Chain, - addresses: TestAddresses, -): Promise { - const usdcDonor = await TestWallet.fromAddress(ADDRESSES.USDC_DONOR, transport, chain) - - // liqProvider have WETH and USDC - await liqProvider.transfer(ADDRESSES.WETH, parseEther('100')) - await liqProvider.unlimitedApprove(ADDRESSES.WETH, addresses.aqua) - await liqProvider.unlimitedApprove(ADDRESSES.USDC, addresses.aqua) - await usdcDonor.transferToken( - ADDRESSES.USDC, - await liqProvider.getAddress(), - parseUnits('100000', 6), - ) - - // swapper have USDC - await usdcDonor.transferToken(ADDRESSES.USDC, await swapper.getAddress(), parseUnits('10000', 6)) - await swapper.unlimitedApprove(ADDRESSES.USDC, addresses.testTrader) - - console.log('swapper address is', await swapper.getAddress()) - console.log('swapper USDC balance is', await swapper.tokenBalance(ADDRESSES.USDC)) - console.log('swapper WETH balance is', await swapper.tokenBalance(ADDRESSES.WETH)) - - console.log('liquidity provider address is', await liqProvider.getAddress()) - console.log('liquidity provider USDC balance is', await liqProvider.tokenBalance(ADDRESSES.USDC)) - console.log('liquidity provider WETH balance is', await liqProvider.tokenBalance(ADDRESSES.WETH)) -} - -/** - * Deploy contract and return its address - */ -async function deploy( - json: ContractParams, - params: ContractConstructorArgs, - deployer: WalletClient, -): Promise { - const [account] = await deployer.getAddresses() - - const txHash = await deployer.deployContract({ - abi: json.abi, - bytecode: json.bytecode.object, - args: params, - account, - chain: deployer.chain, - }) - - // Get the contract address from the transaction receipt - const publicClient = deployer.extend(publicActions) - const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash }) - - return receipt.contractAddress as Hex -} - -type ContractParams = { abi: Abi; bytecode: { object: Hex } } - -export type TestAddresses = { - aqua: Hex - testTrader: Hex - xycSwap: Hex -} - -export type TestClient< - transport extends Transport = Transport, - chain extends Chain | undefined = Chain | undefined, - account extends Account | undefined = Account | undefined, - includeActions extends boolean = true, - rpcSchema extends RpcSchema | undefined = undefined, - mode extends 'anvil' = 'anvil', -> = Prettify< - { mode: mode } & Client< - transport, - chain, - account, - rpcSchema extends RpcSchema ? [...TestRpcSchema, ...rpcSchema] : TestRpcSchema, - { mode: mode } & (includeActions extends true - ? TestActions & PublicActions - : Record) - > -> - -export type _Client = TestClient diff --git a/typescript/aqua/tsconfig.json b/typescript/aqua/tsconfig.json deleted file mode 100644 index 369689b..0000000 --- a/typescript/aqua/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../tsconfig.base.json", - "compilerOptions": { - "outDir": "./dist", - "baseUrl": "./src" - }, - "include": ["src/**/*.ts"], - "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"] -} diff --git a/typescript/aqua/tsconfig.spec.json b/typescript/aqua/tsconfig.spec.json deleted file mode 100644 index d866144..0000000 --- a/typescript/aqua/tsconfig.spec.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "types": ["vitest/globals", "node"] - }, - "include": ["src/**/*.test.ts", "src/**/*.spec.ts"] -} diff --git a/typescript/aqua/tsdown.config.js b/typescript/aqua/tsdown.config.js deleted file mode 100644 index fb0bb40..0000000 --- a/typescript/aqua/tsdown.config.js +++ /dev/null @@ -1,24 +0,0 @@ -import { defineConfig } from 'tsdown' - -export default defineConfig({ - entry: ['src/index.ts'], - platform: 'neutral', - exports: { - customExports(exports, _ctx) { - for (const [exp, map] of Object.entries(exports)) { - if (map instanceof Object) { - const types = map.require.replace(/\.js$/, '.d.ts') - exports[exp] = { types, ...map } - } - } - - return exports - }, - }, - unbundle: false, - dts: { - build: true, - }, - outDir: './dist', - format: ['cjs', 'esm'], -}) diff --git a/typescript/aqua/vitest.config.mts b/typescript/aqua/vitest.config.mts deleted file mode 100644 index d497136..0000000 --- a/typescript/aqua/vitest.config.mts +++ /dev/null @@ -1,17 +0,0 @@ -import { defineConfig } from 'vitest/config' -import tsconfigPaths from 'vite-tsconfig-paths' - -export default defineConfig({ - root: __dirname, - plugins: [tsconfigPaths()], - test: { - globals: true, - environment: 'node', - include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - coverage: { - reportsDirectory: '../../coverage/typescript/aqua', - include: ['src'], - exclude: ['**/index.ts', '**/constants.ts', '**/types.ts'], - }, - }, -}) diff --git a/typescript/aqua/vitest.e2e.config.mts b/typescript/aqua/vitest.e2e.config.mts deleted file mode 100644 index abcb4f8..0000000 --- a/typescript/aqua/vitest.e2e.config.mts +++ /dev/null @@ -1,14 +0,0 @@ -import { defineConfig } from 'vitest/config' -import tsconfigPaths from 'vite-tsconfig-paths' - -export default defineConfig({ - root: __dirname, - plugins: [tsconfigPaths()], - test: { - globals: true, - environment: 'node', - include: ['tests/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts}'], - hookTimeout: 60_000, - testTimeout: 60_000, - }, -})