@clober/v2-sdk 0.0.6 → 0.0.7-5.dev
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -4
- package/dist/cjs/abis/core/book-manager-abi.js +112 -0
- package/dist/cjs/abis/core/book-manager-abi.js.map +1 -0
- package/dist/cjs/abis/core/book-viewer-abi.js +137 -5
- package/dist/cjs/abis/core/book-viewer-abi.js.map +1 -1
- package/dist/cjs/abis/core/controller-abi.js +29 -24
- package/dist/cjs/abis/core/controller-abi.js.map +1 -1
- package/dist/cjs/abis/rebalancer/minter-abi.js +230 -0
- package/dist/cjs/abis/rebalancer/minter-abi.js.map +1 -0
- package/dist/cjs/abis/rebalancer/mock-swap-abi.js +95 -0
- package/dist/cjs/abis/rebalancer/mock-swap-abi.js.map +1 -0
- package/dist/cjs/abis/rebalancer/operator-abi.js +375 -0
- package/dist/cjs/abis/rebalancer/operator-abi.js.map +1 -0
- package/dist/cjs/abis/rebalancer/rebalancer-abi.js +1367 -0
- package/dist/cjs/abis/rebalancer/rebalancer-abi.js.map +1 -0
- package/dist/cjs/abis/rebalancer/strategy-abi.js +780 -0
- package/dist/cjs/abis/rebalancer/strategy-abi.js.map +1 -0
- package/dist/cjs/apis/chart-logs.js +163 -0
- package/dist/cjs/apis/chart-logs.js.map +1 -0
- package/dist/cjs/apis/market.js +40 -21
- package/dist/cjs/apis/market.js.map +1 -1
- package/dist/cjs/apis/odos.js +100 -0
- package/dist/cjs/apis/odos.js.map +1 -0
- package/dist/cjs/apis/open-order.js +60 -28
- package/dist/cjs/apis/open-order.js.map +1 -1
- package/dist/cjs/apis/pool.js +79 -0
- package/dist/cjs/apis/pool.js.map +1 -0
- package/dist/cjs/apis/strategy.js +30 -0
- package/dist/cjs/apis/strategy.js.map +1 -0
- package/dist/cjs/approval.js +85 -31
- package/dist/cjs/approval.js.map +1 -1
- package/dist/cjs/call.js +837 -155
- package/dist/cjs/call.js.map +1 -1
- package/dist/cjs/constants/addresses.js +50 -1
- package/dist/cjs/constants/addresses.js.map +1 -1
- package/dist/cjs/constants/bera-bartio-chain.js +30 -0
- package/dist/cjs/constants/bera-bartio-chain.js.map +1 -0
- package/dist/cjs/constants/chain.js +18 -2
- package/dist/cjs/constants/chain.js.map +1 -1
- package/dist/cjs/constants/currency.js +56 -3
- package/dist/cjs/constants/currency.js.map +1 -1
- package/dist/cjs/constants/fee.js +17 -2
- package/dist/cjs/constants/fee.js.map +1 -1
- package/dist/cjs/constants/permit.js +14 -0
- package/dist/cjs/constants/permit.js.map +1 -0
- package/dist/cjs/constants/price.js +2 -1
- package/dist/cjs/constants/price.js.map +1 -1
- package/dist/cjs/constants/subgraph.js +35 -0
- package/dist/cjs/constants/subgraph.js.map +1 -0
- package/dist/cjs/constants/test-chain.js +50 -0
- package/dist/cjs/constants/test-chain.js.map +1 -0
- package/dist/cjs/constants/tick.js +6 -0
- package/dist/cjs/constants/tick.js.map +1 -0
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/model/book.js +62 -35
- package/dist/cjs/model/book.js.map +1 -1
- package/dist/cjs/model/chart-log.js +3 -0
- package/dist/cjs/model/chart-log.js.map +1 -0
- package/dist/cjs/model/market.js +61 -26
- package/dist/cjs/model/market.js.map +1 -1
- package/dist/cjs/model/pool.js +240 -0
- package/dist/cjs/model/pool.js.map +1 -0
- package/dist/cjs/type.js +16 -1
- package/dist/cjs/type.js.map +1 -1
- package/dist/cjs/utils/allowance.js +39 -0
- package/dist/cjs/utils/allowance.js.map +1 -0
- package/dist/cjs/utils/approval.js +2 -3
- package/dist/cjs/utils/approval.js.map +1 -1
- package/dist/cjs/utils/bigint.js +13 -0
- package/dist/cjs/utils/bigint.js.map +1 -0
- package/dist/cjs/utils/book-id.js +7 -7
- package/dist/cjs/utils/book-id.js.map +1 -1
- package/dist/cjs/utils/build-transaction.js +9 -9
- package/dist/cjs/utils/build-transaction.js.map +1 -1
- package/dist/cjs/utils/currency.js +95 -11
- package/dist/cjs/utils/currency.js.map +1 -1
- package/dist/cjs/utils/market.js +1 -1
- package/dist/cjs/utils/market.js.map +1 -1
- package/dist/cjs/utils/math.js +3 -1
- package/dist/cjs/utils/math.js.map +1 -1
- package/dist/cjs/utils/open.js +35 -25
- package/dist/cjs/utils/open.js.map +1 -1
- package/dist/cjs/utils/order.js +115 -0
- package/dist/cjs/utils/order.js.map +1 -0
- package/dist/cjs/utils/pool-key.js +17 -0
- package/dist/cjs/utils/pool-key.js.map +1 -0
- package/dist/cjs/utils/pool.js +88 -0
- package/dist/cjs/utils/pool.js.map +1 -0
- package/dist/cjs/utils/prices.js +40 -5
- package/dist/cjs/utils/prices.js.map +1 -1
- package/dist/cjs/utils/tick.js +12 -1
- package/dist/cjs/utils/tick.js.map +1 -1
- package/dist/cjs/utils/unit-size.js +48 -0
- package/dist/cjs/utils/unit-size.js.map +1 -0
- package/dist/cjs/utils.js +16 -0
- package/dist/cjs/utils.js.map +1 -0
- package/dist/cjs/view.js +271 -40
- package/dist/cjs/view.js.map +1 -1
- package/dist/esm/abis/core/book-manager-abi.js +109 -0
- package/dist/esm/abis/core/book-manager-abi.js.map +1 -0
- package/dist/esm/abis/core/book-viewer-abi.js +137 -5
- package/dist/esm/abis/core/book-viewer-abi.js.map +1 -1
- package/dist/esm/abis/core/controller-abi.js +29 -24
- package/dist/esm/abis/core/controller-abi.js.map +1 -1
- package/dist/esm/abis/rebalancer/minter-abi.js +227 -0
- package/dist/esm/abis/rebalancer/minter-abi.js.map +1 -0
- package/dist/esm/abis/rebalancer/mock-swap-abi.js +92 -0
- package/dist/esm/abis/rebalancer/mock-swap-abi.js.map +1 -0
- package/dist/esm/abis/rebalancer/operator-abi.js +372 -0
- package/dist/esm/abis/rebalancer/operator-abi.js.map +1 -0
- package/dist/esm/abis/rebalancer/rebalancer-abi.js +1364 -0
- package/dist/esm/abis/rebalancer/rebalancer-abi.js.map +1 -0
- package/dist/esm/abis/rebalancer/strategy-abi.js +777 -0
- package/dist/esm/abis/rebalancer/strategy-abi.js.map +1 -0
- package/dist/esm/apis/chart-logs.js +159 -0
- package/dist/esm/apis/chart-logs.js.map +1 -0
- package/dist/esm/apis/market.js +41 -22
- package/dist/esm/apis/market.js.map +1 -1
- package/dist/esm/apis/odos.js +94 -0
- package/dist/esm/apis/odos.js.map +1 -0
- package/dist/esm/apis/open-order.js +61 -28
- package/dist/esm/apis/open-order.js.map +1 -1
- package/dist/esm/apis/pool.js +74 -0
- package/dist/esm/apis/pool.js.map +1 -0
- package/dist/esm/apis/strategy.js +26 -0
- package/dist/esm/apis/strategy.js.map +1 -0
- package/dist/esm/approval.js +122 -45
- package/dist/esm/approval.js.map +1 -1
- package/dist/esm/call.js +942 -270
- package/dist/esm/call.js.map +1 -1
- package/dist/esm/constants/addresses.js +51 -2
- package/dist/esm/constants/addresses.js.map +1 -1
- package/dist/esm/constants/bera-bartio-chain.js +27 -0
- package/dist/esm/constants/bera-bartio-chain.js.map +1 -0
- package/dist/esm/constants/chain.js +17 -2
- package/dist/esm/constants/chain.js.map +1 -1
- package/dist/esm/constants/currency.js +57 -2
- package/dist/esm/constants/currency.js.map +1 -1
- package/dist/esm/constants/fee.js +17 -2
- package/dist/esm/constants/fee.js.map +1 -1
- package/dist/esm/constants/permit.js +11 -0
- package/dist/esm/constants/permit.js.map +1 -0
- package/dist/esm/constants/price.js +1 -0
- package/dist/esm/constants/price.js.map +1 -1
- package/dist/esm/constants/subgraph.js +31 -0
- package/dist/esm/constants/subgraph.js.map +1 -0
- package/dist/esm/constants/test-chain.js +47 -0
- package/dist/esm/constants/test-chain.js.map +1 -0
- package/dist/esm/constants/tick.js +3 -0
- package/dist/esm/constants/tick.js.map +1 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/model/book.js +62 -35
- package/dist/esm/model/book.js.map +1 -1
- package/dist/esm/model/chart-log.js +2 -0
- package/dist/esm/model/chart-log.js.map +1 -0
- package/dist/esm/model/market.js +63 -28
- package/dist/esm/model/market.js.map +1 -1
- package/dist/esm/model/pool.js +237 -0
- package/dist/esm/model/pool.js.map +1 -0
- package/dist/esm/type.js +15 -0
- package/dist/esm/type.js.map +1 -1
- package/dist/esm/utils/allowance.js +35 -0
- package/dist/esm/utils/allowance.js.map +1 -0
- package/dist/esm/utils/approval.js +2 -3
- package/dist/esm/utils/approval.js.map +1 -1
- package/dist/esm/utils/bigint.js +7 -0
- package/dist/esm/utils/bigint.js.map +1 -0
- package/dist/esm/utils/book-id.js +7 -7
- package/dist/esm/utils/book-id.js.map +1 -1
- package/dist/esm/utils/build-transaction.js +9 -9
- package/dist/esm/utils/build-transaction.js.map +1 -1
- package/dist/esm/utils/currency.js +93 -10
- package/dist/esm/utils/currency.js.map +1 -1
- package/dist/esm/utils/market.js +1 -1
- package/dist/esm/utils/market.js.map +1 -1
- package/dist/esm/utils/math.js +1 -0
- package/dist/esm/utils/math.js.map +1 -1
- package/dist/esm/utils/open.js +33 -23
- package/dist/esm/utils/open.js.map +1 -1
- package/dist/esm/utils/order.js +110 -0
- package/dist/esm/utils/order.js.map +1 -0
- package/dist/esm/utils/pool-key.js +12 -0
- package/dist/esm/utils/pool-key.js.map +1 -0
- package/dist/esm/utils/pool.js +84 -0
- package/dist/esm/utils/pool.js.map +1 -0
- package/dist/esm/utils/prices.js +39 -5
- package/dist/esm/utils/prices.js.map +1 -1
- package/dist/esm/utils/tick.js +11 -1
- package/dist/esm/utils/tick.js.map +1 -1
- package/dist/esm/utils/unit-size.js +44 -0
- package/dist/esm/utils/unit-size.js.map +1 -0
- package/dist/esm/utils.js +4 -0
- package/dist/esm/utils.js.map +1 -0
- package/dist/esm/view.js +410 -79
- package/dist/esm/view.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/types/abis/core/book-manager-abi.d.ts +82 -0
- package/dist/types/abis/core/book-manager-abi.d.ts.map +1 -0
- package/dist/types/abis/core/book-viewer-abi.d.ts +107 -5
- package/dist/types/abis/core/book-viewer-abi.d.ts.map +1 -1
- package/dist/types/abis/core/controller-abi.d.ts +23 -19
- package/dist/types/abis/core/controller-abi.d.ts.map +1 -1
- package/dist/types/abis/rebalancer/minter-abi.d.ts +174 -0
- package/dist/types/abis/rebalancer/minter-abi.d.ts.map +1 -0
- package/dist/types/abis/rebalancer/mock-swap-abi.d.ts +70 -0
- package/dist/types/abis/rebalancer/mock-swap-abi.d.ts.map +1 -0
- package/dist/types/abis/rebalancer/operator-abi.d.ts +287 -0
- package/dist/types/abis/rebalancer/operator-abi.d.ts.map +1 -0
- package/dist/types/abis/rebalancer/rebalancer-abi.d.ts +1056 -0
- package/dist/types/abis/rebalancer/rebalancer-abi.d.ts.map +1 -0
- package/dist/types/abis/rebalancer/strategy-abi.d.ts +602 -0
- package/dist/types/abis/rebalancer/strategy-abi.d.ts.map +1 -0
- package/dist/types/apis/chart-logs.d.ts +5 -0
- package/dist/types/apis/chart-logs.d.ts.map +1 -0
- package/dist/types/apis/market.d.ts +2 -1
- package/dist/types/apis/market.d.ts.map +1 -1
- package/dist/types/apis/odos.d.ts +28 -0
- package/dist/types/apis/odos.d.ts.map +1 -0
- package/dist/types/apis/open-order.d.ts +4 -2
- package/dist/types/apis/open-order.d.ts.map +1 -1
- package/dist/types/apis/pool.d.ts +12 -0
- package/dist/types/apis/pool.d.ts.map +1 -0
- package/dist/types/apis/strategy.d.ts +5 -0
- package/dist/types/apis/strategy.d.ts.map +1 -0
- package/dist/types/approval.d.ts +49 -17
- package/dist/types/approval.d.ts.map +1 -1
- package/dist/types/call.d.ts +311 -133
- package/dist/types/call.d.ts.map +1 -1
- package/dist/types/constants/addresses.d.ts +4 -0
- package/dist/types/constants/addresses.d.ts.map +1 -1
- package/dist/types/constants/bera-bartio-chain.d.ts +33 -0
- package/dist/types/constants/bera-bartio-chain.d.ts.map +1 -0
- package/dist/types/constants/chain.d.ts +7 -2
- package/dist/types/constants/chain.d.ts.map +1 -1
- package/dist/types/constants/currency.d.ts +6 -0
- package/dist/types/constants/currency.d.ts.map +1 -1
- package/dist/types/constants/fee.d.ts +7 -2
- package/dist/types/constants/fee.d.ts.map +1 -1
- package/dist/types/constants/permit.d.ts +10 -0
- package/dist/types/constants/permit.d.ts.map +1 -0
- package/dist/types/constants/price.d.ts +1 -0
- package/dist/types/constants/price.d.ts.map +1 -1
- package/dist/types/constants/subgraph.d.ts +5 -0
- package/dist/types/constants/subgraph.d.ts.map +1 -0
- package/dist/types/constants/test-chain.d.ts +4 -0
- package/dist/types/constants/test-chain.d.ts.map +1 -0
- package/dist/types/constants/tick.d.ts +3 -0
- package/dist/types/constants/tick.d.ts.map +1 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/model/book.d.ts +25 -33
- package/dist/types/model/book.d.ts.map +1 -1
- package/dist/types/model/chart-log.d.ts +9 -0
- package/dist/types/model/chart-log.d.ts.map +1 -0
- package/dist/types/model/currency.d.ts +7 -0
- package/dist/types/model/currency.d.ts.map +1 -1
- package/dist/types/model/depth.d.ts +4 -3
- package/dist/types/model/depth.d.ts.map +1 -1
- package/dist/types/model/market.d.ts +24 -13
- package/dist/types/model/market.d.ts.map +1 -1
- package/dist/types/model/open-order.d.ts +20 -27
- package/dist/types/model/open-order.d.ts.map +1 -1
- package/dist/types/model/pool.d.ts +71 -0
- package/dist/types/model/pool.d.ts.map +1 -0
- package/dist/types/type.d.ts +112 -6
- package/dist/types/type.d.ts.map +1 -1
- package/dist/types/utils/allowance.d.ts +3 -0
- package/dist/types/utils/allowance.d.ts.map +1 -0
- package/dist/types/utils/approval.d.ts +2 -1
- package/dist/types/utils/approval.d.ts.map +1 -1
- package/dist/types/utils/bigint.d.ts +4 -0
- package/dist/types/utils/bigint.d.ts.map +1 -0
- package/dist/types/utils/book-id.d.ts +2 -1
- package/dist/types/utils/book-id.d.ts.map +1 -1
- package/dist/types/utils/build-transaction.d.ts +3 -3
- package/dist/types/utils/build-transaction.d.ts.map +1 -1
- package/dist/types/utils/currency.d.ts +5 -1
- package/dist/types/utils/currency.d.ts.map +1 -1
- package/dist/types/utils/math.d.ts +1 -0
- package/dist/types/utils/math.d.ts.map +1 -1
- package/dist/types/utils/open.d.ts +2 -1
- package/dist/types/utils/open.d.ts.map +1 -1
- package/dist/types/utils/order.d.ts +10 -0
- package/dist/types/utils/order.d.ts.map +1 -0
- package/dist/types/utils/pool-key.d.ts +3 -0
- package/dist/types/utils/pool-key.d.ts.map +1 -0
- package/dist/types/utils/pool.d.ts +11 -0
- package/dist/types/utils/pool.d.ts.map +1 -0
- package/dist/types/utils/prices.d.ts +13 -2
- package/dist/types/utils/prices.d.ts.map +1 -1
- package/dist/types/utils/tick.d.ts +1 -0
- package/dist/types/utils/tick.d.ts.map +1 -1
- package/dist/types/utils/unit-size.d.ts +5 -0
- package/dist/types/utils/unit-size.d.ts.map +1 -0
- package/dist/types/utils.d.ts +4 -0
- package/dist/types/utils.d.ts.map +1 -0
- package/dist/types/view.d.ts +309 -51
- package/dist/types/view.d.ts.map +1 -1
- package/package.json +3 -2
- package/dist/cjs/abis/core/params-abi.js +0 -62
- package/dist/cjs/abis/core/params-abi.js.map +0 -1
- package/dist/cjs/apis/subgraph.js +0 -26
- package/dist/cjs/apis/subgraph.js.map +0 -1
- package/dist/cjs/constants/client.js +0 -14
- package/dist/cjs/constants/client.js.map +0 -1
- package/dist/cjs/constants/subgraph-url.js +0 -8
- package/dist/cjs/constants/subgraph-url.js.map +0 -1
- package/dist/cjs/signature.js +0 -141
- package/dist/cjs/signature.js.map +0 -1
- package/dist/cjs/utils/decorator.js +0 -13
- package/dist/cjs/utils/decorator.js.map +0 -1
- package/dist/cjs/utils/unit.js +0 -34
- package/dist/cjs/utils/unit.js.map +0 -1
- package/dist/esm/abis/core/params-abi.js +0 -59
- package/dist/esm/abis/core/params-abi.js.map +0 -1
- package/dist/esm/apis/subgraph.js +0 -22
- package/dist/esm/apis/subgraph.js.map +0 -1
- package/dist/esm/constants/client.js +0 -10
- package/dist/esm/constants/client.js.map +0 -1
- package/dist/esm/constants/subgraph-url.js +0 -5
- package/dist/esm/constants/subgraph-url.js.map +0 -1
- package/dist/esm/signature.js +0 -171
- package/dist/esm/signature.js.map +0 -1
- package/dist/esm/utils/decorator.js +0 -9
- package/dist/esm/utils/decorator.js.map +0 -1
- package/dist/esm/utils/unit.js +0 -30
- package/dist/esm/utils/unit.js.map +0 -1
- package/dist/types/abis/core/params-abi.d.ts +0 -21
- package/dist/types/abis/core/params-abi.d.ts.map +0 -1
- package/dist/types/apis/subgraph.d.ts +0 -3
- package/dist/types/apis/subgraph.d.ts.map +0 -1
- package/dist/types/constants/client.d.ts +0 -5
- package/dist/types/constants/client.d.ts.map +0 -1
- package/dist/types/constants/subgraph-url.d.ts +0 -5
- package/dist/types/constants/subgraph-url.d.ts.map +0 -1
- package/dist/types/signature.d.ts +0 -44
- package/dist/types/signature.d.ts.map +0 -1
- package/dist/types/utils/decorator.d.ts +0 -6
- package/dist/types/utils/decorator.d.ts.map +0 -1
- package/dist/types/utils/unit.d.ts +0 -4
- package/dist/types/utils/unit.d.ts.map +0 -1
package/dist/esm/call.js
CHANGED
|
@@ -1,65 +1,84 @@
|
|
|
1
|
-
import { formatUnits, isAddressEqual, parseUnits, zeroAddress, zeroHash, } from 'viem';
|
|
1
|
+
import { createPublicClient, formatUnits, getAddress, http, isAddressEqual, parseUnits, zeroAddress, zeroHash, } from 'viem';
|
|
2
2
|
import { CHAIN_MAP } from './constants/chain';
|
|
3
|
-
import {
|
|
3
|
+
import { calculateUnitSize } from './utils/unit-size';
|
|
4
4
|
import { CONTROLLER_ABI } from './abis/core/controller-abi';
|
|
5
5
|
import { getDeadlineTimestampInSeconds } from './utils/time';
|
|
6
6
|
import { buildTransaction } from './utils/build-transaction';
|
|
7
7
|
import { CONTRACT_ADDRESSES } from './constants/addresses';
|
|
8
8
|
import { MAKER_DEFAULT_POLICY, TAKER_DEFAULT_POLICY } from './constants/fee';
|
|
9
9
|
import { fetchMarket } from './apis/market';
|
|
10
|
-
import { parsePrice } from './utils/prices';
|
|
11
|
-
import {
|
|
12
|
-
import { getExpectedOutput,
|
|
10
|
+
import { convertHumanReadablePriceToRawPrice, formatPrice, parsePrice, } from './utils/prices';
|
|
11
|
+
import { invertTick, toPrice } from './utils/tick';
|
|
12
|
+
import { getExpectedInput, getExpectedOutput, getQuoteToken } from './view';
|
|
13
13
|
import { toBookId } from './utils/book-id';
|
|
14
14
|
import { fetchIsApprovedForAll } from './utils/approval';
|
|
15
|
-
import {
|
|
15
|
+
import { fetchOnChainOrders } from './utils/order';
|
|
16
|
+
import { applyPercent } from './utils/bigint';
|
|
17
|
+
import { fetchPool } from './apis/pool';
|
|
18
|
+
import { REBALANCER_ABI } from './abis/rebalancer/rebalancer-abi';
|
|
19
|
+
import { getExpectedMintResult, getIdealDelta } from './utils/pool';
|
|
20
|
+
import { fetchCallData, fetchQuote } from './apis/odos';
|
|
21
|
+
import { MINTER_ABI } from './abis/rebalancer/minter-abi';
|
|
22
|
+
import { emptyERC20PermitParams } from './constants/permit';
|
|
23
|
+
import { abs } from './utils/math';
|
|
24
|
+
import { toBytes32 } from './utils/pool-key';
|
|
25
|
+
import { OPERATOR_ABI } from './abis/rebalancer/operator-abi';
|
|
26
|
+
import { STRATEGY_ABI } from './abis/rebalancer/strategy-abi';
|
|
16
27
|
/**
|
|
17
28
|
* Build a transaction to open a market.
|
|
18
29
|
*
|
|
19
30
|
* @param chainId The chain ID of the blockchain.
|
|
31
|
+
* @param userAddress The address of the user.
|
|
20
32
|
* @param inputToken The address of the input token.
|
|
21
33
|
* @param outputToken The address of the output token.
|
|
22
|
-
* @param options
|
|
23
|
-
* @param options.rpcUrl The RPC URL of the blockchain.
|
|
34
|
+
* @param options {@link DefaultWriteContractOptions} options.
|
|
24
35
|
* @returns A Promise resolving to a transaction object. If the market is already open, returns undefined.
|
|
25
36
|
* @example
|
|
26
37
|
* import { openMarket } from '@clober/v2-sdk'
|
|
27
38
|
*
|
|
28
|
-
* const transaction = await openMarket(
|
|
29
|
-
* 421614,
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
39
|
+
* const transaction = await openMarket({
|
|
40
|
+
* chainId: 421614,
|
|
41
|
+
* userAddress: '0xF8c1869Ecd4df136693C45EcE1b67f85B6bDaE69',
|
|
42
|
+
* inputToken: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
43
|
+
* outputToken: '0x0000000000000000000000000000000000000000'
|
|
44
|
+
* })
|
|
33
45
|
*/
|
|
34
|
-
export const openMarket =
|
|
35
|
-
const
|
|
46
|
+
export const openMarket = async ({ chainId, userAddress, inputToken, outputToken, options, }) => {
|
|
47
|
+
const publicClient = createPublicClient({
|
|
48
|
+
chain: CHAIN_MAP[chainId],
|
|
49
|
+
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
|
|
50
|
+
});
|
|
51
|
+
const market = await fetchMarket(publicClient, chainId, [inputToken, outputToken], !!(options && options.useSubgraph));
|
|
36
52
|
const isBid = isAddressEqual(market.quote.address, inputToken);
|
|
37
|
-
if ((isBid && !market.
|
|
38
|
-
|
|
39
|
-
|
|
53
|
+
if ((isBid && !market.bidBook.isOpened) ||
|
|
54
|
+
(!isBid && !market.askBook.isOpened)) {
|
|
55
|
+
const unitSize = await calculateUnitSize(publicClient, chainId, isBid ? market.quote : market.base);
|
|
56
|
+
return buildTransaction(publicClient, {
|
|
57
|
+
chain: CHAIN_MAP[chainId],
|
|
40
58
|
address: CONTRACT_ADDRESSES[chainId].Controller,
|
|
59
|
+
account: userAddress,
|
|
41
60
|
abi: CONTROLLER_ABI,
|
|
42
61
|
functionName: 'open',
|
|
43
62
|
args: [
|
|
44
63
|
[
|
|
45
64
|
{
|
|
46
65
|
key: {
|
|
47
|
-
base:
|
|
48
|
-
|
|
49
|
-
quote:
|
|
50
|
-
makerPolicy: MAKER_DEFAULT_POLICY.value,
|
|
66
|
+
base: outputToken,
|
|
67
|
+
unitSize,
|
|
68
|
+
quote: inputToken,
|
|
69
|
+
makerPolicy: MAKER_DEFAULT_POLICY[chainId].value,
|
|
51
70
|
hooks: zeroAddress,
|
|
52
|
-
takerPolicy: TAKER_DEFAULT_POLICY.value,
|
|
71
|
+
takerPolicy: TAKER_DEFAULT_POLICY[chainId].value,
|
|
53
72
|
},
|
|
54
73
|
hookData: zeroHash,
|
|
55
74
|
},
|
|
56
75
|
],
|
|
57
76
|
getDeadlineTimestampInSeconds(),
|
|
58
77
|
],
|
|
59
|
-
});
|
|
78
|
+
}, options?.gasLimit);
|
|
60
79
|
}
|
|
61
80
|
return undefined;
|
|
62
|
-
}
|
|
81
|
+
};
|
|
63
82
|
/**
|
|
64
83
|
* Places a limit order on the specified chain for trading tokens.
|
|
65
84
|
*
|
|
@@ -69,66 +88,76 @@ export const openMarket = decorator(async ({ chainId, inputToken, outputToken, }
|
|
|
69
88
|
* @param {`0x${string}`} outputToken The address of the token to be received as output.
|
|
70
89
|
* @param {string} amount The amount of input tokens for the order.
|
|
71
90
|
* @param {string} price The price at which the order should be executed.
|
|
72
|
-
* @param {
|
|
73
|
-
* @param {
|
|
91
|
+
* @param options {@link DefaultWriteContractOptions} options.
|
|
92
|
+
* @param {erc20PermitParam} [options.erc20PermitParam] The permit signature for token approval.
|
|
74
93
|
* @param {boolean} [options.postOnly] A boolean indicating whether the order is only to be made not taken.
|
|
75
|
-
* @param {
|
|
76
|
-
* @
|
|
94
|
+
* @param {bigint} [options.makeTick] The tick for the make order.
|
|
95
|
+
* @param {bigint} [options.takeLimitTick] The tick for the take order.
|
|
96
|
+
* @param {boolean} [options.roundingUpMakeBid] A boolean indicating whether to round up the make bid.
|
|
97
|
+
* @param {boolean} [options.roundingDownMakeAsk] A boolean indicating whether to round down the make ask.
|
|
98
|
+
* @param {boolean} [options.roundingDownTakenBid] A boolean indicating whether to round down the taken bid.
|
|
99
|
+
* @param {boolean} [options.roundingUpTakenAsk] A boolean indicating whether to round up the taken ask.
|
|
100
|
+
* @returns {Promise<{ transaction: Transaction, result: { make: CurrencyFlow, take: CurrencyFlow, spent: CurrencyFlow }>}
|
|
77
101
|
* Promise resolving to the transaction object representing the limit order with the result of the order.
|
|
78
102
|
* @example
|
|
79
|
-
* import {
|
|
103
|
+
* import { limitOrder } from '@clober/v2-sdk'
|
|
80
104
|
* import { privateKeyToAccount } from 'viem/accounts'
|
|
81
105
|
*
|
|
82
|
-
* const
|
|
83
|
-
* 421614,
|
|
84
|
-
*
|
|
85
|
-
* '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
86
|
-
* '
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
* 421614,
|
|
91
|
-
* '0xF8c1869Ecd4df136693C45EcE1b67f85B6bDaE69
|
|
92
|
-
* '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
93
|
-
* '0x0000000000000000000000000000000000000000',
|
|
94
|
-
* '100.123', // 100.123 USDC
|
|
95
|
-
* '4000.01', // price at 4000.01 (ETH/USDC)
|
|
96
|
-
* { signature }
|
|
97
|
-
* )
|
|
106
|
+
* const { transaction } = await limitOrder({
|
|
107
|
+
* chainId: 421614,
|
|
108
|
+
* userAddress: '0xF8c1869Ecd4df136693C45EcE1b67f85B6bDaE69
|
|
109
|
+
* inputToken: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
110
|
+
* outputToken: '0x0000000000000000000000000000000000000000',
|
|
111
|
+
* amount: '100.123', // 100.123 USDC
|
|
112
|
+
* price: '4000.01', // price at 4000.01 (ETH/USDC)
|
|
113
|
+
* })
|
|
98
114
|
*
|
|
99
115
|
* @example
|
|
100
116
|
* import { limitOrder } from '@clober/v2-sdk'
|
|
101
117
|
*
|
|
102
|
-
* const { transaction } = await limitOrder(
|
|
103
|
-
* 421614,
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* )
|
|
118
|
+
* const { transaction } = await limitOrder({
|
|
119
|
+
* chainId: 421614,
|
|
120
|
+
* userAddress: '0xF8c1869Ecd4df136693C45EcE1b67f85B6bDaE69
|
|
121
|
+
* inputToken: '0x0000000000000000000000000000000000000000',
|
|
122
|
+
* outputToken: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
123
|
+
* amount: '0.13', // 0.13 ETH
|
|
124
|
+
* price: '4000.01', // price at 4000.01 (ETH/USDC)
|
|
125
|
+
* })
|
|
110
126
|
*/
|
|
111
|
-
export const limitOrder =
|
|
112
|
-
const
|
|
127
|
+
export const limitOrder = async ({ chainId, userAddress, inputToken, outputToken, amount, price, options, }) => {
|
|
128
|
+
const [roundingUpMakeBid, roundingDownMakeAsk, roundingDownTakenBid, roundingUpTakenAsk,] = [
|
|
129
|
+
options?.roundingUpMakeBid ? options.roundingUpMakeBid : false,
|
|
130
|
+
options?.roundingDownMakeAsk ? options.roundingDownMakeAsk : false,
|
|
131
|
+
options?.roundingDownTakenBid ? options.roundingDownTakenBid : false,
|
|
132
|
+
options?.roundingUpTakenAsk ? options.roundingUpTakenAsk : false,
|
|
133
|
+
];
|
|
134
|
+
const publicClient = createPublicClient({
|
|
135
|
+
chain: CHAIN_MAP[chainId],
|
|
136
|
+
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
|
|
137
|
+
});
|
|
138
|
+
const market = await fetchMarket(publicClient, chainId, [inputToken, outputToken], !!(options && options.useSubgraph));
|
|
113
139
|
const isBid = isAddressEqual(market.quote.address, inputToken);
|
|
114
|
-
|
|
140
|
+
const [inputCurrency, outputCurrency] = isBid
|
|
141
|
+
? [market.quote, market.base]
|
|
142
|
+
: [market.base, market.quote];
|
|
143
|
+
if ((isBid && !market.bidBook.isOpened) ||
|
|
144
|
+
(!isBid && !market.askBook.isOpened)) {
|
|
115
145
|
throw new Error(`
|
|
116
146
|
Open the market before placing a limit order.
|
|
117
147
|
import { openMarket } from '@clober/v2-sdk'
|
|
118
148
|
|
|
119
|
-
const transaction = await openMarket(
|
|
120
|
-
${chainId},
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
)
|
|
149
|
+
const transaction = await openMarket({
|
|
150
|
+
chainId: ${chainId},
|
|
151
|
+
inputToken: '${inputToken}',
|
|
152
|
+
outputToken: '${outputToken}',
|
|
153
|
+
})
|
|
124
154
|
`);
|
|
125
155
|
}
|
|
126
|
-
const
|
|
127
|
-
const tick = isBid ? fromPrice(rawPrice) : fromPrice(invertPrice(rawPrice));
|
|
156
|
+
const { roundingDownTick, roundingUpTick } = parsePrice(Number(price), market.quote.decimals, market.base.decimals);
|
|
128
157
|
const tokensToSettle = [inputToken, outputToken].filter((address) => !isAddressEqual(address, zeroAddress));
|
|
129
|
-
const quoteAmount = parseUnits(amount,
|
|
130
|
-
const [
|
|
131
|
-
|
|
158
|
+
const quoteAmount = parseUnits(amount, inputCurrency.decimals);
|
|
159
|
+
const [unitSize, { takenAmount, spentAmount, bookId, events }] = await Promise.all([
|
|
160
|
+
calculateUnitSize(publicClient, chainId, inputCurrency),
|
|
132
161
|
getExpectedOutput({
|
|
133
162
|
chainId,
|
|
134
163
|
inputToken,
|
|
@@ -141,24 +170,21 @@ export const limitOrder = decorator(async ({ chainId, userAddress, inputToken, o
|
|
|
141
170
|
}),
|
|
142
171
|
]);
|
|
143
172
|
const isETH = isAddressEqual(inputToken, zeroAddress);
|
|
144
|
-
const permitParamsList = options?.signature && !isETH
|
|
145
|
-
? [
|
|
146
|
-
{
|
|
147
|
-
token: inputToken,
|
|
148
|
-
permitAmount: quoteAmount,
|
|
149
|
-
signature: options.signature,
|
|
150
|
-
},
|
|
151
|
-
]
|
|
152
|
-
: [];
|
|
153
173
|
const makeParam = {
|
|
154
|
-
id: toBookId(inputToken, outputToken,
|
|
155
|
-
tick:
|
|
174
|
+
id: toBookId(chainId, inputToken, outputToken, unitSize),
|
|
175
|
+
tick: options?.makeTick
|
|
176
|
+
? Number(options.makeTick)
|
|
177
|
+
: Number(isBid
|
|
178
|
+
? roundingUpMakeBid
|
|
179
|
+
? roundingUpTick
|
|
180
|
+
: roundingDownTick
|
|
181
|
+
: invertTick(roundingDownMakeAsk ? roundingDownTick : roundingUpTick)),
|
|
156
182
|
quoteAmount,
|
|
157
183
|
hookData: zeroHash,
|
|
158
184
|
};
|
|
159
|
-
if (options?.postOnly === true ||
|
|
185
|
+
if (options?.postOnly === true || spentAmount === '0') {
|
|
160
186
|
return {
|
|
161
|
-
transaction: await buildTransaction(
|
|
187
|
+
transaction: await buildTransaction(publicClient, {
|
|
162
188
|
chain: CHAIN_MAP[chainId],
|
|
163
189
|
account: userAddress,
|
|
164
190
|
address: CONTRACT_ADDRESSES[chainId].Controller,
|
|
@@ -167,21 +193,31 @@ export const limitOrder = decorator(async ({ chainId, userAddress, inputToken, o
|
|
|
167
193
|
args: [
|
|
168
194
|
[makeParam],
|
|
169
195
|
tokensToSettle,
|
|
170
|
-
|
|
196
|
+
options?.erc20PermitParam ? [options.erc20PermitParam] : [],
|
|
171
197
|
getDeadlineTimestampInSeconds(),
|
|
172
198
|
],
|
|
173
199
|
value: isETH ? quoteAmount : 0n,
|
|
174
|
-
}),
|
|
200
|
+
}, options?.gasLimit),
|
|
175
201
|
result: {
|
|
176
202
|
make: {
|
|
177
|
-
amount: formatUnits(quoteAmount,
|
|
178
|
-
currency:
|
|
203
|
+
amount: formatUnits(quoteAmount, inputCurrency.decimals),
|
|
204
|
+
currency: inputCurrency,
|
|
179
205
|
direction: 'in',
|
|
206
|
+
price: formatPrice(isBid
|
|
207
|
+
? toPrice(BigInt(makeParam.tick))
|
|
208
|
+
: toPrice(invertTick(BigInt(makeParam.tick))), market.quote.decimals, market.base.decimals),
|
|
180
209
|
},
|
|
181
|
-
|
|
210
|
+
spent: {
|
|
182
211
|
amount: '0',
|
|
183
|
-
currency:
|
|
212
|
+
currency: inputCurrency,
|
|
213
|
+
direction: 'in',
|
|
214
|
+
events: [],
|
|
215
|
+
},
|
|
216
|
+
taken: {
|
|
217
|
+
amount: '0',
|
|
218
|
+
currency: outputCurrency,
|
|
184
219
|
direction: 'out',
|
|
220
|
+
events: [],
|
|
185
221
|
},
|
|
186
222
|
},
|
|
187
223
|
};
|
|
@@ -189,7 +225,7 @@ export const limitOrder = decorator(async ({ chainId, userAddress, inputToken, o
|
|
|
189
225
|
else {
|
|
190
226
|
// take and make
|
|
191
227
|
return {
|
|
192
|
-
transaction: await buildTransaction(
|
|
228
|
+
transaction: await buildTransaction(publicClient, {
|
|
193
229
|
chain: CHAIN_MAP[chainId],
|
|
194
230
|
account: userAddress,
|
|
195
231
|
address: CONTRACT_ADDRESSES[chainId].Controller,
|
|
@@ -200,7 +236,15 @@ export const limitOrder = decorator(async ({ chainId, userAddress, inputToken, o
|
|
|
200
236
|
{
|
|
201
237
|
takeBookId: bookId,
|
|
202
238
|
makeBookId: makeParam.id,
|
|
203
|
-
limitPrice:
|
|
239
|
+
limitPrice: options?.takeLimitTick
|
|
240
|
+
? toPrice(options.takeLimitTick)
|
|
241
|
+
: toPrice(isBid
|
|
242
|
+
? invertTick(roundingUpTakenAsk
|
|
243
|
+
? roundingUpTick
|
|
244
|
+
: roundingDownTick)
|
|
245
|
+
: roundingDownTakenBid
|
|
246
|
+
? roundingDownTick
|
|
247
|
+
: roundingUpTick),
|
|
204
248
|
tick: makeParam.tick,
|
|
205
249
|
quoteAmount,
|
|
206
250
|
takeHookData: zeroHash,
|
|
@@ -208,75 +252,93 @@ export const limitOrder = decorator(async ({ chainId, userAddress, inputToken, o
|
|
|
208
252
|
},
|
|
209
253
|
],
|
|
210
254
|
tokensToSettle,
|
|
211
|
-
|
|
255
|
+
options?.erc20PermitParam ? [options.erc20PermitParam] : [],
|
|
212
256
|
getDeadlineTimestampInSeconds(),
|
|
213
257
|
],
|
|
214
258
|
value: isETH ? quoteAmount : 0n,
|
|
215
|
-
}),
|
|
259
|
+
}, options?.gasLimit),
|
|
216
260
|
result: {
|
|
217
261
|
make: {
|
|
218
|
-
amount: formatUnits(quoteAmount
|
|
219
|
-
currency:
|
|
262
|
+
amount: formatUnits(quoteAmount - parseUnits(spentAmount, inputCurrency.decimals), inputCurrency.decimals),
|
|
263
|
+
currency: inputCurrency,
|
|
264
|
+
direction: 'in',
|
|
265
|
+
price: formatPrice(isBid
|
|
266
|
+
? toPrice(BigInt(makeParam.tick))
|
|
267
|
+
: toPrice(invertTick(BigInt(makeParam.tick))), market.quote.decimals, market.base.decimals),
|
|
268
|
+
},
|
|
269
|
+
spent: {
|
|
270
|
+
amount: spentAmount,
|
|
271
|
+
currency: inputCurrency,
|
|
220
272
|
direction: 'in',
|
|
273
|
+
events: events.map(({ price, spentAmount }) => ({
|
|
274
|
+
price,
|
|
275
|
+
amount: spentAmount,
|
|
276
|
+
})),
|
|
221
277
|
},
|
|
222
|
-
|
|
223
|
-
amount:
|
|
224
|
-
currency:
|
|
278
|
+
taken: {
|
|
279
|
+
amount: takenAmount,
|
|
280
|
+
currency: outputCurrency,
|
|
225
281
|
direction: 'out',
|
|
282
|
+
events: events.map(({ price, takenAmount }) => ({
|
|
283
|
+
price,
|
|
284
|
+
amount: takenAmount,
|
|
285
|
+
})),
|
|
226
286
|
},
|
|
227
287
|
},
|
|
228
288
|
};
|
|
229
289
|
}
|
|
230
|
-
}
|
|
290
|
+
};
|
|
231
291
|
/**
|
|
232
292
|
* Executes a market order on the specified chain for trading tokens.
|
|
293
|
+
* If only `amountIn` is provided, spend the specified amount of input tokens.
|
|
294
|
+
* If only `amountOut` is provided, take the specified amount of output tokens.
|
|
233
295
|
*
|
|
234
296
|
* @param {CHAIN_IDS} chainId The chain ID.
|
|
235
297
|
* @param {`0x${string}`} userAddress The Ethereum address of the user placing the order.
|
|
236
298
|
* @param {`0x${string}`} inputToken The address of the token to be used as input.
|
|
237
299
|
* @param {`0x${string}`} outputToken The address of the token to be received as output.
|
|
238
|
-
* @param {string}
|
|
239
|
-
* @param {
|
|
240
|
-
* @param {
|
|
241
|
-
* @param {
|
|
242
|
-
* @param {
|
|
243
|
-
*
|
|
244
|
-
* @
|
|
300
|
+
* @param {string} amountIn The amount of input tokens for the order to spend.
|
|
301
|
+
* @param {string} amountOut The amount of output tokens for the order to take.
|
|
302
|
+
* @param options {@link DefaultWriteContractOptions} options.
|
|
303
|
+
* @param {erc20PermitParam} [options.erc20PermitParam] The permit signature for token approval.
|
|
304
|
+
* @param {number} [options.slippage] The maximum slippage percentage allowed for the order.
|
|
305
|
+
* @param {boolean} [options.roundingDownTakenBid] A boolean indicating whether to round down the taken bid.
|
|
306
|
+
* @param {boolean} [options.roundingUpTakenAsk] A boolean indicating whether to round up the taken ask.
|
|
307
|
+
* if the slippage is not provided, unlimited slippage is allowed.
|
|
308
|
+
* @returns {Promise<{ transaction: Transaction, result: { spent: CurrencyFlow, taken: CurrencyFlow } }>}
|
|
309
|
+
* Promise resolving to the transaction object representing the market order with the result of the order.
|
|
245
310
|
* @example
|
|
246
|
-
* import {
|
|
311
|
+
* import { marketOrder } from '@clober/v2-sdk'
|
|
247
312
|
* import { privateKeyToAccount } from 'viem/accounts'
|
|
248
313
|
*
|
|
249
|
-
* const
|
|
250
|
-
* 421614,
|
|
251
|
-
*
|
|
252
|
-
* '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
253
|
-
* '
|
|
254
|
-
*
|
|
255
|
-
*
|
|
256
|
-
*
|
|
257
|
-
* 421614,
|
|
258
|
-
* '0xF8c1869Ecd4df136693C45EcE1b67f85B6bDaE69
|
|
259
|
-
* '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
260
|
-
* '0x0000000000000000000000000000000000000000',
|
|
261
|
-
* '100.123', // 100.123 USDC
|
|
262
|
-
* { signature }
|
|
263
|
-
* )
|
|
264
|
-
*
|
|
265
|
-
* @example
|
|
266
|
-
* import { marketOrder } from '@clober/v2-sdk'
|
|
314
|
+
* const transaction = await marketOrder({
|
|
315
|
+
* chainId: 421614,
|
|
316
|
+
* userAddress: '0xF8c1869Ecd4df136693C45EcE1b67f85B6bDaE69
|
|
317
|
+
* inputToken: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
318
|
+
* outputToken: '0x0000000000000000000000000000000000000000',
|
|
319
|
+
* amount: '100.123', // 100.123 USDC
|
|
320
|
+
* options: { erc20PermitParam }
|
|
321
|
+
* })
|
|
267
322
|
*
|
|
268
|
-
* const transaction = await limitOrder(
|
|
269
|
-
* 421614,
|
|
270
|
-
* '0xF8c1869Ecd4df136693C45EcE1b67f85B6bDaE69
|
|
271
|
-
* '0x0000000000000000000000000000000000000000',
|
|
272
|
-
* '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
273
|
-
* '0.13', // 0.13 ETH
|
|
274
|
-
* )
|
|
275
323
|
*/
|
|
276
|
-
export const marketOrder =
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
324
|
+
export const marketOrder = async ({ chainId, userAddress, inputToken, outputToken, amountIn, amountOut, options, }) => {
|
|
325
|
+
if (!amountIn && !amountOut) {
|
|
326
|
+
throw new Error('Either amountIn or amountOut must be provided');
|
|
327
|
+
}
|
|
328
|
+
else if (amountIn && amountOut) {
|
|
329
|
+
throw new Error('Only one of amountIn or amountOut can be provided');
|
|
330
|
+
}
|
|
331
|
+
const publicClient = createPublicClient({
|
|
332
|
+
chain: CHAIN_MAP[chainId],
|
|
333
|
+
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
|
|
334
|
+
});
|
|
335
|
+
const market = await fetchMarket(publicClient, chainId, [inputToken, outputToken], !!(options && options.useSubgraph));
|
|
336
|
+
const isTakingBid = isAddressEqual(market.base.address, inputToken);
|
|
337
|
+
const [inputCurrency, outputCurrency] = isTakingBid
|
|
338
|
+
? [market.base, market.quote]
|
|
339
|
+
: [market.quote, market.base];
|
|
340
|
+
if ((isTakingBid && !market.bidBook.isOpened) ||
|
|
341
|
+
(!isTakingBid && !market.askBook.isOpened)) {
|
|
280
342
|
throw new Error(`
|
|
281
343
|
Open the market before placing a market order.
|
|
282
344
|
import { openMarket } from '@clober/v2-sdk'
|
|
@@ -288,51 +350,135 @@ export const marketOrder = decorator(async ({ chainId, userAddress, inputToken,
|
|
|
288
350
|
)
|
|
289
351
|
`);
|
|
290
352
|
}
|
|
291
|
-
const rawLimitPrice = parsePrice(Number(options?.limitPrice ?? '0'), market.quote.decimals, market.base.decimals);
|
|
292
353
|
const tokensToSettle = [inputToken, outputToken].filter((address) => !isAddressEqual(address, zeroAddress));
|
|
293
|
-
const quoteAmount = parseUnits(amount, isBid ? market.quote.decimals : market.base.decimals);
|
|
294
|
-
const { bookId, takenAmount } = await getExpectedOutput({
|
|
295
|
-
chainId,
|
|
296
|
-
inputToken,
|
|
297
|
-
outputToken,
|
|
298
|
-
amountIn: amount,
|
|
299
|
-
options: {
|
|
300
|
-
...options,
|
|
301
|
-
// todo: pass limit price
|
|
302
|
-
},
|
|
303
|
-
});
|
|
304
354
|
const isETH = isAddressEqual(inputToken, zeroAddress);
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
355
|
+
if (amountIn && !amountOut) {
|
|
356
|
+
const { bookId, takenAmount, spentAmount, events } = await getExpectedOutput({
|
|
357
|
+
chainId,
|
|
358
|
+
inputToken,
|
|
359
|
+
outputToken,
|
|
360
|
+
amountIn,
|
|
361
|
+
options: {
|
|
362
|
+
...options,
|
|
363
|
+
// don't need to check limit price for market order
|
|
311
364
|
},
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
365
|
+
});
|
|
366
|
+
const baseAmount = parseUnits(amountIn, inputCurrency.decimals);
|
|
367
|
+
return {
|
|
368
|
+
transaction: await buildTransaction(publicClient, {
|
|
369
|
+
chain: CHAIN_MAP[chainId],
|
|
370
|
+
account: userAddress,
|
|
371
|
+
address: CONTRACT_ADDRESSES[chainId].Controller,
|
|
372
|
+
abi: CONTROLLER_ABI,
|
|
373
|
+
functionName: 'spend',
|
|
374
|
+
args: [
|
|
375
|
+
[
|
|
376
|
+
{
|
|
377
|
+
id: bookId,
|
|
378
|
+
limitPrice: 0n,
|
|
379
|
+
baseAmount,
|
|
380
|
+
minQuoteAmount: options?.slippage
|
|
381
|
+
? applyPercent(parseUnits(takenAmount, outputCurrency.decimals), 100 - options.slippage)
|
|
382
|
+
: 0n,
|
|
383
|
+
hookData: zeroHash,
|
|
384
|
+
},
|
|
385
|
+
],
|
|
386
|
+
tokensToSettle,
|
|
387
|
+
options?.erc20PermitParam ? [options.erc20PermitParam] : [],
|
|
388
|
+
getDeadlineTimestampInSeconds(),
|
|
389
|
+
],
|
|
390
|
+
value: isETH ? baseAmount : 0n,
|
|
391
|
+
}, options?.gasLimit),
|
|
392
|
+
result: {
|
|
393
|
+
spent: {
|
|
394
|
+
amount: spentAmount,
|
|
395
|
+
currency: inputCurrency,
|
|
396
|
+
direction: 'in',
|
|
397
|
+
events: events.map(({ price, spentAmount }) => ({
|
|
398
|
+
price,
|
|
399
|
+
amount: spentAmount,
|
|
400
|
+
})),
|
|
327
401
|
},
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
})
|
|
402
|
+
taken: {
|
|
403
|
+
amount: takenAmount,
|
|
404
|
+
currency: outputCurrency,
|
|
405
|
+
direction: 'out',
|
|
406
|
+
events: events.map(({ price, takenAmount }) => ({
|
|
407
|
+
price,
|
|
408
|
+
amount: takenAmount,
|
|
409
|
+
})),
|
|
410
|
+
},
|
|
411
|
+
},
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
else if (!amountIn && amountOut) {
|
|
415
|
+
const { bookId, spentAmount, takenAmount, events } = await getExpectedInput({
|
|
416
|
+
chainId,
|
|
417
|
+
inputToken,
|
|
418
|
+
outputToken,
|
|
419
|
+
amountOut,
|
|
420
|
+
options: {
|
|
421
|
+
...options,
|
|
422
|
+
// don't need to check limit price for market order
|
|
423
|
+
},
|
|
424
|
+
});
|
|
425
|
+
const quoteAmount = parseUnits(amountOut, outputCurrency.decimals);
|
|
426
|
+
const baseAmount = parseUnits(spentAmount, inputCurrency.decimals);
|
|
427
|
+
const maxBaseAmount = options?.erc20PermitParam?.permitAmount ??
|
|
428
|
+
(options?.slippage
|
|
429
|
+
? applyPercent(baseAmount, 100 + options.slippage)
|
|
430
|
+
: isETH
|
|
431
|
+
? baseAmount
|
|
432
|
+
: 2n ** 256n - 1n);
|
|
433
|
+
return {
|
|
434
|
+
transaction: await buildTransaction(publicClient, {
|
|
435
|
+
chain: CHAIN_MAP[chainId],
|
|
436
|
+
account: userAddress,
|
|
437
|
+
address: CONTRACT_ADDRESSES[chainId].Controller,
|
|
438
|
+
abi: CONTROLLER_ABI,
|
|
439
|
+
functionName: 'take',
|
|
440
|
+
args: [
|
|
441
|
+
[
|
|
442
|
+
{
|
|
443
|
+
id: bookId,
|
|
444
|
+
limitPrice: 0n,
|
|
445
|
+
quoteAmount,
|
|
446
|
+
maxBaseAmount,
|
|
447
|
+
hookData: zeroHash,
|
|
448
|
+
},
|
|
449
|
+
],
|
|
450
|
+
tokensToSettle,
|
|
451
|
+
options?.erc20PermitParam ? [options.erc20PermitParam] : [],
|
|
452
|
+
getDeadlineTimestampInSeconds(),
|
|
453
|
+
],
|
|
454
|
+
value: isETH ? maxBaseAmount : 0n,
|
|
455
|
+
}, options?.gasLimit),
|
|
456
|
+
result: {
|
|
457
|
+
spent: {
|
|
458
|
+
amount: spentAmount,
|
|
459
|
+
currency: inputCurrency,
|
|
460
|
+
direction: 'in',
|
|
461
|
+
events: events.map(({ price, spentAmount }) => ({
|
|
462
|
+
price,
|
|
463
|
+
amount: spentAmount,
|
|
464
|
+
})),
|
|
465
|
+
},
|
|
466
|
+
taken: {
|
|
467
|
+
amount: takenAmount,
|
|
468
|
+
currency: outputCurrency,
|
|
469
|
+
direction: 'out',
|
|
470
|
+
events: events.map(({ price, takenAmount }) => ({
|
|
471
|
+
price,
|
|
472
|
+
amount: takenAmount,
|
|
473
|
+
})),
|
|
474
|
+
},
|
|
475
|
+
},
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
throw new Error('Either amountIn or amountOut must be provided');
|
|
480
|
+
}
|
|
481
|
+
};
|
|
336
482
|
/**
|
|
337
483
|
* Claims specified open order for settlement.
|
|
338
484
|
* [IMPORTANT] Set ApprovalForAll before calling this function.
|
|
@@ -340,25 +486,24 @@ export const marketOrder = decorator(async ({ chainId, userAddress, inputToken,
|
|
|
340
486
|
* @param {CHAIN_IDS} chainId The chain ID.
|
|
341
487
|
* @param {`0x${string}`} userAddress The Ethereum address of the user.
|
|
342
488
|
* @param {string} id An ID representing the open order to be claimed.
|
|
343
|
-
* @param {
|
|
344
|
-
* @param {string} [options.rpcUrl] The RPC URL to use for executing the transaction.
|
|
489
|
+
* @param options {@link DefaultWriteContractOptions} options.
|
|
345
490
|
* @returns {Promise<{ transaction: Transaction, result: CurrencyFlow }>}
|
|
346
491
|
* Promise resolving to the transaction object representing the claim action with the result of the order.
|
|
347
492
|
* @throws {Error} Throws an error if no open orders are found for the specified user.
|
|
348
493
|
* @example
|
|
349
494
|
* import { getOpenOrders, claimOrders } from '@clober/v2-sdk'
|
|
350
495
|
*
|
|
351
|
-
* const openOrders = await getOpenOrders(
|
|
352
|
-
* 421614,
|
|
353
|
-
*
|
|
354
|
-
* )
|
|
355
|
-
* const transaction = await claimOrders(
|
|
356
|
-
* 421614,
|
|
357
|
-
* '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
358
|
-
* openOrders.map((order) => order.id)
|
|
359
|
-
* )
|
|
496
|
+
* const openOrders = await getOpenOrders({
|
|
497
|
+
* chainId: 421614,
|
|
498
|
+
* userAddress: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0'
|
|
499
|
+
* })
|
|
500
|
+
* const transaction = await claimOrders({
|
|
501
|
+
* chainId: 421614,
|
|
502
|
+
* userAddress: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
503
|
+
* id: openOrders.map((order) => order.id)
|
|
504
|
+
* })
|
|
360
505
|
*/
|
|
361
|
-
export const claimOrder =
|
|
506
|
+
export const claimOrder = async ({ chainId, userAddress, id, options, }) => {
|
|
362
507
|
const { transaction, result } = await claimOrders({
|
|
363
508
|
chainId,
|
|
364
509
|
userAddress,
|
|
@@ -369,7 +514,7 @@ export const claimOrder = decorator(async ({ chainId, userAddress, id, options,
|
|
|
369
514
|
transaction,
|
|
370
515
|
result: result[0],
|
|
371
516
|
};
|
|
372
|
-
}
|
|
517
|
+
};
|
|
373
518
|
/**
|
|
374
519
|
* Claims specified open orders for settlement.
|
|
375
520
|
* [IMPORTANT] Set ApprovalForAll before calling this function.
|
|
@@ -377,73 +522,73 @@ export const claimOrder = decorator(async ({ chainId, userAddress, id, options,
|
|
|
377
522
|
* @param {CHAIN_IDS} chainId The chain ID.
|
|
378
523
|
* @param {`0x${string}`} userAddress The Ethereum address of the user.
|
|
379
524
|
* @param {string[]} ids An array of IDs representing the open orders to be claimed.
|
|
380
|
-
* @param {
|
|
381
|
-
* @param {string} [options.rpcUrl] The RPC URL to use for executing the transaction.
|
|
525
|
+
* @param options {@link DefaultWriteContractOptions} options.
|
|
382
526
|
* @returns {Promise<{ transaction: Transaction, result: CurrencyFlow[] }>}
|
|
383
527
|
* Promise resolving to the transaction object representing the claim action with the result of the orders.
|
|
384
528
|
* @throws {Error} Throws an error if no open orders are found for the specified user.
|
|
385
529
|
* @example
|
|
386
530
|
* import { getOpenOrders, claimOrders } from '@clober/v2-sdk'
|
|
387
531
|
*
|
|
388
|
-
* const openOrders = await getOpenOrders(
|
|
389
|
-
* 421614,
|
|
390
|
-
*
|
|
391
|
-
* )
|
|
532
|
+
* const openOrders = await getOpenOrders({
|
|
533
|
+
* chainId: 421614,
|
|
534
|
+
* userAddress: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0'
|
|
535
|
+
* })
|
|
392
536
|
* const transaction = await claimOrders(
|
|
393
|
-
* 421614,
|
|
394
|
-
* '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
395
|
-
* openOrders.map((order) => order.id)
|
|
537
|
+
* chainId: 421614,
|
|
538
|
+
* userAddress: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
539
|
+
* ids: openOrders.map((order) => order.id)
|
|
396
540
|
* )
|
|
397
541
|
*/
|
|
398
|
-
export const claimOrders =
|
|
399
|
-
const
|
|
542
|
+
export const claimOrders = async ({ chainId, userAddress, ids, options, }) => {
|
|
543
|
+
const publicClient = createPublicClient({
|
|
544
|
+
chain: CHAIN_MAP[chainId],
|
|
545
|
+
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
|
|
546
|
+
});
|
|
547
|
+
const isApprovedForAll = await fetchIsApprovedForAll(publicClient, chainId, userAddress);
|
|
400
548
|
if (!isApprovedForAll) {
|
|
401
549
|
throw new Error(`
|
|
402
550
|
Set ApprovalForAll before calling this function.
|
|
403
551
|
import { setApprovalOfOpenOrdersForAll } from '@clober/v2-sdk'
|
|
404
552
|
|
|
405
|
-
const hash = await setApprovalOfOpenOrdersForAll(
|
|
406
|
-
${chainId},
|
|
407
|
-
|
|
408
|
-
)
|
|
553
|
+
const hash = await setApprovalOfOpenOrdersForAll({
|
|
554
|
+
chainId: ${chainId},
|
|
555
|
+
walletClient, // use viem
|
|
556
|
+
})
|
|
409
557
|
`);
|
|
410
558
|
}
|
|
411
|
-
const
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
}
|
|
415
|
-
const tokensToSettle = openOrders
|
|
416
|
-
.map((order) => [
|
|
417
|
-
order.outputCurrency.address,
|
|
418
|
-
order.inputCurrency.address,
|
|
419
|
-
])
|
|
559
|
+
const orders = (await fetchOnChainOrders(publicClient, chainId, ids.map((id) => BigInt(id)), !!(options && options.useSubgraph))).filter((order) => isAddressEqual(order.user, userAddress) && order.claimable.value !== '0');
|
|
560
|
+
const tokensToSettle = orders
|
|
561
|
+
.map((order) => [order.inputCurrency.address, order.outputCurrency.address])
|
|
420
562
|
.flat()
|
|
421
563
|
.filter((address, index, self) => self.findIndex((c) => isAddressEqual(c, address)) === index)
|
|
422
564
|
.filter((address) => !isAddressEqual(address, zeroAddress));
|
|
423
565
|
return {
|
|
424
|
-
transaction: await buildTransaction(
|
|
566
|
+
transaction: await buildTransaction(publicClient, {
|
|
425
567
|
chain: CHAIN_MAP[chainId],
|
|
426
568
|
account: userAddress,
|
|
427
569
|
address: CONTRACT_ADDRESSES[chainId].Controller,
|
|
428
570
|
abi: CONTROLLER_ABI,
|
|
429
571
|
functionName: 'claim',
|
|
430
572
|
args: [
|
|
431
|
-
|
|
432
|
-
id
|
|
573
|
+
orders.map(({ id }) => ({
|
|
574
|
+
id,
|
|
433
575
|
hookData: zeroHash,
|
|
434
576
|
})),
|
|
435
577
|
tokensToSettle,
|
|
436
578
|
[],
|
|
437
579
|
getDeadlineTimestampInSeconds(),
|
|
438
580
|
],
|
|
439
|
-
}),
|
|
440
|
-
result:
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
581
|
+
}, options?.gasLimit),
|
|
582
|
+
result: orders.reduce((acc, { claimable: { currency, value } }) => {
|
|
583
|
+
const index = acc.findIndex((c) => isAddressEqual(c.currency.address, currency.address));
|
|
584
|
+
if (index === -1) {
|
|
585
|
+
return [...acc, { currency, amount: value, direction: 'out' }];
|
|
586
|
+
}
|
|
587
|
+
acc[index].amount = (Number(acc[index].amount) + Number(value)).toString();
|
|
588
|
+
return acc;
|
|
589
|
+
}, []),
|
|
445
590
|
};
|
|
446
|
-
}
|
|
591
|
+
};
|
|
447
592
|
/**
|
|
448
593
|
* Cancels specified open order if the order is not fully filled.
|
|
449
594
|
* [IMPORTANT] Set ApprovalForAll before calling this function.
|
|
@@ -451,25 +596,24 @@ export const claimOrders = decorator(async ({ chainId, userAddress, ids, options
|
|
|
451
596
|
* @param {CHAIN_IDS} chainId The chain ID.
|
|
452
597
|
* @param {`0x${string}`} userAddress The Ethereum address of the user.
|
|
453
598
|
* @param {string} id An ID representing the open order to be canceled
|
|
454
|
-
* @param {
|
|
455
|
-
* @param {string} [options.rpcUrl] The RPC URL to use for executing the transaction.
|
|
599
|
+
* @param options {@link DefaultWriteContractOptions} options.
|
|
456
600
|
* @returns {Promise<{ transaction: Transaction, result: CurrencyFlow }>}
|
|
457
601
|
* Promise resolving to the transaction object representing the cancel action with the result of the order.
|
|
458
602
|
* @throws {Error} Throws an error if no open orders are found for the specified user.
|
|
459
603
|
* @example
|
|
460
604
|
* import { getOpenOrders, cancelOrders } from '@clober/v2-sdk'
|
|
461
605
|
*
|
|
462
|
-
* const openOrders = await getOpenOrders(
|
|
463
|
-
* 421614,
|
|
464
|
-
*
|
|
465
|
-
* )
|
|
466
|
-
* const transaction = await cancelOrders(
|
|
467
|
-
* 421614,
|
|
468
|
-
* '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
469
|
-
* openOrders.map((order) => order.id)
|
|
470
|
-
* )
|
|
606
|
+
* const openOrders = await getOpenOrders({
|
|
607
|
+
* chainId: 421614,
|
|
608
|
+
* userAddress:'0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0'
|
|
609
|
+
* })
|
|
610
|
+
* const transaction = await cancelOrders({
|
|
611
|
+
* chainId: 421614,
|
|
612
|
+
* userAddress: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
613
|
+
* id: openOrders.map((order) => order.id)
|
|
614
|
+
* })
|
|
471
615
|
*/
|
|
472
|
-
export const cancelOrder =
|
|
616
|
+
export const cancelOrder = async ({ chainId, userAddress, id, options, }) => {
|
|
473
617
|
const { transaction, result } = await cancelOrders({
|
|
474
618
|
chainId,
|
|
475
619
|
userAddress,
|
|
@@ -480,7 +624,7 @@ export const cancelOrder = decorator(async ({ chainId, userAddress, id, options,
|
|
|
480
624
|
transaction,
|
|
481
625
|
result: result[0],
|
|
482
626
|
};
|
|
483
|
-
}
|
|
627
|
+
};
|
|
484
628
|
/**
|
|
485
629
|
* Cancels specified open orders if orders are not fully filled.
|
|
486
630
|
* [IMPORTANT] Set ApprovalForAll before calling this function.
|
|
@@ -488,59 +632,56 @@ export const cancelOrder = decorator(async ({ chainId, userAddress, id, options,
|
|
|
488
632
|
* @param {CHAIN_IDS} chainId The chain ID.
|
|
489
633
|
* @param {`0x${string}`} userAddress The Ethereum address of the user.
|
|
490
634
|
* @param {string[]} ids An array of IDs representing the open orders to be canceled.
|
|
491
|
-
* @param {
|
|
492
|
-
* @param {string} [options.rpcUrl] The RPC URL to use for executing the transaction.
|
|
635
|
+
* @param options {@link DefaultWriteContractOptions} options.
|
|
493
636
|
* @returns {Promise<{ transaction: Transaction, result: CurrencyFlow[] }>
|
|
494
637
|
* Promise resolving to the transaction object representing the cancel action with the result of the orders.
|
|
495
638
|
* @throws {Error} Throws an error if no open orders are found for the specified user.
|
|
496
639
|
* @example
|
|
497
640
|
* import { getOpenOrders, cancelOrders } from '@clober/v2-sdk'
|
|
498
641
|
*
|
|
499
|
-
* const openOrders = await getOpenOrders(
|
|
500
|
-
* 421614,
|
|
501
|
-
*
|
|
502
|
-
* )
|
|
503
|
-
* const transaction = await cancelOrders(
|
|
504
|
-
* 421614,
|
|
505
|
-
* '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
506
|
-
* openOrders.map((order) => order.id)
|
|
507
|
-
* )
|
|
642
|
+
* const openOrders = await getOpenOrders({
|
|
643
|
+
* chainId: 421614,
|
|
644
|
+
* userAddress: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0'
|
|
645
|
+
* })
|
|
646
|
+
* const transaction = await cancelOrders({
|
|
647
|
+
* chainId: 421614,
|
|
648
|
+
* userAddress: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
649
|
+
* ids: openOrders.map((order) => order.id)
|
|
650
|
+
* })
|
|
508
651
|
*/
|
|
509
|
-
export const cancelOrders =
|
|
510
|
-
const
|
|
652
|
+
export const cancelOrders = async ({ chainId, userAddress, ids, options, }) => {
|
|
653
|
+
const publicClient = createPublicClient({
|
|
654
|
+
chain: CHAIN_MAP[chainId],
|
|
655
|
+
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
|
|
656
|
+
});
|
|
657
|
+
const isApprovedForAll = await fetchIsApprovedForAll(publicClient, chainId, userAddress);
|
|
511
658
|
if (!isApprovedForAll) {
|
|
512
659
|
throw new Error(`
|
|
513
660
|
Set ApprovalForAll before calling this function.
|
|
514
661
|
import { setApprovalOfOpenOrdersForAll } from '@clober/v2-sdk'
|
|
515
662
|
|
|
516
|
-
const hash = await setApprovalOfOpenOrdersForAll(
|
|
517
|
-
${chainId},
|
|
518
|
-
|
|
519
|
-
)
|
|
663
|
+
const hash = await setApprovalOfOpenOrdersForAll({
|
|
664
|
+
chainId: ${chainId},
|
|
665
|
+
walletClient, // use viem
|
|
666
|
+
})
|
|
520
667
|
`);
|
|
521
668
|
}
|
|
522
|
-
const
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
}
|
|
526
|
-
const tokensToSettle = openOrders
|
|
527
|
-
.map((order) => [
|
|
528
|
-
order.outputCurrency.address,
|
|
529
|
-
order.inputCurrency.address,
|
|
530
|
-
])
|
|
669
|
+
const orders = (await fetchOnChainOrders(publicClient, chainId, ids.map((id) => BigInt(id)), !!(options && options.useSubgraph))).filter((order) => isAddressEqual(order.user, userAddress) && order.cancelable.value !== '0');
|
|
670
|
+
const tokensToSettle = orders
|
|
671
|
+
.map((order) => [order.inputCurrency.address, order.outputCurrency.address])
|
|
531
672
|
.flat()
|
|
532
673
|
.filter((address, index, self) => self.findIndex((c) => isAddressEqual(c, address)) === index)
|
|
533
674
|
.filter((address) => !isAddressEqual(address, zeroAddress));
|
|
534
675
|
return {
|
|
535
|
-
transaction: await buildTransaction(
|
|
676
|
+
transaction: await buildTransaction(publicClient, {
|
|
536
677
|
chain: CHAIN_MAP[chainId],
|
|
537
678
|
account: userAddress,
|
|
538
679
|
address: CONTRACT_ADDRESSES[chainId].Controller,
|
|
539
680
|
abi: CONTROLLER_ABI,
|
|
540
681
|
functionName: 'cancel',
|
|
541
682
|
args: [
|
|
542
|
-
|
|
543
|
-
id
|
|
683
|
+
orders.map(({ id }) => ({
|
|
684
|
+
id,
|
|
544
685
|
leftQuoteAmount: 0n,
|
|
545
686
|
hookData: zeroHash,
|
|
546
687
|
})),
|
|
@@ -548,12 +689,543 @@ export const cancelOrders = decorator(async ({ chainId, userAddress, ids, option
|
|
|
548
689
|
[],
|
|
549
690
|
getDeadlineTimestampInSeconds(),
|
|
550
691
|
],
|
|
551
|
-
}),
|
|
552
|
-
result:
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
692
|
+
}, options?.gasLimit),
|
|
693
|
+
result: orders.reduce((acc, { cancelable: { currency, value } }) => {
|
|
694
|
+
const index = acc.findIndex((c) => isAddressEqual(c.currency.address, currency.address));
|
|
695
|
+
if (index === -1) {
|
|
696
|
+
return [...acc, { currency, amount: value, direction: 'out' }];
|
|
697
|
+
}
|
|
698
|
+
acc[index].amount = (Number(acc[index].amount) + Number(value)).toString();
|
|
699
|
+
return acc;
|
|
700
|
+
}, []),
|
|
701
|
+
};
|
|
702
|
+
};
|
|
703
|
+
/**
|
|
704
|
+
* Build a transaction to open a pool,
|
|
705
|
+
*
|
|
706
|
+
* @param chainId The chain ID of the blockchain.
|
|
707
|
+
* @param userAddress The address of the user.
|
|
708
|
+
* @param inputToken The address of the input token.
|
|
709
|
+
* @param outputToken The address of the output token.
|
|
710
|
+
* @param options {@link DefaultWriteContractOptions} options.
|
|
711
|
+
* @returns A Promise resolving to a transaction object. If the market is already open, returns undefined.
|
|
712
|
+
* @example
|
|
713
|
+
* import { openPool } from '@clober/v2-sdk'
|
|
714
|
+
*
|
|
715
|
+
* const transaction = await openPool({
|
|
716
|
+
* chainId: 421614,
|
|
717
|
+
* userAddress: '0xF8c1869Ecd4df136693C45EcE1b67f85B6bDaE69',
|
|
718
|
+
* inputToken: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
719
|
+
* outputToken: '0x0000000000000000000000000000000000000000',
|
|
720
|
+
* salt: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
721
|
+
* })
|
|
722
|
+
*/
|
|
723
|
+
export const openPool = async ({ chainId, userAddress, tokenA, tokenB, salt, options, }) => {
|
|
724
|
+
const publicClient = createPublicClient({
|
|
725
|
+
chain: CHAIN_MAP[chainId],
|
|
726
|
+
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
|
|
727
|
+
});
|
|
728
|
+
const pool = await fetchPool(publicClient, chainId, [tokenA, tokenB], salt, !!(options && options.useSubgraph));
|
|
729
|
+
if (!pool.isOpened) {
|
|
730
|
+
return buildTransaction(publicClient, {
|
|
731
|
+
chain: CHAIN_MAP[chainId],
|
|
732
|
+
address: CONTRACT_ADDRESSES[chainId].Rebalancer,
|
|
733
|
+
account: userAddress,
|
|
734
|
+
abi: REBALANCER_ABI,
|
|
735
|
+
functionName: 'open',
|
|
736
|
+
args: [
|
|
737
|
+
{
|
|
738
|
+
base: pool.market.bidBook.base.address,
|
|
739
|
+
unitSize: pool.market.bidBook.unitSize,
|
|
740
|
+
quote: pool.market.bidBook.quote.address,
|
|
741
|
+
makerPolicy: MAKER_DEFAULT_POLICY[chainId].value,
|
|
742
|
+
hooks: zeroAddress,
|
|
743
|
+
takerPolicy: TAKER_DEFAULT_POLICY[chainId].value,
|
|
744
|
+
},
|
|
745
|
+
{
|
|
746
|
+
base: pool.market.askBook.base.address,
|
|
747
|
+
unitSize: pool.market.askBook.unitSize,
|
|
748
|
+
quote: pool.market.askBook.quote.address,
|
|
749
|
+
makerPolicy: MAKER_DEFAULT_POLICY[chainId].value,
|
|
750
|
+
hooks: zeroAddress,
|
|
751
|
+
takerPolicy: TAKER_DEFAULT_POLICY[chainId].value,
|
|
752
|
+
},
|
|
753
|
+
toBytes32(salt),
|
|
754
|
+
CONTRACT_ADDRESSES[chainId].Strategy,
|
|
755
|
+
],
|
|
756
|
+
}, options?.gasLimit);
|
|
757
|
+
}
|
|
758
|
+
return undefined;
|
|
759
|
+
};
|
|
760
|
+
export const addLiquidity = async ({ chainId, userAddress, token0, token1, salt, amount0, amount1, options, }) => {
|
|
761
|
+
if (isAddressEqual(token0, zeroAddress) ||
|
|
762
|
+
isAddressEqual(token1, zeroAddress)) {
|
|
763
|
+
throw new Error('ETH is not supported for adding liquidity');
|
|
764
|
+
}
|
|
765
|
+
const publicClient = createPublicClient({
|
|
766
|
+
chain: CHAIN_MAP[chainId],
|
|
767
|
+
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
|
|
768
|
+
});
|
|
769
|
+
const pool = await fetchPool(publicClient, chainId, [token0, token1], salt, !!(options && options.useSubgraph));
|
|
770
|
+
if (!pool.isOpened) {
|
|
771
|
+
throw new Error(`
|
|
772
|
+
Open the pool before adding liquidity.
|
|
773
|
+
import { openPool } from '@clober/v2-sdk'
|
|
774
|
+
|
|
775
|
+
const transaction = await openPool({
|
|
776
|
+
chainId: ${chainId},
|
|
777
|
+
tokenA: '${token0}',
|
|
778
|
+
tokenB: '${token1}',
|
|
779
|
+
salt: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
780
|
+
})
|
|
781
|
+
`);
|
|
782
|
+
}
|
|
783
|
+
const [amountAOrigin, amountBOrigin] = isAddressEqual(pool.currencyA.address, getAddress(token0))
|
|
784
|
+
? [
|
|
785
|
+
parseUnits(amount0 ?? '0', pool.currencyA.decimals),
|
|
786
|
+
parseUnits(amount1 ?? '0', pool.currencyB.decimals),
|
|
787
|
+
]
|
|
788
|
+
: [
|
|
789
|
+
parseUnits(amount1 ?? '0', pool.currencyA.decimals),
|
|
790
|
+
parseUnits(amount0 ?? '0', pool.currencyB.decimals),
|
|
791
|
+
];
|
|
792
|
+
let [amountA, amountB] = [amountAOrigin, amountBOrigin];
|
|
793
|
+
const tokenAPermitParams = isAddressEqual(pool.currencyA.address, getAddress(token0))
|
|
794
|
+
? options?.token0PermitParams ?? emptyERC20PermitParams
|
|
795
|
+
: options?.token1PermitParams ?? emptyERC20PermitParams;
|
|
796
|
+
const tokenBPermitParams = isAddressEqual(pool.currencyA.address, getAddress(token0))
|
|
797
|
+
? options?.token1PermitParams ?? emptyERC20PermitParams
|
|
798
|
+
: options?.token0PermitParams ?? emptyERC20PermitParams;
|
|
799
|
+
let disableSwap = !!(options && options.disableSwap);
|
|
800
|
+
if (pool.totalSupply === 0n ||
|
|
801
|
+
(pool.liquidityA === 0n && pool.liquidityB === 0n)) {
|
|
802
|
+
disableSwap = true;
|
|
803
|
+
}
|
|
804
|
+
const slippageLimitPercent = options?.slippage ?? 2;
|
|
805
|
+
const swapParams = {
|
|
806
|
+
inCurrency: zeroAddress,
|
|
807
|
+
amount: 0n,
|
|
808
|
+
data: '0x',
|
|
809
|
+
};
|
|
810
|
+
if (!disableSwap) {
|
|
811
|
+
const currencyBPerCurrencyA = options?.testnetPrice
|
|
812
|
+
? isAddressEqual(getQuoteToken({
|
|
813
|
+
chainId,
|
|
814
|
+
token0,
|
|
815
|
+
token1,
|
|
816
|
+
}), pool.currencyA.address)
|
|
817
|
+
? 1 / Number(options.testnetPrice)
|
|
818
|
+
: Number(options.testnetPrice)
|
|
819
|
+
: undefined;
|
|
820
|
+
const swapAmountA = parseUnits('1', pool.currencyA.decimals);
|
|
821
|
+
const { amountOut: swapAmountB } = await fetchQuote({
|
|
822
|
+
chainId,
|
|
823
|
+
amountIn: swapAmountA,
|
|
824
|
+
tokenIn: pool.currencyA,
|
|
825
|
+
tokenOut: pool.currencyB,
|
|
826
|
+
slippageLimitPercent: 20,
|
|
827
|
+
userAddress: CONTRACT_ADDRESSES[chainId].Minter,
|
|
828
|
+
testnetPrice: currencyBPerCurrencyA,
|
|
829
|
+
});
|
|
830
|
+
const { deltaA, deltaB } = getIdealDelta(amountA, amountB, pool.liquidityA, pool.liquidityB, swapAmountA, swapAmountB);
|
|
831
|
+
if (deltaA < 0n) {
|
|
832
|
+
swapParams.inCurrency = pool.currencyA.address;
|
|
833
|
+
swapParams.amount = -deltaA;
|
|
834
|
+
const { amountOut: actualDeltaB, data: calldata } = await fetchCallData({
|
|
835
|
+
chainId,
|
|
836
|
+
amountIn: swapParams.amount,
|
|
837
|
+
tokenIn: pool.currencyA,
|
|
838
|
+
tokenOut: pool.currencyB,
|
|
839
|
+
slippageLimitPercent,
|
|
840
|
+
userAddress: CONTRACT_ADDRESSES[chainId].Minter,
|
|
841
|
+
testnetPrice: currencyBPerCurrencyA,
|
|
842
|
+
});
|
|
843
|
+
swapParams.data = calldata;
|
|
844
|
+
amountA += deltaA;
|
|
845
|
+
amountB += actualDeltaB;
|
|
846
|
+
}
|
|
847
|
+
else if (deltaB < 0n) {
|
|
848
|
+
swapParams.inCurrency = pool.currencyB.address;
|
|
849
|
+
swapParams.amount = -deltaB;
|
|
850
|
+
const { amountOut: actualDeltaA, data: calldata } = await fetchCallData({
|
|
851
|
+
chainId,
|
|
852
|
+
amountIn: swapParams.amount,
|
|
853
|
+
tokenIn: pool.currencyB,
|
|
854
|
+
tokenOut: pool.currencyA,
|
|
855
|
+
slippageLimitPercent,
|
|
856
|
+
userAddress: CONTRACT_ADDRESSES[chainId].Minter,
|
|
857
|
+
testnetPrice: currencyBPerCurrencyA
|
|
858
|
+
? 1 / currencyBPerCurrencyA
|
|
859
|
+
: undefined,
|
|
860
|
+
});
|
|
861
|
+
swapParams.data = calldata;
|
|
862
|
+
amountA += actualDeltaA;
|
|
863
|
+
amountB += deltaB;
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
const { mintAmount, inAmountA, inAmountB } = getExpectedMintResult(pool.totalSupply, pool.liquidityA, pool.liquidityB, amountA, amountB, pool.currencyA, pool.currencyB);
|
|
867
|
+
if (mintAmount === 0n) {
|
|
868
|
+
return {
|
|
869
|
+
transaction: undefined,
|
|
870
|
+
result: {
|
|
871
|
+
currencyA: {
|
|
872
|
+
currency: pool.currencyA,
|
|
873
|
+
amount: '0',
|
|
874
|
+
direction: 'in',
|
|
875
|
+
},
|
|
876
|
+
currencyB: {
|
|
877
|
+
currency: pool.currencyB,
|
|
878
|
+
amount: '0',
|
|
879
|
+
direction: 'in',
|
|
880
|
+
},
|
|
881
|
+
lpCurrency: {
|
|
882
|
+
currency: pool.currencyLp,
|
|
883
|
+
amount: '0',
|
|
884
|
+
direction: 'out',
|
|
885
|
+
},
|
|
886
|
+
},
|
|
887
|
+
};
|
|
888
|
+
}
|
|
889
|
+
const minMintAmount = applyPercent(mintAmount, 100 - slippageLimitPercent);
|
|
890
|
+
const transaction = await buildTransaction(publicClient, {
|
|
891
|
+
chain: CHAIN_MAP[chainId],
|
|
892
|
+
account: userAddress,
|
|
893
|
+
address: CONTRACT_ADDRESSES[chainId].Minter,
|
|
894
|
+
abi: MINTER_ABI,
|
|
895
|
+
functionName: 'mint',
|
|
896
|
+
args: [
|
|
897
|
+
pool.key,
|
|
898
|
+
amountAOrigin,
|
|
899
|
+
amountBOrigin,
|
|
900
|
+
minMintAmount,
|
|
901
|
+
{
|
|
902
|
+
permitAmount: tokenAPermitParams.permitAmount,
|
|
903
|
+
signature: tokenAPermitParams.signature,
|
|
904
|
+
},
|
|
905
|
+
{
|
|
906
|
+
permitAmount: tokenBPermitParams.permitAmount,
|
|
907
|
+
signature: tokenBPermitParams.signature,
|
|
908
|
+
},
|
|
909
|
+
swapParams,
|
|
910
|
+
],
|
|
911
|
+
}, options?.gasLimit);
|
|
912
|
+
const currencyARefund = amountA - inAmountA;
|
|
913
|
+
const currencyBRefund = amountB - inAmountB;
|
|
914
|
+
const currencyAResultAmount = amountAOrigin - currencyARefund;
|
|
915
|
+
const currencyBResultAmount = amountBOrigin - currencyBRefund;
|
|
916
|
+
return {
|
|
917
|
+
transaction,
|
|
918
|
+
result: {
|
|
919
|
+
currencyA: {
|
|
920
|
+
currency: pool.currencyA,
|
|
921
|
+
amount: formatUnits(abs(currencyAResultAmount), pool.currencyA.decimals),
|
|
922
|
+
direction: currencyAResultAmount >= 0 ? 'in' : 'out',
|
|
923
|
+
},
|
|
924
|
+
currencyB: {
|
|
925
|
+
currency: pool.currencyB,
|
|
926
|
+
amount: formatUnits(abs(currencyBResultAmount), pool.currencyB.decimals),
|
|
927
|
+
direction: currencyBResultAmount >= 0 ? 'in' : 'out',
|
|
928
|
+
},
|
|
929
|
+
lpCurrency: {
|
|
930
|
+
currency: pool.currencyLp,
|
|
931
|
+
amount: formatUnits(mintAmount, pool.currencyLp.decimals),
|
|
932
|
+
direction: 'out',
|
|
933
|
+
},
|
|
934
|
+
},
|
|
557
935
|
};
|
|
558
|
-
}
|
|
936
|
+
};
|
|
937
|
+
// @dev: Withdraw amount calculation logic is based on the contract code.
|
|
938
|
+
export const removeLiquidity = async ({ chainId, userAddress, token0, token1, salt, amount, options, }) => {
|
|
939
|
+
const publicClient = createPublicClient({
|
|
940
|
+
chain: CHAIN_MAP[chainId],
|
|
941
|
+
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
|
|
942
|
+
});
|
|
943
|
+
const pool = await fetchPool(publicClient, chainId, [token0, token1], salt, !!(options && options.useSubgraph));
|
|
944
|
+
if (!pool.isOpened) {
|
|
945
|
+
throw new Error(`
|
|
946
|
+
Open the pool before removing liquidity.
|
|
947
|
+
import { openPool } from '@clober/v2-sdk'
|
|
948
|
+
|
|
949
|
+
const transaction = await openPool({
|
|
950
|
+
chainId: ${chainId},
|
|
951
|
+
tokenA: '${token0}',
|
|
952
|
+
tokenB: '${token1}',
|
|
953
|
+
salt: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
954
|
+
})
|
|
955
|
+
`);
|
|
956
|
+
}
|
|
957
|
+
const burnAmount = parseUnits(amount, pool.currencyLp.decimals);
|
|
958
|
+
const slippageLimitPercent = options?.slippage ?? 2;
|
|
959
|
+
const withdrawAmountA = (burnAmount * pool.liquidityA) / pool.totalSupply;
|
|
960
|
+
const withdrawAmountB = (burnAmount * pool.liquidityB) / pool.totalSupply;
|
|
961
|
+
const minWithdrawAmountA = applyPercent(withdrawAmountA, 100 - slippageLimitPercent);
|
|
962
|
+
const minWithdrawAmountB = applyPercent(withdrawAmountB, 100 - slippageLimitPercent);
|
|
963
|
+
if (burnAmount === 0n) {
|
|
964
|
+
return {
|
|
965
|
+
transaction: undefined,
|
|
966
|
+
result: {
|
|
967
|
+
currencyA: {
|
|
968
|
+
currency: pool.currencyA,
|
|
969
|
+
amount: '0',
|
|
970
|
+
direction: 'out',
|
|
971
|
+
},
|
|
972
|
+
currencyB: {
|
|
973
|
+
currency: pool.currencyB,
|
|
974
|
+
amount: '0',
|
|
975
|
+
direction: 'out',
|
|
976
|
+
},
|
|
977
|
+
lpCurrency: {
|
|
978
|
+
currency: pool.currencyLp,
|
|
979
|
+
amount: '0',
|
|
980
|
+
direction: 'in',
|
|
981
|
+
},
|
|
982
|
+
},
|
|
983
|
+
};
|
|
984
|
+
}
|
|
985
|
+
const transaction = await buildTransaction(publicClient, {
|
|
986
|
+
chain: CHAIN_MAP[chainId],
|
|
987
|
+
account: userAddress,
|
|
988
|
+
address: CONTRACT_ADDRESSES[chainId].Rebalancer,
|
|
989
|
+
abi: REBALANCER_ABI,
|
|
990
|
+
functionName: 'burn',
|
|
991
|
+
args: [pool.key, burnAmount, minWithdrawAmountA, minWithdrawAmountB],
|
|
992
|
+
}, options?.gasLimit);
|
|
993
|
+
return {
|
|
994
|
+
transaction,
|
|
995
|
+
result: {
|
|
996
|
+
currencyA: {
|
|
997
|
+
currency: pool.currencyA,
|
|
998
|
+
amount: formatUnits(withdrawAmountA, pool.currencyA.decimals),
|
|
999
|
+
direction: 'out',
|
|
1000
|
+
},
|
|
1001
|
+
currencyB: {
|
|
1002
|
+
currency: pool.currencyB,
|
|
1003
|
+
amount: formatUnits(withdrawAmountB, pool.currencyB.decimals),
|
|
1004
|
+
direction: 'out',
|
|
1005
|
+
},
|
|
1006
|
+
lpCurrency: {
|
|
1007
|
+
currency: pool.currencyLp,
|
|
1008
|
+
amount: amount,
|
|
1009
|
+
direction: 'in',
|
|
1010
|
+
},
|
|
1011
|
+
},
|
|
1012
|
+
};
|
|
1013
|
+
};
|
|
1014
|
+
export const refillOrder = async ({ chainId, userAddress, token0, token1, salt, options, }) => {
|
|
1015
|
+
const publicClient = createPublicClient({
|
|
1016
|
+
chain: CHAIN_MAP[chainId],
|
|
1017
|
+
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
|
|
1018
|
+
});
|
|
1019
|
+
const pool = options?.pool
|
|
1020
|
+
? options.pool
|
|
1021
|
+
: (await fetchPool(publicClient, chainId, [token0, token1], salt, !!(options && options.useSubgraph))).toJson();
|
|
1022
|
+
if (!pool.isOpened) {
|
|
1023
|
+
throw new Error(`
|
|
1024
|
+
Open the pool before rebalancing pool.
|
|
1025
|
+
import { openPool } from '@clober/v2-sdk'
|
|
1026
|
+
|
|
1027
|
+
const transaction = await openPool({
|
|
1028
|
+
chainId: ${chainId},
|
|
1029
|
+
tokenA: '${token0}',
|
|
1030
|
+
tokenB: '${token1}',
|
|
1031
|
+
salt: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
1032
|
+
})
|
|
1033
|
+
`);
|
|
1034
|
+
}
|
|
1035
|
+
return buildTransaction(publicClient, {
|
|
1036
|
+
chain: CHAIN_MAP[chainId],
|
|
1037
|
+
account: userAddress,
|
|
1038
|
+
address: CONTRACT_ADDRESSES[chainId].Rebalancer,
|
|
1039
|
+
abi: REBALANCER_ABI,
|
|
1040
|
+
functionName: 'rebalance',
|
|
1041
|
+
args: [pool.key],
|
|
1042
|
+
}, options?.gasLimit, options?.gasPriceLimit);
|
|
1043
|
+
};
|
|
1044
|
+
export const adjustOrderPrice = async ({ chainId, userAddress, token0, token1, salt, oraclePrice, bidPrice, askPrice, alpha, options, }) => {
|
|
1045
|
+
if (Number(alpha) <= 0 || Number(alpha) > 1) {
|
|
1046
|
+
throw new Error('Alpha value must be in the range (0, 1]');
|
|
1047
|
+
}
|
|
1048
|
+
if (Number(bidPrice) <= 0 || Number(askPrice) <= 0) {
|
|
1049
|
+
throw new Error('Price must be greater than 0');
|
|
1050
|
+
}
|
|
1051
|
+
if (Number(bidPrice) >= Number(askPrice)) {
|
|
1052
|
+
throw new Error('Bid price must be less than ask price');
|
|
1053
|
+
}
|
|
1054
|
+
const publicClient = createPublicClient({
|
|
1055
|
+
chain: CHAIN_MAP[chainId],
|
|
1056
|
+
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
|
|
1057
|
+
});
|
|
1058
|
+
const pool = options?.pool
|
|
1059
|
+
? options.pool
|
|
1060
|
+
: (await fetchPool(publicClient, chainId, [token0, token1], salt, !!(options && options.useSubgraph))).toJson();
|
|
1061
|
+
if (!pool.isOpened) {
|
|
1062
|
+
throw new Error(`
|
|
1063
|
+
Open the pool before updating strategy price.
|
|
1064
|
+
import { openPool } from '@clober/v2-sdk'
|
|
1065
|
+
|
|
1066
|
+
const transaction = await openPool({
|
|
1067
|
+
chainId: ${chainId},
|
|
1068
|
+
tokenA: '${token0}',
|
|
1069
|
+
tokenB: '${token1}',
|
|
1070
|
+
salt: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
1071
|
+
})
|
|
1072
|
+
`);
|
|
1073
|
+
}
|
|
1074
|
+
const [roundingUpBidPrice, roundingUpAskPrice] = [
|
|
1075
|
+
options?.roundingUpBidPrice ? options.roundingUpBidPrice : false,
|
|
1076
|
+
options?.roundingUpAskPrice ? options.roundingUpAskPrice : false,
|
|
1077
|
+
];
|
|
1078
|
+
const { roundingDownTick: roundingDownTickA, roundingUpTick: roundingUpTickA, } = parsePrice(Number(bidPrice), pool.currencyA.decimals, pool.currencyB.decimals);
|
|
1079
|
+
const { roundingDownTick: roundingDownTickB, roundingUpTick: roundingUpTickB, } = parsePrice(Number(askPrice), pool.currencyA.decimals, pool.currencyB.decimals);
|
|
1080
|
+
const oracleRawPrice = convertHumanReadablePriceToRawPrice(Number(oraclePrice), pool.currencyA.decimals, pool.currencyB.decimals);
|
|
1081
|
+
const tickA = options?.bidTick
|
|
1082
|
+
? Number(options.bidTick)
|
|
1083
|
+
: Number(roundingUpBidPrice ? roundingUpTickA : roundingDownTickA);
|
|
1084
|
+
const tickB = options?.askTick
|
|
1085
|
+
? Number(options.askTick)
|
|
1086
|
+
: Number(invertTick(roundingUpAskPrice ? roundingUpTickB : roundingDownTickB));
|
|
1087
|
+
const alphaRaw = parseUnits(alpha, 6);
|
|
1088
|
+
return buildTransaction(publicClient, {
|
|
1089
|
+
chain: CHAIN_MAP[chainId],
|
|
1090
|
+
account: userAddress,
|
|
1091
|
+
address: CONTRACT_ADDRESSES[chainId].Operator,
|
|
1092
|
+
abi: OPERATOR_ABI,
|
|
1093
|
+
functionName: 'updatePrice',
|
|
1094
|
+
args: [pool.key, oracleRawPrice, tickA, tickB, alphaRaw],
|
|
1095
|
+
}, options?.gasLimit, options?.gasPriceLimit);
|
|
1096
|
+
};
|
|
1097
|
+
export const setStrategyConfig = async ({ chainId, userAddress, token0, token1, salt, config, options, }) => {
|
|
1098
|
+
// validate config
|
|
1099
|
+
if (Number(config.referenceThreshold) < 0 ||
|
|
1100
|
+
Number(config.referenceThreshold) > 1) {
|
|
1101
|
+
throw new Error('Reference threshold must be in the range [0, 1]');
|
|
1102
|
+
}
|
|
1103
|
+
if (Number(config.rebalanceThreshold) < 0 ||
|
|
1104
|
+
Number(config.rebalanceThreshold) > 1) {
|
|
1105
|
+
throw new Error('Rebalance threshold must be in the range [0, 1]');
|
|
1106
|
+
}
|
|
1107
|
+
if (Number(config.priceThresholdA) < 0 ||
|
|
1108
|
+
Number(config.priceThresholdA) > 1 ||
|
|
1109
|
+
Number(config.priceThresholdB) < 0 ||
|
|
1110
|
+
Number(config.priceThresholdB) > 1) {
|
|
1111
|
+
throw new Error('Price threshold must be in the range [0, 1]');
|
|
1112
|
+
}
|
|
1113
|
+
if (Number(config.rateA) < 0 ||
|
|
1114
|
+
Number(config.rateA) > 1 ||
|
|
1115
|
+
Number(config.rateB) < 0 ||
|
|
1116
|
+
Number(config.rateB) > 1) {
|
|
1117
|
+
throw new Error('Rate must be in the range [0, 1]');
|
|
1118
|
+
}
|
|
1119
|
+
if (Number(config.minRateA) < 0 ||
|
|
1120
|
+
Number(config.minRateA) > 1 ||
|
|
1121
|
+
Number(config.minRateB) < 0 ||
|
|
1122
|
+
Number(config.minRateB) > 1) {
|
|
1123
|
+
throw new Error('Min rate must be in the range [0, 1]');
|
|
1124
|
+
}
|
|
1125
|
+
if (Number(config.minRateA) > Number(config.rateA) ||
|
|
1126
|
+
Number(config.minRateB) > Number(config.rateB)) {
|
|
1127
|
+
throw new Error('Min rate must be less or equal to rate');
|
|
1128
|
+
}
|
|
1129
|
+
const publicClient = createPublicClient({
|
|
1130
|
+
chain: CHAIN_MAP[chainId],
|
|
1131
|
+
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
|
|
1132
|
+
});
|
|
1133
|
+
const pool = await fetchPool(publicClient, chainId, [token0, token1], salt, !!(options && options.useSubgraph));
|
|
1134
|
+
if (!pool.isOpened) {
|
|
1135
|
+
throw new Error(`
|
|
1136
|
+
Open the pool before set strategy config.
|
|
1137
|
+
import { openPool } from '@clober/v2-sdk'
|
|
1138
|
+
|
|
1139
|
+
const transaction = await openPool({
|
|
1140
|
+
chainId: ${chainId},
|
|
1141
|
+
tokenA: '${token0}',
|
|
1142
|
+
tokenB: '${token1}',
|
|
1143
|
+
})
|
|
1144
|
+
`);
|
|
1145
|
+
}
|
|
1146
|
+
const configRaw = {
|
|
1147
|
+
referenceThreshold: parseUnits(config.referenceThreshold, 6),
|
|
1148
|
+
rebalanceThreshold: parseUnits(config.rebalanceThreshold, 6),
|
|
1149
|
+
rateA: parseUnits(config.rateA, 6),
|
|
1150
|
+
rateB: parseUnits(config.rateB, 6),
|
|
1151
|
+
minRateA: parseUnits(config.minRateA, 6),
|
|
1152
|
+
minRateB: parseUnits(config.minRateB, 6),
|
|
1153
|
+
priceThresholdA: parseUnits(config.priceThresholdA, 6),
|
|
1154
|
+
priceThresholdB: parseUnits(config.priceThresholdB, 6),
|
|
1155
|
+
};
|
|
1156
|
+
return buildTransaction(publicClient, {
|
|
1157
|
+
chain: CHAIN_MAP[chainId],
|
|
1158
|
+
account: userAddress,
|
|
1159
|
+
address: CONTRACT_ADDRESSES[chainId].Strategy,
|
|
1160
|
+
abi: STRATEGY_ABI,
|
|
1161
|
+
functionName: 'setConfig',
|
|
1162
|
+
args: [pool.key, configRaw],
|
|
1163
|
+
}, options?.gasLimit);
|
|
1164
|
+
};
|
|
1165
|
+
export const pausePool = async ({ chainId, userAddress, token0, token1, salt, options, }) => {
|
|
1166
|
+
const publicClient = createPublicClient({
|
|
1167
|
+
chain: CHAIN_MAP[chainId],
|
|
1168
|
+
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
|
|
1169
|
+
});
|
|
1170
|
+
const pool = options?.pool
|
|
1171
|
+
? options.pool
|
|
1172
|
+
: (await fetchPool(publicClient, chainId, [token0, token1], salt, !!(options && options.useSubgraph))).toJson();
|
|
1173
|
+
if (!pool.isOpened) {
|
|
1174
|
+
throw new Error(`
|
|
1175
|
+
Open the pool before trying pause.
|
|
1176
|
+
import { openPool } from '@clober/v2-sdk'
|
|
1177
|
+
|
|
1178
|
+
const transaction = await openPool({
|
|
1179
|
+
chainId: ${chainId},
|
|
1180
|
+
tokenA: '${token0}',
|
|
1181
|
+
tokenB: '${token1}',
|
|
1182
|
+
salt: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
1183
|
+
})
|
|
1184
|
+
`);
|
|
1185
|
+
}
|
|
1186
|
+
if (pool.paused) {
|
|
1187
|
+
return undefined;
|
|
1188
|
+
}
|
|
1189
|
+
return buildTransaction(publicClient, {
|
|
1190
|
+
chain: CHAIN_MAP[chainId],
|
|
1191
|
+
account: userAddress,
|
|
1192
|
+
address: CONTRACT_ADDRESSES[chainId].Rebalancer,
|
|
1193
|
+
abi: REBALANCER_ABI,
|
|
1194
|
+
functionName: 'pause',
|
|
1195
|
+
args: [pool.key],
|
|
1196
|
+
}, options?.gasLimit, options?.gasPriceLimit);
|
|
1197
|
+
};
|
|
1198
|
+
export const resumePool = async ({ chainId, userAddress, token0, token1, salt, options, }) => {
|
|
1199
|
+
const publicClient = createPublicClient({
|
|
1200
|
+
chain: CHAIN_MAP[chainId],
|
|
1201
|
+
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
|
|
1202
|
+
});
|
|
1203
|
+
const pool = options?.pool
|
|
1204
|
+
? options.pool
|
|
1205
|
+
: (await fetchPool(publicClient, chainId, [token0, token1], salt, !!(options && options.useSubgraph))).toJson();
|
|
1206
|
+
if (!pool.isOpened) {
|
|
1207
|
+
throw new Error(`
|
|
1208
|
+
Open the pool before trying resume.
|
|
1209
|
+
import { openPool } from '@clober/v2-sdk'
|
|
1210
|
+
|
|
1211
|
+
const transaction = await openPool({
|
|
1212
|
+
chainId: ${chainId},
|
|
1213
|
+
tokenA: '${token0}',
|
|
1214
|
+
tokenB: '${token1}',
|
|
1215
|
+
salt: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
1216
|
+
})
|
|
1217
|
+
`);
|
|
1218
|
+
}
|
|
1219
|
+
if (!pool.paused) {
|
|
1220
|
+
return undefined;
|
|
1221
|
+
}
|
|
1222
|
+
return buildTransaction(publicClient, {
|
|
1223
|
+
chain: CHAIN_MAP[chainId],
|
|
1224
|
+
account: userAddress,
|
|
1225
|
+
address: CONTRACT_ADDRESSES[chainId].Rebalancer,
|
|
1226
|
+
abi: REBALANCER_ABI,
|
|
1227
|
+
functionName: 'resume',
|
|
1228
|
+
args: [pool.key],
|
|
1229
|
+
}, options?.gasLimit, options?.gasPriceLimit);
|
|
1230
|
+
};
|
|
559
1231
|
//# sourceMappingURL=call.js.map
|