@clober/v2-sdk 0.0.5 → 0.0.6-0.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 +262 -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 +370 -0
- package/dist/cjs/abis/rebalancer/operator-abi.js.map +1 -0
- package/dist/cjs/abis/rebalancer/rebalancer-abi.js +1235 -0
- package/dist/cjs/abis/rebalancer/rebalancer-abi.js.map +1 -0
- package/dist/cjs/abis/rebalancer/strategy-abi.js +633 -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 +61 -0
- package/dist/cjs/apis/pool.js.map +1 -0
- package/dist/cjs/apis/strategy.js +23 -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 +672 -155
- package/dist/cjs/call.js.map +1 -1
- package/dist/cjs/constants/addresses.js +41 -1
- package/dist/cjs/constants/addresses.js.map +1 -1
- package/dist/cjs/constants/chain.js +22 -2
- package/dist/cjs/constants/chain.js.map +1 -1
- package/dist/cjs/constants/currency.js +27 -2
- package/dist/cjs/constants/currency.js.map +1 -1
- package/dist/cjs/constants/fee.js +15 -2
- package/dist/cjs/constants/fee.js.map +1 -1
- package/dist/cjs/constants/permit.js +13 -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 +38 -0
- package/dist/cjs/constants/subgraph.js.map +1 -0
- package/dist/cjs/constants/test-chain.js +27 -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 +20 -6
- 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 +136 -0
- package/dist/cjs/model/pool.js.map +1 -0
- package/dist/cjs/model/strategy.js +3 -0
- package/dist/cjs/model/strategy.js.map +1 -0
- package/dist/cjs/signature.js +28 -20
- package/dist/cjs/signature.js.map +1 -1
- 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 +87 -5
- 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 +100 -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 +229 -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 +259 -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 +367 -0
- package/dist/esm/abis/rebalancer/operator-abi.js.map +1 -0
- package/dist/esm/abis/rebalancer/rebalancer-abi.js +1232 -0
- package/dist/esm/abis/rebalancer/rebalancer-abi.js.map +1 -0
- package/dist/esm/abis/rebalancer/strategy-abi.js +630 -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 +57 -0
- package/dist/esm/apis/pool.js.map +1 -0
- package/dist/esm/apis/strategy.js +19 -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 +789 -265
- package/dist/esm/call.js.map +1 -1
- package/dist/esm/constants/addresses.js +42 -2
- package/dist/esm/constants/addresses.js.map +1 -1
- package/dist/esm/constants/chain.js +21 -2
- package/dist/esm/constants/chain.js.map +1 -1
- package/dist/esm/constants/currency.js +29 -2
- package/dist/esm/constants/currency.js.map +1 -1
- package/dist/esm/constants/fee.js +15 -2
- package/dist/esm/constants/fee.js.map +1 -1
- package/dist/esm/constants/permit.js +10 -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 +34 -0
- package/dist/esm/constants/subgraph.js.map +1 -0
- package/dist/esm/constants/test-chain.js +24 -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 -0
- 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 +133 -0
- package/dist/esm/model/pool.js.map +1 -0
- package/dist/esm/model/strategy.js +2 -0
- package/dist/esm/model/strategy.js.map +1 -0
- package/dist/esm/signature.js +42 -41
- package/dist/esm/signature.js.map +1 -1
- 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 +85 -4
- 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 +96 -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 +367 -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 +198 -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 +283 -0
- package/dist/types/abis/rebalancer/operator-abi.d.ts.map +1 -0
- package/dist/types/abis/rebalancer/rebalancer-abi.d.ts +952 -0
- package/dist/types/abis/rebalancer/rebalancer-abi.d.ts.map +1 -0
- package/dist/types/abis/rebalancer/strategy-abi.d.ts +487 -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 +5 -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 +47 -15
- package/dist/types/approval.d.ts.map +1 -1
- package/dist/types/call.d.ts +250 -122
- 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/chain.d.ts +6 -2
- package/dist/types/constants/chain.d.ts.map +1 -1
- 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 +3 -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 -0
- 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 +11 -6
- package/dist/types/model/open-order.d.ts.map +1 -1
- package/dist/types/model/pool.d.ts +38 -0
- package/dist/types/model/pool.d.ts.map +1 -0
- package/dist/types/model/strategy.d.ts +6 -0
- package/dist/types/model/strategy.d.ts.map +1 -0
- package/dist/types/signature.d.ts +19 -25
- package/dist/types/signature.d.ts.map +1 -1
- package/dist/types/type.d.ts +63 -5
- 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 +9 -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 +283 -46
- package/dist/types/view.d.ts.map +1 -1
- package/package.json +1 -1
- 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/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/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/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,83 @@
|
|
|
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 {
|
|
10
|
+
import { convertHumanReadablePriceToRawPrice, formatPrice, parsePrice, } from './utils/prices';
|
|
11
|
+
import { invertTick, toPrice } from './utils/tick';
|
|
12
|
+
import { getExpectedInput, getExpectedOutput } from './view';
|
|
13
13
|
import { toBookId } from './utils/book-id';
|
|
14
14
|
import { fetchIsApprovedForAll } from './utils/approval';
|
|
15
|
-
import {
|
|
15
|
+
import { fetchOrders } 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';
|
|
16
26
|
/**
|
|
17
27
|
* Build a transaction to open a market.
|
|
18
28
|
*
|
|
19
29
|
* @param chainId The chain ID of the blockchain.
|
|
30
|
+
* @param userAddress The address of the user.
|
|
20
31
|
* @param inputToken The address of the input token.
|
|
21
32
|
* @param outputToken The address of the output token.
|
|
22
|
-
* @param options
|
|
23
|
-
* @param options.rpcUrl The RPC URL of the blockchain.
|
|
33
|
+
* @param options {@link DefaultOptions} options.
|
|
24
34
|
* @returns A Promise resolving to a transaction object. If the market is already open, returns undefined.
|
|
25
35
|
* @example
|
|
26
36
|
* import { openMarket } from '@clober/v2-sdk'
|
|
27
37
|
*
|
|
28
|
-
* const transaction = await openMarket(
|
|
29
|
-
* 421614,
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
38
|
+
* const transaction = await openMarket({
|
|
39
|
+
* chainId: 421614,
|
|
40
|
+
* userAddress: '0xF8c1869Ecd4df136693C45EcE1b67f85B6bDaE69',
|
|
41
|
+
* inputToken: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
42
|
+
* outputToken: '0x0000000000000000000000000000000000000000'
|
|
43
|
+
* })
|
|
33
44
|
*/
|
|
34
|
-
export const openMarket =
|
|
35
|
-
const
|
|
45
|
+
export const openMarket = async ({ chainId, userAddress, inputToken, outputToken, options, }) => {
|
|
46
|
+
const publicClient = createPublicClient({
|
|
47
|
+
chain: CHAIN_MAP[chainId],
|
|
48
|
+
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
|
|
49
|
+
});
|
|
50
|
+
const market = await fetchMarket(publicClient, chainId, [inputToken, outputToken], !!(options && options.useSubgraph));
|
|
36
51
|
const isBid = isAddressEqual(market.quote.address, inputToken);
|
|
37
|
-
if ((isBid && !market.
|
|
38
|
-
|
|
39
|
-
|
|
52
|
+
if ((isBid && !market.bidBook.isOpened) ||
|
|
53
|
+
(!isBid && !market.askBook.isOpened)) {
|
|
54
|
+
const unitSize = await calculateUnitSize(publicClient, chainId, isBid ? market.quote : market.base);
|
|
55
|
+
return buildTransaction(publicClient, {
|
|
56
|
+
chain: CHAIN_MAP[chainId],
|
|
40
57
|
address: CONTRACT_ADDRESSES[chainId].Controller,
|
|
58
|
+
account: userAddress,
|
|
41
59
|
abi: CONTROLLER_ABI,
|
|
42
60
|
functionName: 'open',
|
|
43
61
|
args: [
|
|
44
62
|
[
|
|
45
63
|
{
|
|
46
64
|
key: {
|
|
47
|
-
base:
|
|
48
|
-
|
|
49
|
-
quote:
|
|
50
|
-
makerPolicy: MAKER_DEFAULT_POLICY.value,
|
|
65
|
+
base: outputToken,
|
|
66
|
+
unitSize,
|
|
67
|
+
quote: inputToken,
|
|
68
|
+
makerPolicy: MAKER_DEFAULT_POLICY[chainId].value,
|
|
51
69
|
hooks: zeroAddress,
|
|
52
|
-
takerPolicy: TAKER_DEFAULT_POLICY.value,
|
|
70
|
+
takerPolicy: TAKER_DEFAULT_POLICY[chainId].value,
|
|
53
71
|
},
|
|
54
72
|
hookData: zeroHash,
|
|
55
73
|
},
|
|
56
74
|
],
|
|
57
75
|
getDeadlineTimestampInSeconds(),
|
|
58
76
|
],
|
|
59
|
-
});
|
|
77
|
+
}, options?.gasLimit);
|
|
60
78
|
}
|
|
61
79
|
return undefined;
|
|
62
|
-
}
|
|
80
|
+
};
|
|
63
81
|
/**
|
|
64
82
|
* Places a limit order on the specified chain for trading tokens.
|
|
65
83
|
*
|
|
@@ -69,66 +87,84 @@ export const openMarket = decorator(async ({ chainId, inputToken, outputToken, }
|
|
|
69
87
|
* @param {`0x${string}`} outputToken The address of the token to be received as output.
|
|
70
88
|
* @param {string} amount The amount of input tokens for the order.
|
|
71
89
|
* @param {string} price The price at which the order should be executed.
|
|
72
|
-
* @param {
|
|
73
|
-
* @param {
|
|
90
|
+
* @param options {@link DefaultOptions} options.
|
|
91
|
+
* @param {erc20PermitParam} [options.erc20PermitParam] The permit signature for token approval.
|
|
74
92
|
* @param {boolean} [options.postOnly] A boolean indicating whether the order is only to be made not taken.
|
|
75
|
-
* @param {
|
|
76
|
-
* @
|
|
93
|
+
* @param {bigint} [options.makeTick] The tick for the make order.
|
|
94
|
+
* @param {bigint} [options.takeLimitTick] The tick for the take order.
|
|
95
|
+
* @param {boolean} [options.roundingUpMakeBid] A boolean indicating whether to round up the make bid.
|
|
96
|
+
* @param {boolean} [options.roundingDownMakeAsk] A boolean indicating whether to round down the make ask.
|
|
97
|
+
* @param {boolean} [options.roundingDownTakenBid] A boolean indicating whether to round down the taken bid.
|
|
98
|
+
* @param {boolean} [options.roundingUpTakenAsk] A boolean indicating whether to round up the taken ask.
|
|
99
|
+
* @returns {Promise<{ transaction: Transaction, result: { make: CurrencyFlow, take: CurrencyFlow, spent: CurrencyFlow }>}
|
|
77
100
|
* Promise resolving to the transaction object representing the limit order with the result of the order.
|
|
78
101
|
* @example
|
|
79
102
|
* import { signERC20Permit, limitOrder } from '@clober/v2-sdk'
|
|
80
103
|
* import { privateKeyToAccount } from 'viem/accounts'
|
|
81
104
|
*
|
|
82
|
-
* const
|
|
83
|
-
* 421614,
|
|
84
|
-
*
|
|
85
|
-
* '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
86
|
-
* '100.123'
|
|
87
|
-
* )
|
|
105
|
+
* const erc20PermitParam = await signERC20Permit({
|
|
106
|
+
* chainId: 421614,
|
|
107
|
+
* walletClient,
|
|
108
|
+
* token: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
109
|
+
* amount: '100.123'
|
|
110
|
+
* })
|
|
88
111
|
*
|
|
89
|
-
* const { transaction } = await limitOrder(
|
|
90
|
-
* 421614,
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
* )
|
|
112
|
+
* const { transaction } = await limitOrder({
|
|
113
|
+
* chainId: 421614,
|
|
114
|
+
* userAddress: '0xF8c1869Ecd4df136693C45EcE1b67f85B6bDaE69
|
|
115
|
+
* inputToken: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
116
|
+
* outputToken: '0x0000000000000000000000000000000000000000',
|
|
117
|
+
* amount: '100.123', // 100.123 USDC
|
|
118
|
+
* price: '4000.01', // price at 4000.01 (ETH/USDC)
|
|
119
|
+
* options: { erc20PermitParam }
|
|
120
|
+
* })
|
|
98
121
|
*
|
|
99
122
|
* @example
|
|
100
123
|
* import { limitOrder } from '@clober/v2-sdk'
|
|
101
124
|
*
|
|
102
|
-
* const { transaction } = await limitOrder(
|
|
103
|
-
* 421614,
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* )
|
|
125
|
+
* const { transaction } = await limitOrder({
|
|
126
|
+
* chainId: 421614,
|
|
127
|
+
* userAddress: '0xF8c1869Ecd4df136693C45EcE1b67f85B6bDaE69
|
|
128
|
+
* inputToken: '0x0000000000000000000000000000000000000000',
|
|
129
|
+
* outputToken: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
130
|
+
* amount: '0.13', // 0.13 ETH
|
|
131
|
+
* price: '4000.01', // price at 4000.01 (ETH/USDC)
|
|
132
|
+
* })
|
|
110
133
|
*/
|
|
111
|
-
export const limitOrder =
|
|
112
|
-
const
|
|
134
|
+
export const limitOrder = async ({ chainId, userAddress, inputToken, outputToken, amount, price, options, }) => {
|
|
135
|
+
const [roundingUpMakeBid, roundingDownMakeAsk, roundingDownTakenBid, roundingUpTakenAsk,] = [
|
|
136
|
+
options?.roundingUpMakeBid ? options.roundingUpMakeBid : false,
|
|
137
|
+
options?.roundingDownMakeAsk ? options.roundingDownMakeAsk : false,
|
|
138
|
+
options?.roundingDownTakenBid ? options.roundingDownTakenBid : false,
|
|
139
|
+
options?.roundingUpTakenAsk ? options.roundingUpTakenAsk : false,
|
|
140
|
+
];
|
|
141
|
+
const publicClient = createPublicClient({
|
|
142
|
+
chain: CHAIN_MAP[chainId],
|
|
143
|
+
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
|
|
144
|
+
});
|
|
145
|
+
const market = await fetchMarket(publicClient, chainId, [inputToken, outputToken], !!(options && options.useSubgraph));
|
|
113
146
|
const isBid = isAddressEqual(market.quote.address, inputToken);
|
|
114
|
-
|
|
147
|
+
const [inputCurrency, outputCurrency] = isBid
|
|
148
|
+
? [market.quote, market.base]
|
|
149
|
+
: [market.base, market.quote];
|
|
150
|
+
if ((isBid && !market.bidBook.isOpened) ||
|
|
151
|
+
(!isBid && !market.askBook.isOpened)) {
|
|
115
152
|
throw new Error(`
|
|
116
153
|
Open the market before placing a limit order.
|
|
117
154
|
import { openMarket } from '@clober/v2-sdk'
|
|
118
155
|
|
|
119
|
-
const transaction = await openMarket(
|
|
120
|
-
${chainId},
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
)
|
|
156
|
+
const transaction = await openMarket({
|
|
157
|
+
chainId: ${chainId},
|
|
158
|
+
inputToken: '${inputToken}',
|
|
159
|
+
outputToken: '${outputToken}',
|
|
160
|
+
})
|
|
124
161
|
`);
|
|
125
162
|
}
|
|
126
|
-
const
|
|
127
|
-
const tick = isBid ? fromPrice(rawPrice) : fromPrice(invertPrice(rawPrice));
|
|
163
|
+
const { roundingDownTick, roundingUpTick } = parsePrice(Number(price), market.quote.decimals, market.base.decimals);
|
|
128
164
|
const tokensToSettle = [inputToken, outputToken].filter((address) => !isAddressEqual(address, zeroAddress));
|
|
129
|
-
const quoteAmount = parseUnits(amount,
|
|
130
|
-
const [
|
|
131
|
-
|
|
165
|
+
const quoteAmount = parseUnits(amount, inputCurrency.decimals);
|
|
166
|
+
const [unitSize, { takenAmount, spentAmount, bookId, events }] = await Promise.all([
|
|
167
|
+
calculateUnitSize(publicClient, chainId, inputCurrency),
|
|
132
168
|
getExpectedOutput({
|
|
133
169
|
chainId,
|
|
134
170
|
inputToken,
|
|
@@ -136,28 +172,26 @@ export const limitOrder = decorator(async ({ chainId, userAddress, inputToken, o
|
|
|
136
172
|
amountIn: amount,
|
|
137
173
|
options: {
|
|
138
174
|
...options,
|
|
175
|
+
limitPrice: price,
|
|
139
176
|
},
|
|
140
177
|
}),
|
|
141
178
|
]);
|
|
142
179
|
const isETH = isAddressEqual(inputToken, zeroAddress);
|
|
143
|
-
const permitParamsList = options?.signature && !isETH
|
|
144
|
-
? [
|
|
145
|
-
{
|
|
146
|
-
token: inputToken,
|
|
147
|
-
permitAmount: quoteAmount,
|
|
148
|
-
signature: options.signature,
|
|
149
|
-
},
|
|
150
|
-
]
|
|
151
|
-
: [];
|
|
152
180
|
const makeParam = {
|
|
153
|
-
id: toBookId(inputToken, outputToken,
|
|
154
|
-
tick:
|
|
181
|
+
id: toBookId(chainId, inputToken, outputToken, unitSize),
|
|
182
|
+
tick: options?.makeTick
|
|
183
|
+
? Number(options.makeTick)
|
|
184
|
+
: Number(isBid
|
|
185
|
+
? roundingUpMakeBid
|
|
186
|
+
? roundingUpTick
|
|
187
|
+
: roundingDownTick
|
|
188
|
+
: invertTick(roundingDownMakeAsk ? roundingDownTick : roundingUpTick)),
|
|
155
189
|
quoteAmount,
|
|
156
190
|
hookData: zeroHash,
|
|
157
191
|
};
|
|
158
|
-
if (options?.postOnly === true ||
|
|
192
|
+
if (options?.postOnly === true || spentAmount === '0') {
|
|
159
193
|
return {
|
|
160
|
-
transaction: await buildTransaction(
|
|
194
|
+
transaction: await buildTransaction(publicClient, {
|
|
161
195
|
chain: CHAIN_MAP[chainId],
|
|
162
196
|
account: userAddress,
|
|
163
197
|
address: CONTRACT_ADDRESSES[chainId].Controller,
|
|
@@ -166,21 +200,31 @@ export const limitOrder = decorator(async ({ chainId, userAddress, inputToken, o
|
|
|
166
200
|
args: [
|
|
167
201
|
[makeParam],
|
|
168
202
|
tokensToSettle,
|
|
169
|
-
|
|
203
|
+
options?.erc20PermitParam ? [options.erc20PermitParam] : [],
|
|
170
204
|
getDeadlineTimestampInSeconds(),
|
|
171
205
|
],
|
|
172
206
|
value: isETH ? quoteAmount : 0n,
|
|
173
|
-
}),
|
|
207
|
+
}, options?.gasLimit),
|
|
174
208
|
result: {
|
|
175
209
|
make: {
|
|
176
|
-
amount: formatUnits(quoteAmount,
|
|
177
|
-
currency:
|
|
210
|
+
amount: formatUnits(quoteAmount, inputCurrency.decimals),
|
|
211
|
+
currency: inputCurrency,
|
|
212
|
+
direction: 'in',
|
|
213
|
+
price: formatPrice(isBid
|
|
214
|
+
? toPrice(BigInt(makeParam.tick))
|
|
215
|
+
: toPrice(invertTick(BigInt(makeParam.tick))), market.quote.decimals, market.base.decimals),
|
|
216
|
+
},
|
|
217
|
+
spent: {
|
|
218
|
+
amount: '0',
|
|
219
|
+
currency: inputCurrency,
|
|
178
220
|
direction: 'in',
|
|
221
|
+
events: [],
|
|
179
222
|
},
|
|
180
|
-
|
|
223
|
+
taken: {
|
|
181
224
|
amount: '0',
|
|
182
|
-
currency:
|
|
225
|
+
currency: outputCurrency,
|
|
183
226
|
direction: 'out',
|
|
227
|
+
events: [],
|
|
184
228
|
},
|
|
185
229
|
},
|
|
186
230
|
};
|
|
@@ -188,7 +232,7 @@ export const limitOrder = decorator(async ({ chainId, userAddress, inputToken, o
|
|
|
188
232
|
else {
|
|
189
233
|
// take and make
|
|
190
234
|
return {
|
|
191
|
-
transaction: await buildTransaction(
|
|
235
|
+
transaction: await buildTransaction(publicClient, {
|
|
192
236
|
chain: CHAIN_MAP[chainId],
|
|
193
237
|
account: userAddress,
|
|
194
238
|
address: CONTRACT_ADDRESSES[chainId].Controller,
|
|
@@ -199,7 +243,15 @@ export const limitOrder = decorator(async ({ chainId, userAddress, inputToken, o
|
|
|
199
243
|
{
|
|
200
244
|
takeBookId: bookId,
|
|
201
245
|
makeBookId: makeParam.id,
|
|
202
|
-
limitPrice:
|
|
246
|
+
limitPrice: options?.takeLimitTick
|
|
247
|
+
? toPrice(options.takeLimitTick)
|
|
248
|
+
: toPrice(isBid
|
|
249
|
+
? invertTick(roundingUpTakenAsk
|
|
250
|
+
? roundingUpTick
|
|
251
|
+
: roundingDownTick)
|
|
252
|
+
: roundingDownTakenBid
|
|
253
|
+
? roundingDownTick
|
|
254
|
+
: roundingUpTick),
|
|
203
255
|
tick: makeParam.tick,
|
|
204
256
|
quoteAmount,
|
|
205
257
|
takeHookData: zeroHash,
|
|
@@ -207,75 +259,100 @@ export const limitOrder = decorator(async ({ chainId, userAddress, inputToken, o
|
|
|
207
259
|
},
|
|
208
260
|
],
|
|
209
261
|
tokensToSettle,
|
|
210
|
-
|
|
262
|
+
options?.erc20PermitParam ? [options.erc20PermitParam] : [],
|
|
211
263
|
getDeadlineTimestampInSeconds(),
|
|
212
264
|
],
|
|
213
265
|
value: isETH ? quoteAmount : 0n,
|
|
214
|
-
}),
|
|
266
|
+
}, options?.gasLimit),
|
|
215
267
|
result: {
|
|
216
268
|
make: {
|
|
217
|
-
amount: formatUnits(quoteAmount
|
|
218
|
-
currency:
|
|
269
|
+
amount: formatUnits(quoteAmount - parseUnits(spentAmount, inputCurrency.decimals), inputCurrency.decimals),
|
|
270
|
+
currency: inputCurrency,
|
|
219
271
|
direction: 'in',
|
|
272
|
+
price: formatPrice(isBid
|
|
273
|
+
? toPrice(BigInt(makeParam.tick))
|
|
274
|
+
: toPrice(invertTick(BigInt(makeParam.tick))), market.quote.decimals, market.base.decimals),
|
|
220
275
|
},
|
|
221
|
-
|
|
222
|
-
amount:
|
|
223
|
-
currency:
|
|
276
|
+
spent: {
|
|
277
|
+
amount: spentAmount,
|
|
278
|
+
currency: inputCurrency,
|
|
279
|
+
direction: 'in',
|
|
280
|
+
events: events.map(({ price, spentAmount }) => ({
|
|
281
|
+
price,
|
|
282
|
+
amount: spentAmount,
|
|
283
|
+
})),
|
|
284
|
+
},
|
|
285
|
+
taken: {
|
|
286
|
+
amount: takenAmount,
|
|
287
|
+
currency: outputCurrency,
|
|
224
288
|
direction: 'out',
|
|
289
|
+
events: events.map(({ price, takenAmount }) => ({
|
|
290
|
+
price,
|
|
291
|
+
amount: takenAmount,
|
|
292
|
+
})),
|
|
225
293
|
},
|
|
226
294
|
},
|
|
227
295
|
};
|
|
228
296
|
}
|
|
229
|
-
}
|
|
297
|
+
};
|
|
230
298
|
/**
|
|
231
299
|
* Executes a market order on the specified chain for trading tokens.
|
|
300
|
+
* If only `amountIn` is provided, spend the specified amount of input tokens.
|
|
301
|
+
* If only `amountOut` is provided, take the specified amount of output tokens.
|
|
232
302
|
*
|
|
233
303
|
* @param {CHAIN_IDS} chainId The chain ID.
|
|
234
304
|
* @param {`0x${string}`} userAddress The Ethereum address of the user placing the order.
|
|
235
305
|
* @param {`0x${string}`} inputToken The address of the token to be used as input.
|
|
236
306
|
* @param {`0x${string}`} outputToken The address of the token to be received as output.
|
|
237
|
-
* @param {string}
|
|
238
|
-
* @param {
|
|
239
|
-
* @param {
|
|
240
|
-
* @param {
|
|
241
|
-
* @param {
|
|
242
|
-
*
|
|
243
|
-
* @
|
|
307
|
+
* @param {string} amountIn The amount of input tokens for the order to spend.
|
|
308
|
+
* @param {string} amountOut The amount of output tokens for the order to take.
|
|
309
|
+
* @param options {@link DefaultOptions} options.
|
|
310
|
+
* @param {erc20PermitParam} [options.erc20PermitParam] The permit signature for token approval.
|
|
311
|
+
* @param {number} [options.slippage] The maximum slippage percentage allowed for the order.
|
|
312
|
+
* @param {boolean} [options.roundingDownTakenBid] A boolean indicating whether to round down the taken bid.
|
|
313
|
+
* @param {boolean} [options.roundingUpTakenAsk] A boolean indicating whether to round up the taken ask.
|
|
314
|
+
* if the slippage is not provided, unlimited slippage is allowed.
|
|
315
|
+
* @returns {Promise<{ transaction: Transaction, result: { spent: CurrencyFlow, taken: CurrencyFlow } }>}
|
|
316
|
+
* Promise resolving to the transaction object representing the market order with the result of the order.
|
|
244
317
|
* @example
|
|
245
318
|
* import { signERC20Permit, marketOrder } from '@clober/v2-sdk'
|
|
246
319
|
* import { privateKeyToAccount } from 'viem/accounts'
|
|
247
320
|
*
|
|
248
|
-
* const
|
|
249
|
-
* 421614,
|
|
250
|
-
*
|
|
251
|
-
* '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
252
|
-
* '100.123'
|
|
253
|
-
* )
|
|
321
|
+
* const erc20PermitParam = await signERC20Permit({
|
|
322
|
+
* chainId: 421614,
|
|
323
|
+
* walletClient,
|
|
324
|
+
* token: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
325
|
+
* amount: '100.123'
|
|
326
|
+
* })
|
|
254
327
|
*
|
|
255
|
-
* const transaction = await marketOrder(
|
|
256
|
-
* 421614,
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
* )
|
|
263
|
-
*
|
|
264
|
-
* @example
|
|
265
|
-
* import { marketOrder } from '@clober/v2-sdk'
|
|
328
|
+
* const transaction = await marketOrder({
|
|
329
|
+
* chainId: 421614,
|
|
330
|
+
* userAddress: '0xF8c1869Ecd4df136693C45EcE1b67f85B6bDaE69
|
|
331
|
+
* inputToken: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
332
|
+
* outputToken: '0x0000000000000000000000000000000000000000',
|
|
333
|
+
* amount: '100.123', // 100.123 USDC
|
|
334
|
+
* options: { erc20PermitParam }
|
|
335
|
+
* })
|
|
266
336
|
*
|
|
267
|
-
* const transaction = await limitOrder(
|
|
268
|
-
* 421614,
|
|
269
|
-
* '0xF8c1869Ecd4df136693C45EcE1b67f85B6bDaE69
|
|
270
|
-
* '0x0000000000000000000000000000000000000000',
|
|
271
|
-
* '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
272
|
-
* '0.13', // 0.13 ETH
|
|
273
|
-
* )
|
|
274
337
|
*/
|
|
275
|
-
export const marketOrder =
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
338
|
+
export const marketOrder = async ({ chainId, userAddress, inputToken, outputToken, amountIn, amountOut, options, }) => {
|
|
339
|
+
if (!amountIn && !amountOut) {
|
|
340
|
+
throw new Error('Either amountIn or amountOut must be provided');
|
|
341
|
+
}
|
|
342
|
+
else if (amountIn && amountOut) {
|
|
343
|
+
throw new Error('Only one of amountIn or amountOut can be provided');
|
|
344
|
+
}
|
|
345
|
+
const publicClient = createPublicClient({
|
|
346
|
+
chain: CHAIN_MAP[chainId],
|
|
347
|
+
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
|
|
348
|
+
});
|
|
349
|
+
const market = await fetchMarket(publicClient, chainId, [inputToken, outputToken], !!(options && options.useSubgraph));
|
|
350
|
+
const isTakingBid = isAddressEqual(market.base.address, inputToken);
|
|
351
|
+
const [inputCurrency, outputCurrency] = isTakingBid
|
|
352
|
+
? [market.base, market.quote]
|
|
353
|
+
: [market.quote, market.base];
|
|
354
|
+
if ((isTakingBid && !market.bidBook.isOpened) ||
|
|
355
|
+
(!isTakingBid && !market.askBook.isOpened)) {
|
|
279
356
|
throw new Error(`
|
|
280
357
|
Open the market before placing a market order.
|
|
281
358
|
import { openMarket } from '@clober/v2-sdk'
|
|
@@ -287,50 +364,135 @@ export const marketOrder = decorator(async ({ chainId, userAddress, inputToken,
|
|
|
287
364
|
)
|
|
288
365
|
`);
|
|
289
366
|
}
|
|
290
|
-
const rawLimitPrice = parsePrice(Number(options?.limitPrice ?? '0'), market.quote.decimals, market.base.decimals);
|
|
291
367
|
const tokensToSettle = [inputToken, outputToken].filter((address) => !isAddressEqual(address, zeroAddress));
|
|
292
|
-
const quoteAmount = parseUnits(amount, isBid ? market.quote.decimals : market.base.decimals);
|
|
293
|
-
const { bookId, takenAmount } = await getExpectedOutput({
|
|
294
|
-
chainId,
|
|
295
|
-
inputToken,
|
|
296
|
-
outputToken,
|
|
297
|
-
amountIn: amount,
|
|
298
|
-
options: {
|
|
299
|
-
...options,
|
|
300
|
-
},
|
|
301
|
-
});
|
|
302
368
|
const isETH = isAddressEqual(inputToken, zeroAddress);
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
369
|
+
if (amountIn && !amountOut) {
|
|
370
|
+
const { bookId, takenAmount, spentAmount, events } = await getExpectedOutput({
|
|
371
|
+
chainId,
|
|
372
|
+
inputToken,
|
|
373
|
+
outputToken,
|
|
374
|
+
amountIn,
|
|
375
|
+
options: {
|
|
376
|
+
...options,
|
|
377
|
+
// don't need to check limit price for market order
|
|
309
378
|
},
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
379
|
+
});
|
|
380
|
+
const baseAmount = parseUnits(amountIn, inputCurrency.decimals);
|
|
381
|
+
return {
|
|
382
|
+
transaction: await buildTransaction(publicClient, {
|
|
383
|
+
chain: CHAIN_MAP[chainId],
|
|
384
|
+
account: userAddress,
|
|
385
|
+
address: CONTRACT_ADDRESSES[chainId].Controller,
|
|
386
|
+
abi: CONTROLLER_ABI,
|
|
387
|
+
functionName: 'spend',
|
|
388
|
+
args: [
|
|
389
|
+
[
|
|
390
|
+
{
|
|
391
|
+
id: bookId,
|
|
392
|
+
limitPrice: 0n,
|
|
393
|
+
baseAmount,
|
|
394
|
+
minQuoteAmount: options?.slippage
|
|
395
|
+
? applyPercent(parseUnits(takenAmount, outputCurrency.decimals), 100 - options.slippage)
|
|
396
|
+
: 0n,
|
|
397
|
+
hookData: zeroHash,
|
|
398
|
+
},
|
|
399
|
+
],
|
|
400
|
+
tokensToSettle,
|
|
401
|
+
options?.erc20PermitParam ? [options.erc20PermitParam] : [],
|
|
402
|
+
getDeadlineTimestampInSeconds(),
|
|
403
|
+
],
|
|
404
|
+
value: isETH ? baseAmount : 0n,
|
|
405
|
+
}, options?.gasLimit),
|
|
406
|
+
result: {
|
|
407
|
+
spent: {
|
|
408
|
+
amount: spentAmount,
|
|
409
|
+
currency: inputCurrency,
|
|
410
|
+
direction: 'in',
|
|
411
|
+
events: events.map(({ price, spentAmount }) => ({
|
|
412
|
+
price,
|
|
413
|
+
amount: spentAmount,
|
|
414
|
+
})),
|
|
325
415
|
},
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
})
|
|
416
|
+
taken: {
|
|
417
|
+
amount: takenAmount,
|
|
418
|
+
currency: outputCurrency,
|
|
419
|
+
direction: 'out',
|
|
420
|
+
events: events.map(({ price, takenAmount }) => ({
|
|
421
|
+
price,
|
|
422
|
+
amount: takenAmount,
|
|
423
|
+
})),
|
|
424
|
+
},
|
|
425
|
+
},
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
else if (!amountIn && amountOut) {
|
|
429
|
+
const { bookId, spentAmount, takenAmount, events } = await getExpectedInput({
|
|
430
|
+
chainId,
|
|
431
|
+
inputToken,
|
|
432
|
+
outputToken,
|
|
433
|
+
amountOut,
|
|
434
|
+
options: {
|
|
435
|
+
...options,
|
|
436
|
+
// don't need to check limit price for market order
|
|
437
|
+
},
|
|
438
|
+
});
|
|
439
|
+
const quoteAmount = parseUnits(amountOut, outputCurrency.decimals);
|
|
440
|
+
const baseAmount = parseUnits(spentAmount, inputCurrency.decimals);
|
|
441
|
+
const maxBaseAmount = options?.erc20PermitParam?.permitAmount ??
|
|
442
|
+
(options?.slippage
|
|
443
|
+
? applyPercent(baseAmount, 100 + options.slippage)
|
|
444
|
+
: isETH
|
|
445
|
+
? baseAmount
|
|
446
|
+
: 2n ** 256n - 1n);
|
|
447
|
+
return {
|
|
448
|
+
transaction: await buildTransaction(publicClient, {
|
|
449
|
+
chain: CHAIN_MAP[chainId],
|
|
450
|
+
account: userAddress,
|
|
451
|
+
address: CONTRACT_ADDRESSES[chainId].Controller,
|
|
452
|
+
abi: CONTROLLER_ABI,
|
|
453
|
+
functionName: 'take',
|
|
454
|
+
args: [
|
|
455
|
+
[
|
|
456
|
+
{
|
|
457
|
+
id: bookId,
|
|
458
|
+
limitPrice: 0n,
|
|
459
|
+
quoteAmount,
|
|
460
|
+
maxBaseAmount,
|
|
461
|
+
hookData: zeroHash,
|
|
462
|
+
},
|
|
463
|
+
],
|
|
464
|
+
tokensToSettle,
|
|
465
|
+
options?.erc20PermitParam ? [options.erc20PermitParam] : [],
|
|
466
|
+
getDeadlineTimestampInSeconds(),
|
|
467
|
+
],
|
|
468
|
+
value: isETH ? maxBaseAmount : 0n,
|
|
469
|
+
}, options?.gasLimit),
|
|
470
|
+
result: {
|
|
471
|
+
spent: {
|
|
472
|
+
amount: spentAmount,
|
|
473
|
+
currency: inputCurrency,
|
|
474
|
+
direction: 'in',
|
|
475
|
+
events: events.map(({ price, spentAmount }) => ({
|
|
476
|
+
price,
|
|
477
|
+
amount: spentAmount,
|
|
478
|
+
})),
|
|
479
|
+
},
|
|
480
|
+
taken: {
|
|
481
|
+
amount: takenAmount,
|
|
482
|
+
currency: outputCurrency,
|
|
483
|
+
direction: 'out',
|
|
484
|
+
events: events.map(({ price, takenAmount }) => ({
|
|
485
|
+
price,
|
|
486
|
+
amount: takenAmount,
|
|
487
|
+
})),
|
|
488
|
+
},
|
|
489
|
+
},
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
else {
|
|
493
|
+
throw new Error('Either amountIn or amountOut must be provided');
|
|
494
|
+
}
|
|
495
|
+
};
|
|
334
496
|
/**
|
|
335
497
|
* Claims specified open order for settlement.
|
|
336
498
|
* [IMPORTANT] Set ApprovalForAll before calling this function.
|
|
@@ -338,25 +500,24 @@ export const marketOrder = decorator(async ({ chainId, userAddress, inputToken,
|
|
|
338
500
|
* @param {CHAIN_IDS} chainId The chain ID.
|
|
339
501
|
* @param {`0x${string}`} userAddress The Ethereum address of the user.
|
|
340
502
|
* @param {string} id An ID representing the open order to be claimed.
|
|
341
|
-
* @param {
|
|
342
|
-
* @param {string} [options.rpcUrl] The RPC URL to use for executing the transaction.
|
|
503
|
+
* @param options {@link DefaultOptions} options.
|
|
343
504
|
* @returns {Promise<{ transaction: Transaction, result: CurrencyFlow }>}
|
|
344
505
|
* Promise resolving to the transaction object representing the claim action with the result of the order.
|
|
345
506
|
* @throws {Error} Throws an error if no open orders are found for the specified user.
|
|
346
507
|
* @example
|
|
347
508
|
* import { getOpenOrders, claimOrders } from '@clober/v2-sdk'
|
|
348
509
|
*
|
|
349
|
-
* const openOrders = await getOpenOrders(
|
|
350
|
-
* 421614,
|
|
351
|
-
*
|
|
352
|
-
* )
|
|
353
|
-
* const transaction = await claimOrders(
|
|
354
|
-
* 421614,
|
|
355
|
-
* '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
356
|
-
* openOrders.map((order) => order.id)
|
|
357
|
-
* )
|
|
510
|
+
* const openOrders = await getOpenOrders({
|
|
511
|
+
* chainId: 421614,
|
|
512
|
+
* userAddress: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0'
|
|
513
|
+
* })
|
|
514
|
+
* const transaction = await claimOrders({
|
|
515
|
+
* chainId: 421614,
|
|
516
|
+
* userAddress: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
517
|
+
* id: openOrders.map((order) => order.id)
|
|
518
|
+
* })
|
|
358
519
|
*/
|
|
359
|
-
export const claimOrder =
|
|
520
|
+
export const claimOrder = async ({ chainId, userAddress, id, options, }) => {
|
|
360
521
|
const { transaction, result } = await claimOrders({
|
|
361
522
|
chainId,
|
|
362
523
|
userAddress,
|
|
@@ -367,7 +528,7 @@ export const claimOrder = decorator(async ({ chainId, userAddress, id, options,
|
|
|
367
528
|
transaction,
|
|
368
529
|
result: result[0],
|
|
369
530
|
};
|
|
370
|
-
}
|
|
531
|
+
};
|
|
371
532
|
/**
|
|
372
533
|
* Claims specified open orders for settlement.
|
|
373
534
|
* [IMPORTANT] Set ApprovalForAll before calling this function.
|
|
@@ -375,73 +536,73 @@ export const claimOrder = decorator(async ({ chainId, userAddress, id, options,
|
|
|
375
536
|
* @param {CHAIN_IDS} chainId The chain ID.
|
|
376
537
|
* @param {`0x${string}`} userAddress The Ethereum address of the user.
|
|
377
538
|
* @param {string[]} ids An array of IDs representing the open orders to be claimed.
|
|
378
|
-
* @param {
|
|
379
|
-
* @param {string} [options.rpcUrl] The RPC URL to use for executing the transaction.
|
|
539
|
+
* @param options {@link DefaultOptions} options.
|
|
380
540
|
* @returns {Promise<{ transaction: Transaction, result: CurrencyFlow[] }>}
|
|
381
541
|
* Promise resolving to the transaction object representing the claim action with the result of the orders.
|
|
382
542
|
* @throws {Error} Throws an error if no open orders are found for the specified user.
|
|
383
543
|
* @example
|
|
384
544
|
* import { getOpenOrders, claimOrders } from '@clober/v2-sdk'
|
|
385
545
|
*
|
|
386
|
-
* const openOrders = await getOpenOrders(
|
|
387
|
-
* 421614,
|
|
388
|
-
*
|
|
389
|
-
* )
|
|
546
|
+
* const openOrders = await getOpenOrders({
|
|
547
|
+
* chainId: 421614,
|
|
548
|
+
* userAddress: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0'
|
|
549
|
+
* })
|
|
390
550
|
* const transaction = await claimOrders(
|
|
391
|
-
* 421614,
|
|
392
|
-
* '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
393
|
-
* openOrders.map((order) => order.id)
|
|
551
|
+
* chainId: 421614,
|
|
552
|
+
* userAddress: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
553
|
+
* ids: openOrders.map((order) => order.id)
|
|
394
554
|
* )
|
|
395
555
|
*/
|
|
396
|
-
export const claimOrders =
|
|
397
|
-
const
|
|
556
|
+
export const claimOrders = async ({ chainId, userAddress, ids, options, }) => {
|
|
557
|
+
const publicClient = createPublicClient({
|
|
558
|
+
chain: CHAIN_MAP[chainId],
|
|
559
|
+
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
|
|
560
|
+
});
|
|
561
|
+
const isApprovedForAll = await fetchIsApprovedForAll(publicClient, chainId, userAddress);
|
|
398
562
|
if (!isApprovedForAll) {
|
|
399
563
|
throw new Error(`
|
|
400
564
|
Set ApprovalForAll before calling this function.
|
|
401
565
|
import { setApprovalOfOpenOrdersForAll } from '@clober/v2-sdk'
|
|
402
566
|
|
|
403
|
-
const hash = await setApprovalOfOpenOrdersForAll(
|
|
404
|
-
${chainId},
|
|
405
|
-
|
|
406
|
-
)
|
|
567
|
+
const hash = await setApprovalOfOpenOrdersForAll({
|
|
568
|
+
chainId: ${chainId},
|
|
569
|
+
walletClient, // use viem
|
|
570
|
+
})
|
|
407
571
|
`);
|
|
408
572
|
}
|
|
409
|
-
const
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
}
|
|
413
|
-
const tokensToSettle = openOrders
|
|
414
|
-
.map((order) => [
|
|
415
|
-
order.outputCurrency.address,
|
|
416
|
-
order.inputCurrency.address,
|
|
417
|
-
])
|
|
573
|
+
const orders = (await fetchOrders(publicClient, chainId, ids.map((id) => BigInt(id)), !!(options && options.useSubgraph))).filter((order) => isAddressEqual(order.user, userAddress) && order.claimable.value !== '0');
|
|
574
|
+
const tokensToSettle = orders
|
|
575
|
+
.map((order) => [order.inputCurrency.address, order.outputCurrency.address])
|
|
418
576
|
.flat()
|
|
419
577
|
.filter((address, index, self) => self.findIndex((c) => isAddressEqual(c, address)) === index)
|
|
420
578
|
.filter((address) => !isAddressEqual(address, zeroAddress));
|
|
421
579
|
return {
|
|
422
|
-
transaction: await buildTransaction(
|
|
580
|
+
transaction: await buildTransaction(publicClient, {
|
|
423
581
|
chain: CHAIN_MAP[chainId],
|
|
424
582
|
account: userAddress,
|
|
425
583
|
address: CONTRACT_ADDRESSES[chainId].Controller,
|
|
426
584
|
abi: CONTROLLER_ABI,
|
|
427
585
|
functionName: 'claim',
|
|
428
586
|
args: [
|
|
429
|
-
|
|
430
|
-
id
|
|
587
|
+
orders.map(({ id }) => ({
|
|
588
|
+
id,
|
|
431
589
|
hookData: zeroHash,
|
|
432
590
|
})),
|
|
433
591
|
tokensToSettle,
|
|
434
592
|
[],
|
|
435
593
|
getDeadlineTimestampInSeconds(),
|
|
436
594
|
],
|
|
437
|
-
}),
|
|
438
|
-
result:
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
595
|
+
}, options?.gasLimit),
|
|
596
|
+
result: orders.reduce((acc, { claimable: { currency, value } }) => {
|
|
597
|
+
const index = acc.findIndex((c) => isAddressEqual(c.currency.address, currency.address));
|
|
598
|
+
if (index === -1) {
|
|
599
|
+
return [...acc, { currency, amount: value, direction: 'out' }];
|
|
600
|
+
}
|
|
601
|
+
acc[index].amount = (Number(acc[index].amount) + Number(value)).toString();
|
|
602
|
+
return acc;
|
|
603
|
+
}, []),
|
|
443
604
|
};
|
|
444
|
-
}
|
|
605
|
+
};
|
|
445
606
|
/**
|
|
446
607
|
* Cancels specified open order if the order is not fully filled.
|
|
447
608
|
* [IMPORTANT] Set ApprovalForAll before calling this function.
|
|
@@ -449,25 +610,24 @@ export const claimOrders = decorator(async ({ chainId, userAddress, ids, options
|
|
|
449
610
|
* @param {CHAIN_IDS} chainId The chain ID.
|
|
450
611
|
* @param {`0x${string}`} userAddress The Ethereum address of the user.
|
|
451
612
|
* @param {string} id An ID representing the open order to be canceled
|
|
452
|
-
* @param {
|
|
453
|
-
* @param {string} [options.rpcUrl] The RPC URL to use for executing the transaction.
|
|
613
|
+
* @param options {@link DefaultOptions} options.
|
|
454
614
|
* @returns {Promise<{ transaction: Transaction, result: CurrencyFlow }>}
|
|
455
615
|
* Promise resolving to the transaction object representing the cancel action with the result of the order.
|
|
456
616
|
* @throws {Error} Throws an error if no open orders are found for the specified user.
|
|
457
617
|
* @example
|
|
458
618
|
* import { getOpenOrders, cancelOrders } from '@clober/v2-sdk'
|
|
459
619
|
*
|
|
460
|
-
* const openOrders = await getOpenOrders(
|
|
461
|
-
* 421614,
|
|
462
|
-
*
|
|
463
|
-
* )
|
|
464
|
-
* const transaction = await cancelOrders(
|
|
465
|
-
* 421614,
|
|
466
|
-
* '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
467
|
-
* openOrders.map((order) => order.id)
|
|
468
|
-
* )
|
|
620
|
+
* const openOrders = await getOpenOrders({
|
|
621
|
+
* chainId: 421614,
|
|
622
|
+
* userAddress:'0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0'
|
|
623
|
+
* })
|
|
624
|
+
* const transaction = await cancelOrders({
|
|
625
|
+
* chainId: 421614,
|
|
626
|
+
* userAddress: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
627
|
+
* id: openOrders.map((order) => order.id)
|
|
628
|
+
* })
|
|
469
629
|
*/
|
|
470
|
-
export const cancelOrder =
|
|
630
|
+
export const cancelOrder = async ({ chainId, userAddress, id, options, }) => {
|
|
471
631
|
const { transaction, result } = await cancelOrders({
|
|
472
632
|
chainId,
|
|
473
633
|
userAddress,
|
|
@@ -478,7 +638,7 @@ export const cancelOrder = decorator(async ({ chainId, userAddress, id, options,
|
|
|
478
638
|
transaction,
|
|
479
639
|
result: result[0],
|
|
480
640
|
};
|
|
481
|
-
}
|
|
641
|
+
};
|
|
482
642
|
/**
|
|
483
643
|
* Cancels specified open orders if orders are not fully filled.
|
|
484
644
|
* [IMPORTANT] Set ApprovalForAll before calling this function.
|
|
@@ -486,59 +646,56 @@ export const cancelOrder = decorator(async ({ chainId, userAddress, id, options,
|
|
|
486
646
|
* @param {CHAIN_IDS} chainId The chain ID.
|
|
487
647
|
* @param {`0x${string}`} userAddress The Ethereum address of the user.
|
|
488
648
|
* @param {string[]} ids An array of IDs representing the open orders to be canceled.
|
|
489
|
-
* @param {
|
|
490
|
-
* @param {string} [options.rpcUrl] The RPC URL to use for executing the transaction.
|
|
649
|
+
* @param options {@link DefaultOptions} options.
|
|
491
650
|
* @returns {Promise<{ transaction: Transaction, result: CurrencyFlow[] }>
|
|
492
651
|
* Promise resolving to the transaction object representing the cancel action with the result of the orders.
|
|
493
652
|
* @throws {Error} Throws an error if no open orders are found for the specified user.
|
|
494
653
|
* @example
|
|
495
654
|
* import { getOpenOrders, cancelOrders } from '@clober/v2-sdk'
|
|
496
655
|
*
|
|
497
|
-
* const openOrders = await getOpenOrders(
|
|
498
|
-
* 421614,
|
|
499
|
-
*
|
|
500
|
-
* )
|
|
501
|
-
* const transaction = await cancelOrders(
|
|
502
|
-
* 421614,
|
|
503
|
-
* '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
504
|
-
* openOrders.map((order) => order.id)
|
|
505
|
-
* )
|
|
656
|
+
* const openOrders = await getOpenOrders({
|
|
657
|
+
* chainId: 421614,
|
|
658
|
+
* userAddress: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0'
|
|
659
|
+
* })
|
|
660
|
+
* const transaction = await cancelOrders({
|
|
661
|
+
* chainId: 421614,
|
|
662
|
+
* userAddress: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
663
|
+
* ids: openOrders.map((order) => order.id)
|
|
664
|
+
* })
|
|
506
665
|
*/
|
|
507
|
-
export const cancelOrders =
|
|
508
|
-
const
|
|
666
|
+
export const cancelOrders = async ({ chainId, userAddress, ids, options, }) => {
|
|
667
|
+
const publicClient = createPublicClient({
|
|
668
|
+
chain: CHAIN_MAP[chainId],
|
|
669
|
+
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
|
|
670
|
+
});
|
|
671
|
+
const isApprovedForAll = await fetchIsApprovedForAll(publicClient, chainId, userAddress);
|
|
509
672
|
if (!isApprovedForAll) {
|
|
510
673
|
throw new Error(`
|
|
511
674
|
Set ApprovalForAll before calling this function.
|
|
512
675
|
import { setApprovalOfOpenOrdersForAll } from '@clober/v2-sdk'
|
|
513
676
|
|
|
514
|
-
const hash = await setApprovalOfOpenOrdersForAll(
|
|
515
|
-
${chainId},
|
|
516
|
-
|
|
517
|
-
)
|
|
677
|
+
const hash = await setApprovalOfOpenOrdersForAll({
|
|
678
|
+
chainId: ${chainId},
|
|
679
|
+
walletClient, // use viem
|
|
680
|
+
})
|
|
518
681
|
`);
|
|
519
682
|
}
|
|
520
|
-
const
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
}
|
|
524
|
-
const tokensToSettle = openOrders
|
|
525
|
-
.map((order) => [
|
|
526
|
-
order.outputCurrency.address,
|
|
527
|
-
order.inputCurrency.address,
|
|
528
|
-
])
|
|
683
|
+
const orders = (await fetchOrders(publicClient, chainId, ids.map((id) => BigInt(id)), !!(options && options.useSubgraph))).filter((order) => isAddressEqual(order.user, userAddress) && order.cancelable.value !== '0');
|
|
684
|
+
const tokensToSettle = orders
|
|
685
|
+
.map((order) => [order.inputCurrency.address, order.outputCurrency.address])
|
|
529
686
|
.flat()
|
|
530
687
|
.filter((address, index, self) => self.findIndex((c) => isAddressEqual(c, address)) === index)
|
|
531
688
|
.filter((address) => !isAddressEqual(address, zeroAddress));
|
|
532
689
|
return {
|
|
533
|
-
transaction: await buildTransaction(
|
|
690
|
+
transaction: await buildTransaction(publicClient, {
|
|
534
691
|
chain: CHAIN_MAP[chainId],
|
|
535
692
|
account: userAddress,
|
|
536
693
|
address: CONTRACT_ADDRESSES[chainId].Controller,
|
|
537
694
|
abi: CONTROLLER_ABI,
|
|
538
695
|
functionName: 'cancel',
|
|
539
696
|
args: [
|
|
540
|
-
|
|
541
|
-
id
|
|
697
|
+
orders.map(({ id }) => ({
|
|
698
|
+
id,
|
|
542
699
|
leftQuoteAmount: 0n,
|
|
543
700
|
hookData: zeroHash,
|
|
544
701
|
})),
|
|
@@ -546,12 +703,379 @@ export const cancelOrders = decorator(async ({ chainId, userAddress, ids, option
|
|
|
546
703
|
[],
|
|
547
704
|
getDeadlineTimestampInSeconds(),
|
|
548
705
|
],
|
|
549
|
-
}),
|
|
550
|
-
result:
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
706
|
+
}, options?.gasLimit),
|
|
707
|
+
result: orders.reduce((acc, { cancelable: { currency, value } }) => {
|
|
708
|
+
const index = acc.findIndex((c) => isAddressEqual(c.currency.address, currency.address));
|
|
709
|
+
if (index === -1) {
|
|
710
|
+
return [...acc, { currency, amount: value, direction: 'out' }];
|
|
711
|
+
}
|
|
712
|
+
acc[index].amount = (Number(acc[index].amount) + Number(value)).toString();
|
|
713
|
+
return acc;
|
|
714
|
+
}, []),
|
|
715
|
+
};
|
|
716
|
+
};
|
|
717
|
+
/**
|
|
718
|
+
* Build a transaction to open a pool,
|
|
719
|
+
*
|
|
720
|
+
* @param chainId The chain ID of the blockchain.
|
|
721
|
+
* @param userAddress The address of the user.
|
|
722
|
+
* @param inputToken The address of the input token.
|
|
723
|
+
* @param outputToken The address of the output token.
|
|
724
|
+
* @param options {@link DefaultOptions} options.
|
|
725
|
+
* @returns A Promise resolving to a transaction object. If the market is already open, returns undefined.
|
|
726
|
+
* @example
|
|
727
|
+
* import { openPool } from '@clober/v2-sdk'
|
|
728
|
+
*
|
|
729
|
+
* const transaction = await openPool({
|
|
730
|
+
* chainId: 421614,
|
|
731
|
+
* userAddress: '0xF8c1869Ecd4df136693C45EcE1b67f85B6bDaE69',
|
|
732
|
+
* inputToken: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
|
|
733
|
+
* outputToken: '0x0000000000000000000000000000000000000000'
|
|
734
|
+
* })
|
|
735
|
+
*/
|
|
736
|
+
export const openPool = async ({ chainId, userAddress, tokenA, tokenB, salt, options, }) => {
|
|
737
|
+
const publicClient = createPublicClient({
|
|
738
|
+
chain: CHAIN_MAP[chainId],
|
|
739
|
+
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
|
|
740
|
+
});
|
|
741
|
+
const pool = await fetchPool(publicClient, chainId, [tokenA, tokenB], salt, !!(options && options.useSubgraph));
|
|
742
|
+
if (!pool.isOpened) {
|
|
743
|
+
return buildTransaction(publicClient, {
|
|
744
|
+
chain: CHAIN_MAP[chainId],
|
|
745
|
+
address: CONTRACT_ADDRESSES[chainId].Rebalancer,
|
|
746
|
+
account: userAddress,
|
|
747
|
+
abi: REBALANCER_ABI,
|
|
748
|
+
functionName: 'open',
|
|
749
|
+
args: [
|
|
750
|
+
{
|
|
751
|
+
base: pool.market.bidBook.base.address,
|
|
752
|
+
unitSize: pool.market.bidBook.unitSize,
|
|
753
|
+
quote: pool.market.bidBook.quote.address,
|
|
754
|
+
makerPolicy: MAKER_DEFAULT_POLICY[chainId].value,
|
|
755
|
+
hooks: zeroAddress,
|
|
756
|
+
takerPolicy: TAKER_DEFAULT_POLICY[chainId].value,
|
|
757
|
+
},
|
|
758
|
+
{
|
|
759
|
+
base: pool.market.askBook.base.address,
|
|
760
|
+
unitSize: pool.market.askBook.unitSize,
|
|
761
|
+
quote: pool.market.askBook.quote.address,
|
|
762
|
+
makerPolicy: MAKER_DEFAULT_POLICY[chainId].value,
|
|
763
|
+
hooks: zeroAddress,
|
|
764
|
+
takerPolicy: TAKER_DEFAULT_POLICY[chainId].value,
|
|
765
|
+
},
|
|
766
|
+
toBytes32(salt),
|
|
767
|
+
CONTRACT_ADDRESSES[chainId].Strategy,
|
|
768
|
+
],
|
|
769
|
+
}, options?.gasLimit);
|
|
770
|
+
}
|
|
771
|
+
return undefined;
|
|
772
|
+
};
|
|
773
|
+
export const addLiquidity = async ({ chainId, userAddress, token0, token1, salt, amount0, amount1, options, }) => {
|
|
774
|
+
const publicClient = createPublicClient({
|
|
775
|
+
chain: CHAIN_MAP[chainId],
|
|
776
|
+
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
|
|
777
|
+
});
|
|
778
|
+
const pool = await fetchPool(publicClient, chainId, [token0, token1], salt, !!(options && options.useSubgraph));
|
|
779
|
+
if (!pool.isOpened) {
|
|
780
|
+
throw new Error(`
|
|
781
|
+
Open the pool before adding liquidity.
|
|
782
|
+
import { openPool } from '@clober/v2-sdk'
|
|
783
|
+
|
|
784
|
+
const transaction = await openPool({
|
|
785
|
+
chainId: ${chainId},
|
|
786
|
+
tokenA: '${token0}',
|
|
787
|
+
tokenB: '${token1}',
|
|
788
|
+
})
|
|
789
|
+
`);
|
|
790
|
+
}
|
|
791
|
+
const [amountAOrigin, amountBOrigin] = isAddressEqual(pool.currencyA.address, getAddress(token0))
|
|
792
|
+
? [
|
|
793
|
+
parseUnits(amount0 ?? '0', pool.currencyA.decimals),
|
|
794
|
+
parseUnits(amount1 ?? '0', pool.currencyB.decimals),
|
|
795
|
+
]
|
|
796
|
+
: [
|
|
797
|
+
parseUnits(amount1 ?? '0', pool.currencyA.decimals),
|
|
798
|
+
parseUnits(amount0 ?? '0', pool.currencyB.decimals),
|
|
799
|
+
];
|
|
800
|
+
let [amountA, amountB] = [amountAOrigin, amountBOrigin];
|
|
801
|
+
const tokenAPermitParams = isAddressEqual(pool.currencyA.address, getAddress(token0))
|
|
802
|
+
? options?.token0PermitParams ?? emptyERC20PermitParams
|
|
803
|
+
: options?.token1PermitParams ?? emptyERC20PermitParams;
|
|
804
|
+
const tokenBPermitParams = isAddressEqual(pool.currencyA.address, getAddress(token0))
|
|
805
|
+
? options?.token1PermitParams ?? emptyERC20PermitParams
|
|
806
|
+
: options?.token0PermitParams ?? emptyERC20PermitParams;
|
|
807
|
+
let disableSwap = !!(options && options.disableSwap);
|
|
808
|
+
if (pool.totalSupply === 0n ||
|
|
809
|
+
(pool.liquidityA === 0n && pool.liquidityB === 0n)) {
|
|
810
|
+
disableSwap = true;
|
|
811
|
+
}
|
|
812
|
+
const slippageLimitPercent = options?.slippage ?? 2;
|
|
813
|
+
const swapParams = {
|
|
814
|
+
inCurrency: zeroAddress,
|
|
815
|
+
amount: 0n,
|
|
816
|
+
data: '0x',
|
|
817
|
+
};
|
|
818
|
+
if (!disableSwap) {
|
|
819
|
+
const token0Price = Number(options?.testnetPrice ? options.testnetPrice : '1');
|
|
820
|
+
const currencyBPerCurrencyA = isAddressEqual(token1, pool.currencyB.address)
|
|
821
|
+
? token0Price
|
|
822
|
+
: 1 / token0Price;
|
|
823
|
+
const swapAmountA = parseUnits('1', pool.currencyA.decimals);
|
|
824
|
+
const { amountOut: swapAmountB } = await fetchQuote({
|
|
825
|
+
chainId,
|
|
826
|
+
amountIn: swapAmountA,
|
|
827
|
+
tokenIn: pool.currencyA,
|
|
828
|
+
tokenOut: pool.currencyB,
|
|
829
|
+
slippageLimitPercent: 20,
|
|
830
|
+
userAddress: CONTRACT_ADDRESSES[chainId].Minter,
|
|
831
|
+
testnetPrice: currencyBPerCurrencyA,
|
|
832
|
+
});
|
|
833
|
+
const { deltaA, deltaB } = getIdealDelta(amountA, amountB, pool.liquidityA, pool.liquidityB, swapAmountA, swapAmountB);
|
|
834
|
+
if (deltaA < 0n) {
|
|
835
|
+
swapParams.inCurrency = pool.currencyA.address;
|
|
836
|
+
swapParams.amount = -deltaA;
|
|
837
|
+
const { amountOut: actualDeltaB, data: calldata } = await fetchCallData({
|
|
838
|
+
chainId,
|
|
839
|
+
amountIn: swapParams.amount,
|
|
840
|
+
tokenIn: pool.currencyA,
|
|
841
|
+
tokenOut: pool.currencyB,
|
|
842
|
+
slippageLimitPercent,
|
|
843
|
+
userAddress: CONTRACT_ADDRESSES[chainId].Minter,
|
|
844
|
+
testnetPrice: currencyBPerCurrencyA,
|
|
845
|
+
});
|
|
846
|
+
swapParams.data = calldata;
|
|
847
|
+
amountA += deltaA;
|
|
848
|
+
amountB += actualDeltaB;
|
|
849
|
+
}
|
|
850
|
+
else if (deltaB < 0n) {
|
|
851
|
+
swapParams.inCurrency = pool.currencyB.address;
|
|
852
|
+
swapParams.amount = -deltaB;
|
|
853
|
+
const { amountOut: actualDeltaA, data: calldata } = await fetchCallData({
|
|
854
|
+
chainId,
|
|
855
|
+
amountIn: swapParams.amount,
|
|
856
|
+
tokenIn: pool.currencyB,
|
|
857
|
+
tokenOut: pool.currencyA,
|
|
858
|
+
slippageLimitPercent,
|
|
859
|
+
userAddress: CONTRACT_ADDRESSES[chainId].Minter,
|
|
860
|
+
testnetPrice: 1 / currencyBPerCurrencyA,
|
|
861
|
+
});
|
|
862
|
+
swapParams.data = calldata;
|
|
863
|
+
amountA += actualDeltaA;
|
|
864
|
+
amountB += deltaB;
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
const { mintAmount, inAmountA, inAmountB } = getExpectedMintResult(pool.totalSupply, pool.liquidityA, pool.liquidityB, amountA, amountB, pool.currencyA, pool.currencyB);
|
|
868
|
+
if (mintAmount === 0n) {
|
|
869
|
+
return {
|
|
870
|
+
transaction: undefined,
|
|
871
|
+
result: {
|
|
872
|
+
currencyA: {
|
|
873
|
+
currency: pool.currencyA,
|
|
874
|
+
amount: '0',
|
|
875
|
+
direction: 'in',
|
|
876
|
+
},
|
|
877
|
+
currencyB: {
|
|
878
|
+
currency: pool.currencyB,
|
|
879
|
+
amount: '0',
|
|
880
|
+
direction: 'in',
|
|
881
|
+
},
|
|
882
|
+
lpCurrency: {
|
|
883
|
+
currency: pool.currencyLp,
|
|
884
|
+
amount: '0',
|
|
885
|
+
direction: 'out',
|
|
886
|
+
},
|
|
887
|
+
},
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
const minMintAmount = applyPercent(mintAmount, 100 - slippageLimitPercent);
|
|
891
|
+
const transaction = await buildTransaction(publicClient, {
|
|
892
|
+
chain: CHAIN_MAP[chainId],
|
|
893
|
+
account: userAddress,
|
|
894
|
+
address: CONTRACT_ADDRESSES[chainId].Minter,
|
|
895
|
+
abi: MINTER_ABI,
|
|
896
|
+
functionName: 'mint',
|
|
897
|
+
args: [
|
|
898
|
+
pool.key,
|
|
899
|
+
amountAOrigin,
|
|
900
|
+
amountBOrigin,
|
|
901
|
+
minMintAmount,
|
|
902
|
+
{
|
|
903
|
+
permitAmount: tokenAPermitParams.permitAmount,
|
|
904
|
+
signature: tokenAPermitParams.signature,
|
|
905
|
+
},
|
|
906
|
+
{
|
|
907
|
+
permitAmount: tokenBPermitParams.permitAmount,
|
|
908
|
+
signature: tokenBPermitParams.signature,
|
|
909
|
+
},
|
|
910
|
+
swapParams,
|
|
911
|
+
],
|
|
912
|
+
}, options?.gasLimit);
|
|
913
|
+
const currencyARefund = amountA - inAmountA;
|
|
914
|
+
const currencyBRefund = amountB - inAmountB;
|
|
915
|
+
const currencyAResultAmount = amountAOrigin - currencyARefund;
|
|
916
|
+
const currencyBResultAmount = amountBOrigin - currencyBRefund;
|
|
917
|
+
return {
|
|
918
|
+
transaction,
|
|
919
|
+
result: {
|
|
920
|
+
currencyA: {
|
|
921
|
+
currency: pool.currencyA,
|
|
922
|
+
amount: formatUnits(abs(currencyAResultAmount), pool.currencyA.decimals),
|
|
923
|
+
direction: currencyAResultAmount >= 0 ? 'in' : 'out',
|
|
924
|
+
},
|
|
925
|
+
currencyB: {
|
|
926
|
+
currency: pool.currencyB,
|
|
927
|
+
amount: formatUnits(abs(currencyBResultAmount), pool.currencyB.decimals),
|
|
928
|
+
direction: currencyBResultAmount >= 0 ? 'in' : 'out',
|
|
929
|
+
},
|
|
930
|
+
lpCurrency: {
|
|
931
|
+
currency: pool.currencyLp,
|
|
932
|
+
amount: formatUnits(mintAmount, pool.currencyLp.decimals),
|
|
933
|
+
direction: 'out',
|
|
934
|
+
},
|
|
935
|
+
},
|
|
555
936
|
};
|
|
556
|
-
}
|
|
937
|
+
};
|
|
938
|
+
// @dev: Withdraw amount calculation logic is based on the contract code.
|
|
939
|
+
export const removeLiquidity = async ({ chainId, userAddress, token0, token1, salt, amount, options, }) => {
|
|
940
|
+
const publicClient = createPublicClient({
|
|
941
|
+
chain: CHAIN_MAP[chainId],
|
|
942
|
+
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
|
|
943
|
+
});
|
|
944
|
+
const pool = await fetchPool(publicClient, chainId, [token0, token1], salt, !!(options && options.useSubgraph));
|
|
945
|
+
if (!pool.isOpened) {
|
|
946
|
+
throw new Error(`
|
|
947
|
+
Open the pool before removing liquidity.
|
|
948
|
+
import { openPool } from '@clober/v2-sdk'
|
|
949
|
+
|
|
950
|
+
const transaction = await openPool({
|
|
951
|
+
chainId: ${chainId},
|
|
952
|
+
tokenA: '${token0}',
|
|
953
|
+
tokenB: '${token1}',
|
|
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 rebalance = 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 = await fetchPool(publicClient, chainId, [token0, token1], salt, !!(options && options.useSubgraph));
|
|
1020
|
+
if (!pool.isOpened) {
|
|
1021
|
+
throw new Error(`
|
|
1022
|
+
Open the pool before rebalancing pool.
|
|
1023
|
+
import { openPool } from '@clober/v2-sdk'
|
|
1024
|
+
|
|
1025
|
+
const transaction = await openPool({
|
|
1026
|
+
chainId: ${chainId},
|
|
1027
|
+
tokenA: '${token0}',
|
|
1028
|
+
tokenB: '${token1}',
|
|
1029
|
+
})
|
|
1030
|
+
`);
|
|
1031
|
+
}
|
|
1032
|
+
return buildTransaction(publicClient, {
|
|
1033
|
+
chain: CHAIN_MAP[chainId],
|
|
1034
|
+
account: userAddress,
|
|
1035
|
+
address: CONTRACT_ADDRESSES[chainId].Rebalancer,
|
|
1036
|
+
abi: REBALANCER_ABI,
|
|
1037
|
+
functionName: 'rebalance',
|
|
1038
|
+
args: [pool.key],
|
|
1039
|
+
}, options?.gasLimit);
|
|
1040
|
+
};
|
|
1041
|
+
export const updateStrategyPrice = async ({ chainId, userAddress, token0, token1, salt, oraclePrice, priceA, priceB, options, }) => {
|
|
1042
|
+
const publicClient = createPublicClient({
|
|
1043
|
+
chain: CHAIN_MAP[chainId],
|
|
1044
|
+
transport: options?.rpcUrl ? http(options.rpcUrl) : http(),
|
|
1045
|
+
});
|
|
1046
|
+
const pool = await fetchPool(publicClient, chainId, [token0, token1], salt, !!(options && options.useSubgraph));
|
|
1047
|
+
if (!pool.isOpened) {
|
|
1048
|
+
throw new Error(`
|
|
1049
|
+
Open the pool before updating strategy price.
|
|
1050
|
+
import { openPool } from '@clober/v2-sdk'
|
|
1051
|
+
|
|
1052
|
+
const transaction = await openPool({
|
|
1053
|
+
chainId: ${chainId},
|
|
1054
|
+
tokenA: '${token0}',
|
|
1055
|
+
tokenB: '${token1}',
|
|
1056
|
+
})
|
|
1057
|
+
`);
|
|
1058
|
+
}
|
|
1059
|
+
const [roundingUpPriceA, roundingUpPriceB] = [
|
|
1060
|
+
options?.roundingUpPriceA ? options.roundingUpPriceA : false,
|
|
1061
|
+
options?.roundingUpPriceB ? options.roundingUpPriceB : false,
|
|
1062
|
+
];
|
|
1063
|
+
const { roundingDownTick: roundingDownTickA, roundingUpTick: roundingUpTickA, } = parsePrice(Number(priceA), pool.currencyA.decimals, pool.currencyB.decimals);
|
|
1064
|
+
const { roundingDownTick: roundingDownTickB, roundingUpTick: roundingUpTickB, } = parsePrice(Number(priceB), pool.currencyA.decimals, pool.currencyB.decimals);
|
|
1065
|
+
const oracleRawPrice = convertHumanReadablePriceToRawPrice(Number(oraclePrice), pool.currencyA.decimals, pool.currencyB.decimals);
|
|
1066
|
+
const tickA = options?.tickA
|
|
1067
|
+
? Number(options.tickA)
|
|
1068
|
+
: Number(roundingUpPriceA ? roundingUpTickA : roundingDownTickA);
|
|
1069
|
+
const tickB = options?.tickB
|
|
1070
|
+
? Number(options.tickB)
|
|
1071
|
+
: Number(invertTick(roundingUpPriceB ? roundingUpTickB : roundingDownTickB));
|
|
1072
|
+
return buildTransaction(publicClient, {
|
|
1073
|
+
chain: CHAIN_MAP[chainId],
|
|
1074
|
+
account: userAddress,
|
|
1075
|
+
address: CONTRACT_ADDRESSES[chainId].Operator,
|
|
1076
|
+
abi: OPERATOR_ABI,
|
|
1077
|
+
functionName: 'updatePrice',
|
|
1078
|
+
args: [pool.key, oracleRawPrice, tickA, tickB],
|
|
1079
|
+
}, options?.gasLimit);
|
|
1080
|
+
};
|
|
557
1081
|
//# sourceMappingURL=call.js.map
|