@clober/v2-sdk 0.0.4 → 0.0.5-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.
Files changed (238) hide show
  1. package/README.md +12 -4
  2. package/dist/cjs/abis/core/book-manager-abi.js +112 -0
  3. package/dist/cjs/abis/core/book-manager-abi.js.map +1 -0
  4. package/dist/cjs/abis/core/book-viewer-abi.js +321 -0
  5. package/dist/cjs/abis/core/book-viewer-abi.js.map +1 -0
  6. package/dist/cjs/abis/core/controller-abi.js +29 -24
  7. package/dist/cjs/abis/core/controller-abi.js.map +1 -1
  8. package/dist/cjs/apis/chart-logs.js +154 -0
  9. package/dist/cjs/apis/chart-logs.js.map +1 -0
  10. package/dist/cjs/apis/market.js +61 -32
  11. package/dist/cjs/apis/market.js.map +1 -1
  12. package/dist/cjs/apis/open-order.js +56 -21
  13. package/dist/cjs/apis/open-order.js.map +1 -1
  14. package/dist/cjs/approval.js +77 -30
  15. package/dist/cjs/approval.js.map +1 -1
  16. package/dist/cjs/call.js +313 -206
  17. package/dist/cjs/call.js.map +1 -1
  18. package/dist/cjs/constants/addresses.js +26 -1
  19. package/dist/cjs/constants/addresses.js.map +1 -1
  20. package/dist/cjs/constants/chain.js +19 -1
  21. package/dist/cjs/constants/chain.js.map +1 -1
  22. package/dist/cjs/constants/client.js +4 -0
  23. package/dist/cjs/constants/client.js.map +1 -1
  24. package/dist/cjs/constants/currency.js +28 -2
  25. package/dist/cjs/constants/currency.js.map +1 -1
  26. package/dist/cjs/constants/fee.js +17 -2
  27. package/dist/cjs/constants/fee.js.map +1 -1
  28. package/dist/cjs/constants/subgraph.js +57 -0
  29. package/dist/cjs/constants/subgraph.js.map +1 -0
  30. package/dist/cjs/constants/test-chain.js +27 -0
  31. package/dist/cjs/constants/test-chain.js.map +1 -0
  32. package/dist/cjs/index.js +20 -6
  33. package/dist/cjs/index.js.map +1 -1
  34. package/dist/cjs/model/book.js +47 -29
  35. package/dist/cjs/model/book.js.map +1 -1
  36. package/dist/cjs/model/chart-log.js +3 -0
  37. package/dist/cjs/model/chart-log.js.map +1 -0
  38. package/dist/cjs/model/market.js +45 -182
  39. package/dist/cjs/model/market.js.map +1 -1
  40. package/dist/cjs/signature.js +20 -16
  41. package/dist/cjs/signature.js.map +1 -1
  42. package/dist/cjs/type.js +16 -1
  43. package/dist/cjs/type.js.map +1 -1
  44. package/dist/cjs/utils/allowance.js +40 -0
  45. package/dist/cjs/utils/allowance.js.map +1 -0
  46. package/dist/cjs/utils/bigint.js +9 -0
  47. package/dist/cjs/utils/bigint.js.map +1 -0
  48. package/dist/cjs/utils/bignumber.js +9 -0
  49. package/dist/cjs/utils/bignumber.js.map +1 -0
  50. package/dist/cjs/utils/book-id.js +7 -7
  51. package/dist/cjs/utils/book-id.js.map +1 -1
  52. package/dist/cjs/utils/build-transaction.js +8 -7
  53. package/dist/cjs/utils/build-transaction.js.map +1 -1
  54. package/dist/cjs/utils/currency.js +166 -0
  55. package/dist/cjs/utils/currency.js.map +1 -0
  56. package/dist/cjs/utils/decorator.js +3 -1
  57. package/dist/cjs/utils/decorator.js.map +1 -1
  58. package/dist/cjs/utils/open.js +36 -0
  59. package/dist/cjs/utils/open.js.map +1 -0
  60. package/dist/cjs/utils/order.js +102 -0
  61. package/dist/cjs/utils/order.js.map +1 -0
  62. package/dist/cjs/utils/prices.js +25 -3
  63. package/dist/cjs/utils/prices.js.map +1 -1
  64. package/dist/cjs/utils/unit-size.js +49 -0
  65. package/dist/cjs/utils/unit-size.js.map +1 -0
  66. package/dist/cjs/utils.js +15 -0
  67. package/dist/cjs/utils.js.map +1 -0
  68. package/dist/cjs/view.js +102 -33
  69. package/dist/cjs/view.js.map +1 -1
  70. package/dist/esm/abis/core/book-manager-abi.js +109 -0
  71. package/dist/esm/abis/core/book-manager-abi.js.map +1 -0
  72. package/dist/esm/abis/core/book-viewer-abi.js +318 -0
  73. package/dist/esm/abis/core/book-viewer-abi.js.map +1 -0
  74. package/dist/esm/abis/core/controller-abi.js +29 -24
  75. package/dist/esm/abis/core/controller-abi.js.map +1 -1
  76. package/dist/esm/apis/chart-logs.js +150 -0
  77. package/dist/esm/apis/chart-logs.js.map +1 -0
  78. package/dist/esm/apis/market.js +61 -32
  79. package/dist/esm/apis/market.js.map +1 -1
  80. package/dist/esm/apis/open-order.js +57 -21
  81. package/dist/esm/apis/open-order.js.map +1 -1
  82. package/dist/esm/approval.js +116 -44
  83. package/dist/esm/approval.js.map +1 -1
  84. package/dist/esm/call.js +430 -309
  85. package/dist/esm/call.js.map +1 -1
  86. package/dist/esm/constants/addresses.js +26 -1
  87. package/dist/esm/constants/addresses.js.map +1 -1
  88. package/dist/esm/constants/chain.js +20 -2
  89. package/dist/esm/constants/chain.js.map +1 -1
  90. package/dist/esm/constants/client.js +5 -1
  91. package/dist/esm/constants/client.js.map +1 -1
  92. package/dist/esm/constants/currency.js +28 -2
  93. package/dist/esm/constants/currency.js.map +1 -1
  94. package/dist/esm/constants/fee.js +17 -2
  95. package/dist/esm/constants/fee.js.map +1 -1
  96. package/dist/esm/constants/subgraph.js +53 -0
  97. package/dist/esm/constants/subgraph.js.map +1 -0
  98. package/dist/esm/constants/test-chain.js +24 -0
  99. package/dist/esm/constants/test-chain.js.map +1 -0
  100. package/dist/esm/index.js +1 -0
  101. package/dist/esm/index.js.map +1 -1
  102. package/dist/esm/model/book.js +47 -29
  103. package/dist/esm/model/book.js.map +1 -1
  104. package/dist/esm/model/chart-log.js +2 -0
  105. package/dist/esm/model/chart-log.js.map +1 -0
  106. package/dist/esm/model/market.js +46 -187
  107. package/dist/esm/model/market.js.map +1 -1
  108. package/dist/esm/signature.js +35 -37
  109. package/dist/esm/signature.js.map +1 -1
  110. package/dist/esm/type.js +15 -0
  111. package/dist/esm/type.js.map +1 -1
  112. package/dist/esm/utils/allowance.js +36 -0
  113. package/dist/esm/utils/allowance.js.map +1 -0
  114. package/dist/esm/utils/bigint.js +5 -0
  115. package/dist/esm/utils/bigint.js.map +1 -0
  116. package/dist/esm/utils/bignumber.js +6 -0
  117. package/dist/esm/utils/bignumber.js.map +1 -0
  118. package/dist/esm/utils/book-id.js +7 -7
  119. package/dist/esm/utils/book-id.js.map +1 -1
  120. package/dist/esm/utils/build-transaction.js +8 -7
  121. package/dist/esm/utils/build-transaction.js.map +1 -1
  122. package/dist/esm/utils/currency.js +161 -0
  123. package/dist/esm/utils/currency.js.map +1 -0
  124. package/dist/esm/utils/decorator.js +3 -1
  125. package/dist/esm/utils/decorator.js.map +1 -1
  126. package/dist/esm/utils/open.js +32 -0
  127. package/dist/esm/utils/open.js.map +1 -0
  128. package/dist/esm/utils/order.js +98 -0
  129. package/dist/esm/utils/order.js.map +1 -0
  130. package/dist/esm/utils/prices.js +24 -2
  131. package/dist/esm/utils/prices.js.map +1 -1
  132. package/dist/esm/utils/unit-size.js +45 -0
  133. package/dist/esm/utils/unit-size.js.map +1 -0
  134. package/dist/esm/utils.js +4 -0
  135. package/dist/esm/utils.js.map +1 -0
  136. package/dist/esm/view.js +215 -61
  137. package/dist/esm/view.js.map +1 -1
  138. package/dist/tsconfig.build.tsbuildinfo +1 -1
  139. package/dist/types/abis/core/book-manager-abi.d.ts +82 -0
  140. package/dist/types/abis/core/book-manager-abi.d.ts.map +1 -0
  141. package/dist/types/abis/core/book-viewer-abi.d.ts +243 -0
  142. package/dist/types/abis/core/book-viewer-abi.d.ts.map +1 -0
  143. package/dist/types/abis/core/controller-abi.d.ts +23 -19
  144. package/dist/types/abis/core/controller-abi.d.ts.map +1 -1
  145. package/dist/types/apis/chart-logs.d.ts +5 -0
  146. package/dist/types/apis/chart-logs.d.ts.map +1 -0
  147. package/dist/types/apis/market.d.ts +1 -1
  148. package/dist/types/apis/market.d.ts.map +1 -1
  149. package/dist/types/apis/open-order.d.ts +3 -2
  150. package/dist/types/apis/open-order.d.ts.map +1 -1
  151. package/dist/types/approval.d.ts +48 -16
  152. package/dist/types/approval.d.ts.map +1 -1
  153. package/dist/types/call.d.ts +151 -109
  154. package/dist/types/call.d.ts.map +1 -1
  155. package/dist/types/constants/addresses.d.ts.map +1 -1
  156. package/dist/types/constants/chain.d.ts +6 -2
  157. package/dist/types/constants/chain.d.ts.map +1 -1
  158. package/dist/types/constants/client.d.ts +1 -1
  159. package/dist/types/constants/client.d.ts.map +1 -1
  160. package/dist/types/constants/currency.d.ts.map +1 -1
  161. package/dist/types/constants/fee.d.ts +7 -2
  162. package/dist/types/constants/fee.d.ts.map +1 -1
  163. package/dist/types/constants/subgraph.d.ts +10 -0
  164. package/dist/types/constants/subgraph.d.ts.map +1 -0
  165. package/dist/types/constants/test-chain.d.ts +3 -0
  166. package/dist/types/constants/test-chain.d.ts.map +1 -0
  167. package/dist/types/index.d.ts +1 -0
  168. package/dist/types/index.d.ts.map +1 -1
  169. package/dist/types/model/book.d.ts +13 -29
  170. package/dist/types/model/book.d.ts.map +1 -1
  171. package/dist/types/model/chart-log.d.ts +9 -0
  172. package/dist/types/model/chart-log.d.ts.map +1 -0
  173. package/dist/types/model/depth.d.ts +4 -5
  174. package/dist/types/model/depth.d.ts.map +1 -1
  175. package/dist/types/model/market.d.ts +15 -19
  176. package/dist/types/model/market.d.ts.map +1 -1
  177. package/dist/types/model/open-order.d.ts +16 -8
  178. package/dist/types/model/open-order.d.ts.map +1 -1
  179. package/dist/types/signature.d.ts +18 -24
  180. package/dist/types/signature.d.ts.map +1 -1
  181. package/dist/types/type.d.ts +52 -8
  182. package/dist/types/type.d.ts.map +1 -1
  183. package/dist/types/utils/allowance.d.ts +3 -0
  184. package/dist/types/utils/allowance.d.ts.map +1 -0
  185. package/dist/types/utils/bigint.d.ts +2 -0
  186. package/dist/types/utils/bigint.d.ts.map +1 -0
  187. package/dist/types/utils/bignumber.d.ts +3 -0
  188. package/dist/types/utils/bignumber.d.ts.map +1 -0
  189. package/dist/types/utils/book-id.d.ts +2 -1
  190. package/dist/types/utils/book-id.d.ts.map +1 -1
  191. package/dist/types/utils/build-transaction.d.ts +3 -3
  192. package/dist/types/utils/build-transaction.d.ts.map +1 -1
  193. package/dist/types/{apis → utils}/currency.d.ts +3 -0
  194. package/dist/types/utils/currency.d.ts.map +1 -0
  195. package/dist/types/utils/decorator.d.ts +1 -1
  196. package/dist/types/utils/decorator.d.ts.map +1 -1
  197. package/dist/types/utils/open.d.ts +3 -0
  198. package/dist/types/utils/open.d.ts.map +1 -0
  199. package/dist/types/utils/order.d.ts +8 -0
  200. package/dist/types/utils/order.d.ts.map +1 -0
  201. package/dist/types/utils/prices.d.ts +8 -1
  202. package/dist/types/utils/prices.d.ts.map +1 -1
  203. package/dist/types/utils/unit-size.d.ts +4 -0
  204. package/dist/types/utils/unit-size.d.ts.map +1 -0
  205. package/dist/types/utils.d.ts +4 -0
  206. package/dist/types/utils.d.ts.map +1 -0
  207. package/dist/types/view.d.ts +184 -41
  208. package/dist/types/view.d.ts.map +1 -1
  209. package/package.json +1 -1
  210. package/dist/cjs/abis/core/params-abi.js +0 -62
  211. package/dist/cjs/abis/core/params-abi.js.map +0 -1
  212. package/dist/cjs/apis/currency.js +0 -83
  213. package/dist/cjs/apis/currency.js.map +0 -1
  214. package/dist/cjs/apis/subgraph.js +0 -26
  215. package/dist/cjs/apis/subgraph.js.map +0 -1
  216. package/dist/cjs/constants/subgraph-url.js +0 -8
  217. package/dist/cjs/constants/subgraph-url.js.map +0 -1
  218. package/dist/cjs/utils/unit.js +0 -34
  219. package/dist/cjs/utils/unit.js.map +0 -1
  220. package/dist/esm/abis/core/params-abi.js +0 -59
  221. package/dist/esm/abis/core/params-abi.js.map +0 -1
  222. package/dist/esm/apis/currency.js +0 -79
  223. package/dist/esm/apis/currency.js.map +0 -1
  224. package/dist/esm/apis/subgraph.js +0 -22
  225. package/dist/esm/apis/subgraph.js.map +0 -1
  226. package/dist/esm/constants/subgraph-url.js +0 -5
  227. package/dist/esm/constants/subgraph-url.js.map +0 -1
  228. package/dist/esm/utils/unit.js +0 -30
  229. package/dist/esm/utils/unit.js.map +0 -1
  230. package/dist/types/abis/core/params-abi.d.ts +0 -21
  231. package/dist/types/abis/core/params-abi.d.ts.map +0 -1
  232. package/dist/types/apis/currency.d.ts.map +0 -1
  233. package/dist/types/apis/subgraph.d.ts +0 -3
  234. package/dist/types/apis/subgraph.d.ts.map +0 -1
  235. package/dist/types/constants/subgraph-url.d.ts +0 -5
  236. package/dist/types/constants/subgraph-url.d.ts.map +0 -1
  237. package/dist/types/utils/unit.d.ts +0 -4
  238. package/dist/types/utils/unit.d.ts.map +0 -1
package/dist/esm/call.js CHANGED
@@ -1,6 +1,6 @@
1
- import { encodeAbiParameters, isAddressEqual, parseUnits, zeroAddress, zeroHash, } from 'viem';
1
+ import { formatUnits, isAddressEqual, parseUnits, zeroAddress, zeroHash, } from 'viem';
2
2
  import { CHAIN_MAP } from './constants/chain';
3
- import { calculateUnit } from './utils/unit';
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';
@@ -8,17 +8,18 @@ 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
10
  import { parsePrice } from './utils/prices';
11
- import { fromPrice, invertPrice } from './utils/tick';
12
- import { getExpectedOutput, getOpenOrders } from './view';
11
+ import { fromPrice, invertPrice, toPrice } from './utils/tick';
12
+ import { getExpectedInput, getExpectedOutput } from './view';
13
13
  import { toBookId } from './utils/book-id';
14
- import { MAKE_ORDER_PARAMS_ABI, TAKE_ORDER_PARAMS_ABI, } from './abis/core/params-abi';
15
- import { Action } from './constants/action';
16
14
  import { fetchIsApprovedForAll } from './utils/approval';
17
15
  import { decorator } from './utils/decorator';
16
+ import { fetchOrders } from './utils/order';
17
+ import { applyPercent } from './utils/bigint';
18
18
  /**
19
19
  * Build a transaction to open a market.
20
20
  *
21
21
  * @param chainId The chain ID of the blockchain.
22
+ * @param userAddress The address of the user.
22
23
  * @param inputToken The address of the input token.
23
24
  * @param outputToken The address of the output token.
24
25
  * @param options
@@ -27,38 +28,42 @@ import { decorator } from './utils/decorator';
27
28
  * @example
28
29
  * import { openMarket } from '@clober/v2-sdk'
29
30
  *
30
- * const transaction = await openMarket(
31
- * 421614,
32
- * '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
33
- * '0x0000000000000000000000000000000000000000'
34
- * )
31
+ * const transaction = await openMarket({
32
+ * chainId: 421614,
33
+ * userAddress: '0xF8c1869Ecd4df136693C45EcE1b67f85B6bDaE69',
34
+ * inputToken: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
35
+ * outputToken: '0x0000000000000000000000000000000000000000'
36
+ * })
35
37
  */
36
- export const openMarket = decorator(async ({ chainId, inputToken, outputToken, }) => {
38
+ export const openMarket = decorator(async ({ chainId, userAddress, inputToken, outputToken, options, }) => {
37
39
  const market = await fetchMarket(chainId, [inputToken, outputToken]);
38
40
  const isBid = isAddressEqual(market.quote.address, inputToken);
39
- if ((isBid && !market.bidBookOpen) || (!isBid && !market.askBookOpen)) {
40
- const unit = await calculateUnit(chainId, isBid ? market.quote : market.base);
41
+ if ((isBid && !market.bidBook.isOpened) ||
42
+ (!isBid && !market.askBook.isOpened)) {
43
+ const unitSize = await calculateUnitSize(chainId, isBid ? market.quote : market.base);
41
44
  return buildTransaction(chainId, {
45
+ chain: CHAIN_MAP[chainId],
42
46
  address: CONTRACT_ADDRESSES[chainId].Controller,
47
+ account: userAddress,
43
48
  abi: CONTROLLER_ABI,
44
49
  functionName: 'open',
45
50
  args: [
46
51
  [
47
52
  {
48
53
  key: {
49
- base: inputToken,
50
- unit,
51
- quote: outputToken,
52
- makerPolicy: MAKER_DEFAULT_POLICY.value,
54
+ base: outputToken,
55
+ unitSize,
56
+ quote: inputToken,
57
+ makerPolicy: MAKER_DEFAULT_POLICY[chainId].value,
53
58
  hooks: zeroAddress,
54
- takerPolicy: TAKER_DEFAULT_POLICY.value,
59
+ takerPolicy: TAKER_DEFAULT_POLICY[chainId].value,
55
60
  },
56
61
  hookData: zeroHash,
57
62
  },
58
63
  ],
59
64
  getDeadlineTimestampInSeconds(),
60
65
  ],
61
- });
66
+ }, options?.gasLimit);
62
67
  }
63
68
  return undefined;
64
69
  });
@@ -72,63 +77,70 @@ export const openMarket = decorator(async ({ chainId, inputToken, outputToken, }
72
77
  * @param {string} amount The amount of input tokens for the order.
73
78
  * @param {string} price The price at which the order should be executed.
74
79
  * @param {Object} [options] Optional parameters for the limit order.
75
- * @param {PermitSignature} [options.signature] The permit signature for token approval.
80
+ * @param {erc20PermitParam} [options.erc20PermitParam] The permit signature for token approval.
76
81
  * @param {boolean} [options.postOnly] A boolean indicating whether the order is only to be made not taken.
77
82
  * @param {string} [options.rpcUrl] The RPC URL of the blockchain.
78
- * @returns {Promise<Transaction>} Promise resolving to the transaction object representing the limit order.
83
+ * @param {number} [options.gasLimit] The gas limit to use for the transaction.
84
+ * @param {boolean} [options.useSubgraph] A boolean indicating whether to use the subgraph for fetching orders.
85
+ * @returns {Promise<{ transaction: Transaction, result: { make: CurrencyFlow, take: CurrencyFlow, spent: CurrencyFlow }>}
86
+ * Promise resolving to the transaction object representing the limit order with the result of the order.
79
87
  * @example
80
88
  * import { signERC20Permit, limitOrder } from '@clober/v2-sdk'
81
89
  * import { privateKeyToAccount } from 'viem/accounts'
82
90
  *
83
- * const signature = await signERC20Permit(
84
- * 421614,
85
- * privateKeyToAccount('0x...'),
86
- * '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
87
- * '100.123'
88
- * )
91
+ * const erc20PermitParam = await signERC20Permit({
92
+ * chainId: 421614,
93
+ * walletClient,
94
+ * token: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
95
+ * amount: '100.123'
96
+ * })
89
97
  *
90
- * const transaction = await limitOrder(
91
- * 421614,
92
- * '0xF8c1869Ecd4df136693C45EcE1b67f85B6bDaE69
93
- * '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
94
- * '0x0000000000000000000000000000000000000000',
95
- * '100.123', // 100.123 USDC
96
- * '4000.01', // price at 4000.01 (ETH/USDC)
97
- * { signature }
98
- * )
98
+ * const { transaction } = await limitOrder({
99
+ * chainId: 421614,
100
+ * userAddress: '0xF8c1869Ecd4df136693C45EcE1b67f85B6bDaE69
101
+ * inputToken: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
102
+ * outputToken: '0x0000000000000000000000000000000000000000',
103
+ * amount: '100.123', // 100.123 USDC
104
+ * price: '4000.01', // price at 4000.01 (ETH/USDC)
105
+ * options: { erc20PermitParam }
106
+ * })
99
107
  *
100
108
  * @example
101
109
  * import { limitOrder } from '@clober/v2-sdk'
102
110
  *
103
- * const transaction = await limitOrder(
104
- * 421614,
105
- * '0xF8c1869Ecd4df136693C45EcE1b67f85B6bDaE69
106
- * '0x0000000000000000000000000000000000000000',
107
- * '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
108
- * '0.13', // 0.13 ETH
109
- * '4000.01', // price at 4000.01 (ETH/USDC)
110
- * )
111
+ * const { transaction } = await limitOrder({
112
+ * chainId: 421614,
113
+ * userAddress: '0xF8c1869Ecd4df136693C45EcE1b67f85B6bDaE69
114
+ * inputToken: '0x0000000000000000000000000000000000000000',
115
+ * outputToken: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
116
+ * amount: '0.13', // 0.13 ETH
117
+ * price: '4000.01', // price at 4000.01 (ETH/USDC)
118
+ * })
111
119
  */
112
120
  export const limitOrder = decorator(async ({ chainId, userAddress, inputToken, outputToken, amount, price, options, }) => {
113
121
  const market = await fetchMarket(chainId, [inputToken, outputToken]);
114
122
  const isBid = isAddressEqual(market.quote.address, inputToken);
115
- if ((isBid && !market.bidBookOpen) || (!isBid && !market.askBookOpen)) {
123
+ const [inputCurrency, outputCurrency] = isBid
124
+ ? [market.quote, market.base]
125
+ : [market.base, market.quote];
126
+ if ((isBid && !market.bidBook.isOpened) ||
127
+ (!isBid && !market.askBook.isOpened)) {
116
128
  throw new Error(`
129
+ Open the market before placing a limit order.
117
130
  import { openMarket } from '@clober/v2-sdk'
118
131
 
119
- const transaction = await openMarket(
120
- ${chainId},
121
- '${inputToken}',
122
- '${outputToken}',
123
- )
132
+ const transaction = await openMarket({
133
+ chainId: ${chainId},
134
+ inputToken: '${inputToken}',
135
+ outputToken: '${outputToken}',
136
+ })
124
137
  `);
125
138
  }
126
139
  const rawPrice = parsePrice(Number(price), market.quote.decimals, market.base.decimals);
127
- const tick = isBid ? fromPrice(rawPrice) : fromPrice(invertPrice(rawPrice));
128
140
  const tokensToSettle = [inputToken, outputToken].filter((address) => !isAddressEqual(address, zeroAddress));
129
- const quoteAmount = parseUnits(amount, isBid ? market.quote.decimals : market.base.decimals);
130
- const [unit, { result }] = await Promise.all([
131
- calculateUnit(chainId, isBid ? market.quote : market.base),
141
+ const quoteAmount = parseUnits(amount, inputCurrency.decimals);
142
+ const [unitSize, { takenAmount, spentAmount, bookId }] = await Promise.all([
143
+ calculateUnitSize(chainId, inputCurrency),
132
144
  getExpectedOutput({
133
145
  chainId,
134
146
  inputToken,
@@ -136,162 +148,162 @@ export const limitOrder = decorator(async ({ chainId, userAddress, inputToken, o
136
148
  amountIn: amount,
137
149
  options: {
138
150
  ...options,
151
+ limitPrice: price,
139
152
  },
140
153
  }),
141
154
  ]);
142
155
  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
156
  const makeParam = {
153
- id: toBookId(inputToken, outputToken, unit),
154
- tick: Number(tick),
157
+ id: toBookId(chainId, inputToken, outputToken, unitSize),
158
+ tick: options?.makeTick
159
+ ? Number(options.makeTick)
160
+ : Number(isBid ? fromPrice(rawPrice) : fromPrice(invertPrice(rawPrice))),
155
161
  quoteAmount,
156
162
  hookData: zeroHash,
157
163
  };
158
- if (options?.postOnly === true || result.length === 0) {
159
- return buildTransaction(chainId, {
160
- chain: CHAIN_MAP[chainId],
161
- account: userAddress,
162
- address: CONTRACT_ADDRESSES[chainId].Controller,
163
- abi: CONTROLLER_ABI,
164
- functionName: 'make',
165
- args: [
166
- [makeParam],
167
- tokensToSettle,
168
- permitParamsList,
169
- getDeadlineTimestampInSeconds(),
170
- ],
171
- value: isETH ? quoteAmount : 0n,
172
- });
173
- }
174
- else if (result.length === 1) {
175
- // take and make
176
- return buildTransaction(chainId, {
177
- chain: CHAIN_MAP[chainId],
178
- account: userAddress,
179
- address: CONTRACT_ADDRESSES[chainId].Controller,
180
- abi: CONTROLLER_ABI,
181
- functionName: 'limit',
182
- args: [
183
- [
184
- {
185
- takeBookId: result[0].bookId,
186
- makeBookId: makeParam.id,
187
- limitPrice: rawPrice,
188
- tick: makeParam.tick,
189
- quoteAmount,
190
- takeHookData: zeroHash,
191
- makeHookData: makeParam.hookData,
192
- },
164
+ if (options?.postOnly === true || spentAmount === '0') {
165
+ return {
166
+ transaction: await buildTransaction(chainId, {
167
+ chain: CHAIN_MAP[chainId],
168
+ account: userAddress,
169
+ address: CONTRACT_ADDRESSES[chainId].Controller,
170
+ abi: CONTROLLER_ABI,
171
+ functionName: 'make',
172
+ args: [
173
+ [makeParam],
174
+ tokensToSettle,
175
+ options?.erc20PermitParam ? [options.erc20PermitParam] : [],
176
+ getDeadlineTimestampInSeconds(),
193
177
  ],
194
- tokensToSettle,
195
- permitParamsList,
196
- getDeadlineTimestampInSeconds(),
197
- ],
198
- value: isETH ? quoteAmount : 0n,
199
- });
178
+ value: isETH ? quoteAmount : 0n,
179
+ }, options?.gasLimit),
180
+ result: {
181
+ make: {
182
+ amount: formatUnits(quoteAmount, inputCurrency.decimals),
183
+ currency: inputCurrency,
184
+ direction: 'in',
185
+ },
186
+ spent: {
187
+ amount: '0',
188
+ currency: inputCurrency,
189
+ direction: 'in',
190
+ },
191
+ taken: {
192
+ amount: '0',
193
+ currency: outputCurrency,
194
+ direction: 'out',
195
+ },
196
+ },
197
+ };
200
198
  }
201
199
  else {
202
- // take x n and make
203
- const makeAmount = quoteAmount -
204
- result.reduce((acc, { spendAmount }) => acc + spendAmount, 0n);
205
- return buildTransaction(chainId, {
206
- chain: CHAIN_MAP[chainId],
207
- account: userAddress,
208
- address: CONTRACT_ADDRESSES[chainId].Controller,
209
- abi: CONTROLLER_ABI,
210
- functionName: 'execute',
211
- args: [
212
- [
213
- ...result.map(() => Action.TAKE),
214
- ...(makeAmount > 0n ? [Action.MAKE] : []),
215
- ],
216
- [
217
- ...result.map(({ bookId, takenAmount }) => encodeAbiParameters(TAKE_ORDER_PARAMS_ABI, [
200
+ // take and make
201
+ return {
202
+ transaction: await buildTransaction(chainId, {
203
+ chain: CHAIN_MAP[chainId],
204
+ account: userAddress,
205
+ address: CONTRACT_ADDRESSES[chainId].Controller,
206
+ abi: CONTROLLER_ABI,
207
+ functionName: 'limit',
208
+ args: [
209
+ [
218
210
  {
219
- id: bookId,
220
- limitPrice: rawPrice,
221
- quoteAmount: takenAmount,
222
- hookData: zeroHash,
211
+ takeBookId: bookId,
212
+ makeBookId: makeParam.id,
213
+ limitPrice: options?.takeLimitTick
214
+ ? toPrice(options.takeLimitTick)
215
+ : isBid
216
+ ? invertPrice(rawPrice)
217
+ : rawPrice,
218
+ tick: makeParam.tick,
219
+ quoteAmount,
220
+ takeHookData: zeroHash,
221
+ makeHookData: makeParam.hookData,
223
222
  },
224
- ])),
225
- ...(makeAmount > 0n
226
- ? [
227
- encodeAbiParameters(MAKE_ORDER_PARAMS_ABI, [
228
- {
229
- ...makeParam,
230
- quoteAmount: makeAmount,
231
- },
232
- ]),
233
- ]
234
- : []),
223
+ ],
224
+ tokensToSettle,
225
+ options?.erc20PermitParam ? [options.erc20PermitParam] : [],
226
+ getDeadlineTimestampInSeconds(),
235
227
  ],
236
- tokensToSettle,
237
- permitParamsList,
238
- [],
239
- getDeadlineTimestampInSeconds(),
240
- ],
241
- value: isETH ? quoteAmount : 0n,
242
- });
228
+ value: isETH ? quoteAmount : 0n,
229
+ }, options?.gasLimit),
230
+ result: {
231
+ make: {
232
+ amount: formatUnits(quoteAmount - parseUnits(spentAmount, inputCurrency.decimals), inputCurrency.decimals),
233
+ currency: inputCurrency,
234
+ direction: 'in',
235
+ },
236
+ spent: {
237
+ amount: spentAmount,
238
+ currency: inputCurrency,
239
+ direction: 'in',
240
+ },
241
+ taken: {
242
+ amount: takenAmount,
243
+ currency: outputCurrency,
244
+ direction: 'out',
245
+ },
246
+ },
247
+ };
243
248
  }
244
249
  });
245
250
  /**
246
251
  * Executes a market order on the specified chain for trading tokens.
252
+ * If only `amountIn` is provided, spend the specified amount of input tokens.
253
+ * If only `amountOut` is provided, take the specified amount of output tokens.
247
254
  *
248
255
  * @param {CHAIN_IDS} chainId The chain ID.
249
256
  * @param {`0x${string}`} userAddress The Ethereum address of the user placing the order.
250
257
  * @param {`0x${string}`} inputToken The address of the token to be used as input.
251
258
  * @param {`0x${string}`} outputToken The address of the token to be received as output.
252
- * @param {string} amount The amount of input tokens for the order.
253
- * @param {Object} [options] Optional parameters for the limit order.
254
- * @param {PermitSignature} [options.signature] The permit signature for token approval.
259
+ * @param {string} amountIn The amount of input tokens for the order to spend.
260
+ * @param {string} amountOut The amount of output tokens for the order to take.
261
+ * @param {Object} [options] Optional parameters for the market order.
262
+ * @param {erc20PermitParam} [options.erc20PermitParam] The permit signature for token approval.
255
263
  * @param {string} [options.rpcUrl] The RPC URL of the blockchain.
256
- * @param {string} [options.limitPrice] The upper bound price to tolerate for the market bid, or the lower bound price to tolerate for the market ask.
257
- * if the limit price is not provided, unlimited slippage is allowed.
258
- * @returns {Promise<Transaction>} Promise resolving to the transaction object representing the limit order.
264
+ * @param {number} [options.gasLimit] The gas limit to use for the transaction.
265
+ * @param {boolean} [options.useSubgraph] A boolean indicating whether to use the subgraph for fetching orders.
266
+ * @param {number} [options.slippage] The maximum slippage percentage allowed for the order.
267
+ * if the slippage is not provided, unlimited slippage is allowed.
268
+ * @returns {Promise<{ transaction: Transaction, result: { spent: CurrencyFlow, taken: CurrencyFlow } }>}
269
+ * Promise resolving to the transaction object representing the market order with the result of the order.
259
270
  * @example
260
271
  * import { signERC20Permit, marketOrder } from '@clober/v2-sdk'
261
272
  * import { privateKeyToAccount } from 'viem/accounts'
262
273
  *
263
- * const signature = await signERC20Permit(
264
- * 421614,
265
- * privateKeyToAccount('0x...'),
266
- * '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
267
- * '100.123'
268
- * )
269
- *
270
- * const transaction = await marketOrder(
271
- * 421614,
272
- * '0xF8c1869Ecd4df136693C45EcE1b67f85B6bDaE69
273
- * '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
274
- * '0x0000000000000000000000000000000000000000',
275
- * '100.123', // 100.123 USDC
276
- * { signature }
277
- * )
274
+ * const erc20PermitParam = await signERC20Permit({
275
+ * chainId: 421614,
276
+ * walletClient,
277
+ * token: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
278
+ * amount: '100.123'
279
+ * })
278
280
  *
279
- * @example
280
- * import { marketOrder } from '@clober/v2-sdk'
281
+ * const transaction = await marketOrder({
282
+ * chainId: 421614,
283
+ * userAddress: '0xF8c1869Ecd4df136693C45EcE1b67f85B6bDaE69
284
+ * inputToken: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
285
+ * outputToken: '0x0000000000000000000000000000000000000000',
286
+ * amount: '100.123', // 100.123 USDC
287
+ * options: { erc20PermitParam }
288
+ * })
281
289
  *
282
- * const transaction = await limitOrder(
283
- * 421614,
284
- * '0xF8c1869Ecd4df136693C45EcE1b67f85B6bDaE69
285
- * '0x0000000000000000000000000000000000000000',
286
- * '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
287
- * '0.13', // 0.13 ETH
288
- * )
289
290
  */
290
- export const marketOrder = decorator(async ({ chainId, userAddress, inputToken, outputToken, amount, options, }) => {
291
+ export const marketOrder = decorator(async ({ chainId, userAddress, inputToken, outputToken, amountIn, amountOut, options, }) => {
292
+ if (!amountIn && !amountOut) {
293
+ throw new Error('Either amountIn or amountOut must be provided');
294
+ }
295
+ else if (amountIn && amountOut) {
296
+ throw new Error('Only one of amountIn or amountOut can be provided');
297
+ }
291
298
  const market = await fetchMarket(chainId, [inputToken, outputToken]);
292
- const isBid = isAddressEqual(market.quote.address, inputToken);
293
- if ((isBid && !market.bidBookOpen) || (!isBid && !market.askBookOpen)) {
299
+ const isTakingBid = isAddressEqual(market.base.address, inputToken);
300
+ const [inputCurrency, outputCurrency] = isTakingBid
301
+ ? [market.base, market.quote]
302
+ : [market.quote, market.base];
303
+ if ((isTakingBid && !market.bidBook.isOpened) ||
304
+ (!isTakingBid && !market.askBook.isOpened)) {
294
305
  throw new Error(`
306
+ Open the market before placing a market order.
295
307
  import { openMarket } from '@clober/v2-sdk'
296
308
 
297
309
  const transaction = await openMarket(
@@ -301,47 +313,118 @@ export const marketOrder = decorator(async ({ chainId, userAddress, inputToken,
301
313
  )
302
314
  `);
303
315
  }
304
- const rawLimitPrice = parsePrice(Number(options?.limitPrice ?? '0'), market.quote.decimals, market.base.decimals);
305
316
  const tokensToSettle = [inputToken, outputToken].filter((address) => !isAddressEqual(address, zeroAddress));
306
- const quoteAmount = parseUnits(amount, isBid ? market.quote.decimals : market.base.decimals);
307
- const { result } = await getExpectedOutput({
308
- chainId,
309
- inputToken,
310
- outputToken,
311
- amountIn: amount,
312
- options: {
313
- ...options,
314
- },
315
- });
316
317
  const isETH = isAddressEqual(inputToken, zeroAddress);
317
- const permitParamsList = options?.signature && !isETH
318
- ? [
319
- {
320
- token: inputToken,
321
- permitAmount: quoteAmount,
322
- signature: options.signature,
318
+ if (amountIn && !amountOut) {
319
+ const { bookId, takenAmount, spentAmount } = await getExpectedOutput({
320
+ chainId,
321
+ inputToken,
322
+ outputToken,
323
+ amountIn,
324
+ options: {
325
+ ...options,
326
+ // don't need to check limit price for market order
323
327
  },
324
- ]
325
- : [];
326
- return buildTransaction(chainId, {
327
- chain: CHAIN_MAP[chainId],
328
- account: userAddress,
329
- address: CONTRACT_ADDRESSES[chainId].Controller,
330
- abi: CONTROLLER_ABI,
331
- functionName: 'take',
332
- args: [
333
- result.map(({ bookId, takenAmount }) => ({
334
- id: bookId,
335
- limitPrice: isBid ? invertPrice(rawLimitPrice) : rawLimitPrice,
336
- quoteAmount: takenAmount,
337
- hookData: zeroHash,
338
- })),
339
- tokensToSettle,
340
- permitParamsList,
341
- getDeadlineTimestampInSeconds(),
342
- ],
343
- value: isETH ? quoteAmount : 0n,
344
- });
328
+ });
329
+ const baseAmount = parseUnits(amountIn, inputCurrency.decimals);
330
+ return {
331
+ transaction: await buildTransaction(chainId, {
332
+ chain: CHAIN_MAP[chainId],
333
+ account: userAddress,
334
+ address: CONTRACT_ADDRESSES[chainId].Controller,
335
+ abi: CONTROLLER_ABI,
336
+ functionName: 'spend',
337
+ args: [
338
+ [
339
+ {
340
+ id: bookId,
341
+ limitPrice: 0n,
342
+ baseAmount,
343
+ minQuoteAmount: options?.slippage
344
+ ? applyPercent(parseUnits(takenAmount, outputCurrency.decimals), 100 - options.slippage)
345
+ : 0n,
346
+ hookData: zeroHash,
347
+ },
348
+ ],
349
+ tokensToSettle,
350
+ options?.erc20PermitParam ? [options.erc20PermitParam] : [],
351
+ getDeadlineTimestampInSeconds(),
352
+ ],
353
+ value: isETH ? baseAmount : 0n,
354
+ }, options?.gasLimit),
355
+ result: {
356
+ spent: {
357
+ amount: spentAmount,
358
+ currency: inputCurrency,
359
+ direction: 'in',
360
+ },
361
+ taken: {
362
+ amount: takenAmount,
363
+ currency: outputCurrency,
364
+ direction: 'out',
365
+ },
366
+ },
367
+ };
368
+ }
369
+ else if (!amountIn && amountOut) {
370
+ const { bookId, spentAmount, takenAmount } = await getExpectedInput({
371
+ chainId,
372
+ inputToken,
373
+ outputToken,
374
+ amountOut,
375
+ options: {
376
+ ...options,
377
+ // don't need to check limit price for market order
378
+ },
379
+ });
380
+ const quoteAmount = parseUnits(amountOut, outputCurrency.decimals);
381
+ const baseAmount = parseUnits(spentAmount, inputCurrency.decimals);
382
+ const maxBaseAmount = options?.erc20PermitParam?.permitAmount ??
383
+ (options?.slippage
384
+ ? applyPercent(baseAmount, 100 + options.slippage)
385
+ : isETH
386
+ ? baseAmount
387
+ : 2n ** 256n - 1n);
388
+ return {
389
+ transaction: await buildTransaction(chainId, {
390
+ chain: CHAIN_MAP[chainId],
391
+ account: userAddress,
392
+ address: CONTRACT_ADDRESSES[chainId].Controller,
393
+ abi: CONTROLLER_ABI,
394
+ functionName: 'take',
395
+ args: [
396
+ [
397
+ {
398
+ id: bookId,
399
+ limitPrice: 0n,
400
+ quoteAmount,
401
+ maxBaseAmount,
402
+ hookData: zeroHash,
403
+ },
404
+ ],
405
+ tokensToSettle,
406
+ options?.erc20PermitParam ? [options.erc20PermitParam] : [],
407
+ getDeadlineTimestampInSeconds(),
408
+ ],
409
+ value: isETH ? maxBaseAmount : 0n,
410
+ }, options?.gasLimit),
411
+ result: {
412
+ spent: {
413
+ amount: spentAmount,
414
+ currency: inputCurrency,
415
+ direction: 'in',
416
+ },
417
+ taken: {
418
+ amount: takenAmount,
419
+ currency: outputCurrency,
420
+ direction: 'out',
421
+ },
422
+ },
423
+ };
424
+ }
425
+ else {
426
+ throw new Error('Either amountIn or amountOut must be provided');
427
+ }
345
428
  });
346
429
  /**
347
430
  * Claims specified open order for settlement.
@@ -352,28 +435,35 @@ export const marketOrder = decorator(async ({ chainId, userAddress, inputToken,
352
435
  * @param {string} id An ID representing the open order to be claimed.
353
436
  * @param {Object} [options] Optional parameters for claiming orders.
354
437
  * @param {string} [options.rpcUrl] The RPC URL to use for executing the transaction.
355
- * @returns {Promise<Transaction>} Promise resolving to the transaction object representing the claim action.
438
+ * @param {number} [options.gasLimit] The gas limit to use for the transaction.
439
+ * @param {boolean} [options.useSubgraph] A boolean indicating whether to use the subgraph for fetching orders.
440
+ * @returns {Promise<{ transaction: Transaction, result: CurrencyFlow }>}
441
+ * Promise resolving to the transaction object representing the claim action with the result of the order.
356
442
  * @throws {Error} Throws an error if no open orders are found for the specified user.
357
443
  * @example
358
444
  * import { getOpenOrders, claimOrders } from '@clober/v2-sdk'
359
445
  *
360
- * const openOrders = await getOpenOrders(
361
- * 421614,
362
- * '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0'
363
- * )
364
- * const transaction = await claimOrders(
365
- * 421614,
366
- * '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
367
- * openOrders.map((order) => order.id)
368
- * )
446
+ * const openOrders = await getOpenOrders({
447
+ * chainId: 421614,
448
+ * userAddress: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0'
449
+ * })
450
+ * const transaction = await claimOrders({
451
+ * chainId: 421614,
452
+ * userAddress: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
453
+ * id: openOrders.map((order) => order.id)
454
+ * })
369
455
  */
370
456
  export const claimOrder = decorator(async ({ chainId, userAddress, id, options, }) => {
371
- return claimOrders({
457
+ const { transaction, result } = await claimOrders({
372
458
  chainId,
373
459
  userAddress,
374
460
  ids: [id],
375
461
  options: { ...options },
376
462
  });
463
+ return {
464
+ transaction,
465
+ result: result[0],
466
+ };
377
467
  });
378
468
  /**
379
469
  * Claims specified open orders for settlement.
@@ -384,61 +474,73 @@ export const claimOrder = decorator(async ({ chainId, userAddress, id, options,
384
474
  * @param {string[]} ids An array of IDs representing the open orders to be claimed.
385
475
  * @param {Object} [options] Optional parameters for claiming orders.
386
476
  * @param {string} [options.rpcUrl] The RPC URL to use for executing the transaction.
387
- * @returns {Promise<Transaction>} Promise resolving to the transaction object representing the claim action.
477
+ * @param {number} [options.gasLimit] The gas limit to use for the transaction.
478
+ * @param {boolean} [options.useSubgraph] A boolean indicating whether to use the subgraph for fetching orders.
479
+ * @returns {Promise<{ transaction: Transaction, result: CurrencyFlow[] }>}
480
+ * Promise resolving to the transaction object representing the claim action with the result of the orders.
388
481
  * @throws {Error} Throws an error if no open orders are found for the specified user.
389
482
  * @example
390
483
  * import { getOpenOrders, claimOrders } from '@clober/v2-sdk'
391
484
  *
392
- * const openOrders = await getOpenOrders(
393
- * 421614,
394
- * '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0'
395
- * )
485
+ * const openOrders = await getOpenOrders({
486
+ * chainId: 421614,
487
+ * userAddress: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0'
488
+ * })
396
489
  * const transaction = await claimOrders(
397
- * 421614,
398
- * '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
399
- * openOrders.map((order) => order.id)
490
+ * chainId: 421614,
491
+ * userAddress: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
492
+ * ids: openOrders.map((order) => order.id)
400
493
  * )
401
494
  */
402
495
  export const claimOrders = decorator(async ({ chainId, userAddress, ids, options, }) => {
403
496
  const isApprovedForAll = await fetchIsApprovedForAll(chainId, userAddress);
404
497
  if (!isApprovedForAll) {
405
498
  throw new Error(`
499
+ Set ApprovalForAll before calling this function.
406
500
  import { setApprovalOfOpenOrdersForAll } from '@clober/v2-sdk'
407
501
 
408
- const hash = await setApprovalOfOpenOrdersForAll(
409
- ${chainId},
410
- privateKeyToAccount('0x...')
411
- )
502
+ const hash = await setApprovalOfOpenOrdersForAll({
503
+ chainId: ${chainId},
504
+ walletClient, // use viem
505
+ })
412
506
  `);
413
507
  }
414
- const openOrders = (await getOpenOrders({ chainId, userAddress, options: { ...options } })).filter((order) => ids.includes(order.id));
415
- if (openOrders.length === 0) {
416
- throw new Error(`No claimable open orders found for ${userAddress}`);
417
- }
418
- const tokensToSettle = openOrders
508
+ const orders = (await fetchOrders(chainId, ids.map((id) => BigInt(id)))).filter((order) => isAddressEqual(order.user, userAddress) &&
509
+ order.claimable.value !== '0');
510
+ const tokensToSettle = orders
419
511
  .map((order) => [
420
- order.outputCurrency.address,
421
512
  order.inputCurrency.address,
513
+ order.outputCurrency.address,
422
514
  ])
423
515
  .flat()
424
516
  .filter((address, index, self) => self.findIndex((c) => isAddressEqual(c, address)) === index)
425
517
  .filter((address) => !isAddressEqual(address, zeroAddress));
426
- return buildTransaction(chainId, {
427
- chain: CHAIN_MAP[chainId],
428
- account: userAddress,
429
- address: CONTRACT_ADDRESSES[chainId].Controller,
430
- abi: CONTROLLER_ABI,
431
- functionName: 'claim',
432
- args: [
433
- openOrders.map((order) => ({
434
- id: BigInt(order.id),
435
- hookData: zeroHash,
436
- })),
437
- tokensToSettle,
438
- [],
439
- getDeadlineTimestampInSeconds(),
440
- ],
441
- });
518
+ return {
519
+ transaction: await buildTransaction(chainId, {
520
+ chain: CHAIN_MAP[chainId],
521
+ account: userAddress,
522
+ address: CONTRACT_ADDRESSES[chainId].Controller,
523
+ abi: CONTROLLER_ABI,
524
+ functionName: 'claim',
525
+ args: [
526
+ orders.map(({ id }) => ({
527
+ id,
528
+ hookData: zeroHash,
529
+ })),
530
+ tokensToSettle,
531
+ [],
532
+ getDeadlineTimestampInSeconds(),
533
+ ],
534
+ }, options?.gasLimit),
535
+ result: orders.reduce((acc, { claimable: { currency, value } }) => {
536
+ const index = acc.findIndex((c) => isAddressEqual(c.currency.address, currency.address));
537
+ if (index === -1) {
538
+ return [...acc, { currency, amount: value, direction: 'out' }];
539
+ }
540
+ acc[index].amount = (Number(acc[index].amount) + Number(value)).toString();
541
+ return acc;
542
+ }, []),
543
+ };
442
544
  });
443
545
  /**
444
546
  * Cancels specified open order if the order is not fully filled.
@@ -449,28 +551,35 @@ export const claimOrders = decorator(async ({ chainId, userAddress, ids, options
449
551
  * @param {string} id An ID representing the open order to be canceled
450
552
  * @param {Object} [options] Optional parameters for canceling orders.
451
553
  * @param {string} [options.rpcUrl] The RPC URL to use for executing the transaction.
452
- * @returns {Promise<Transaction>} Promise resolving to the transaction object representing the cancel action.
554
+ * @param {number} [options.gasLimit] The gas limit to use for the transaction.
555
+ * @param {boolean} [options.useSubgraph] A boolean indicating whether to use the subgraph for fetching orders.
556
+ * @returns {Promise<{ transaction: Transaction, result: CurrencyFlow }>}
557
+ * Promise resolving to the transaction object representing the cancel action with the result of the order.
453
558
  * @throws {Error} Throws an error if no open orders are found for the specified user.
454
559
  * @example
455
560
  * import { getOpenOrders, cancelOrders } from '@clober/v2-sdk'
456
561
  *
457
- * const openOrders = await getOpenOrders(
458
- * 421614,
459
- * '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0'
460
- * )
461
- * const transaction = await cancelOrders(
462
- * 421614,
463
- * '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
464
- * openOrders.map((order) => order.id)
465
- * )
562
+ * const openOrders = await getOpenOrders({
563
+ * chainId: 421614,
564
+ * userAddress:'0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0'
565
+ * })
566
+ * const transaction = await cancelOrders({
567
+ * chainId: 421614,
568
+ * userAddress: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
569
+ * id: openOrders.map((order) => order.id)
570
+ * })
466
571
  */
467
572
  export const cancelOrder = decorator(async ({ chainId, userAddress, id, options, }) => {
468
- return cancelOrders({
573
+ const { transaction, result } = await cancelOrders({
469
574
  chainId,
470
575
  userAddress,
471
576
  ids: [id],
472
577
  options: { ...options },
473
578
  });
579
+ return {
580
+ transaction,
581
+ result: result[0],
582
+ };
474
583
  });
475
584
  /**
476
585
  * Cancels specified open orders if orders are not fully filled.
@@ -481,61 +590,73 @@ export const cancelOrder = decorator(async ({ chainId, userAddress, id, options,
481
590
  * @param {string[]} ids An array of IDs representing the open orders to be canceled.
482
591
  * @param {Object} [options] Optional parameters for canceling orders.
483
592
  * @param {string} [options.rpcUrl] The RPC URL to use for executing the transaction.
484
- * @returns {Promise<Transaction>} Promise resolving to the transaction object representing the cancel action.
593
+ * @param {number} [options.gasLimit] The gas limit to use for the transaction.
594
+ * @param {boolean} [options.useSubgraph] A boolean indicating whether to use the subgraph for fetching orders.
595
+ * @returns {Promise<{ transaction: Transaction, result: CurrencyFlow[] }>
596
+ * Promise resolving to the transaction object representing the cancel action with the result of the orders.
485
597
  * @throws {Error} Throws an error if no open orders are found for the specified user.
486
598
  * @example
487
599
  * import { getOpenOrders, cancelOrders } from '@clober/v2-sdk'
488
600
  *
489
- * const openOrders = await getOpenOrders(
490
- * 421614,
491
- * '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0'
492
- * )
493
- * const transaction = await cancelOrders(
494
- * 421614,
495
- * '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
496
- * openOrders.map((order) => order.id)
497
- * )
601
+ * const openOrders = await getOpenOrders({
602
+ * chainId: 421614,
603
+ * userAddress: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0'
604
+ * })
605
+ * const transaction = await cancelOrders({
606
+ * chainId: 421614,
607
+ * userAddress: '0x00bfd44e79fb7f6dd5887a9426c8ef85a0cd23e0',
608
+ * ids: openOrders.map((order) => order.id)
609
+ * })
498
610
  */
499
611
  export const cancelOrders = decorator(async ({ chainId, userAddress, ids, options, }) => {
500
612
  const isApprovedForAll = await fetchIsApprovedForAll(chainId, userAddress);
501
613
  if (!isApprovedForAll) {
502
614
  throw new Error(`
615
+ Set ApprovalForAll before calling this function.
503
616
  import { setApprovalOfOpenOrdersForAll } from '@clober/v2-sdk'
504
617
 
505
- const hash = await setApprovalOfOpenOrdersForAll(
506
- ${chainId},
507
- privateKeyToAccount('0x...')
508
- )
618
+ const hash = await setApprovalOfOpenOrdersForAll({
619
+ chainId: ${chainId},
620
+ walletClient, // use viem
621
+ })
509
622
  `);
510
623
  }
511
- const openOrders = (await getOpenOrders({ chainId, userAddress, options: { ...options } })).filter((order) => ids.includes(order.id) && order.cancelable);
512
- if (openOrders.length === 0) {
513
- throw new Error(`No cancelable open orders found for ${userAddress}`);
514
- }
515
- const tokensToSettle = openOrders
624
+ const orders = (await fetchOrders(chainId, ids.map((id) => BigInt(id)))).filter((order) => isAddressEqual(order.user, userAddress) &&
625
+ order.cancelable.value !== '0');
626
+ const tokensToSettle = orders
516
627
  .map((order) => [
517
- order.outputCurrency.address,
518
628
  order.inputCurrency.address,
629
+ order.outputCurrency.address,
519
630
  ])
520
631
  .flat()
521
632
  .filter((address, index, self) => self.findIndex((c) => isAddressEqual(c, address)) === index)
522
633
  .filter((address) => !isAddressEqual(address, zeroAddress));
523
- return buildTransaction(chainId, {
524
- chain: CHAIN_MAP[chainId],
525
- account: userAddress,
526
- address: CONTRACT_ADDRESSES[chainId].Controller,
527
- abi: CONTROLLER_ABI,
528
- functionName: 'cancel',
529
- args: [
530
- openOrders.map((order) => ({
531
- id: BigInt(order.id),
532
- leftQuoteAmount: 0n,
533
- hookData: zeroHash,
534
- })),
535
- tokensToSettle,
536
- [],
537
- getDeadlineTimestampInSeconds(),
538
- ],
539
- });
634
+ return {
635
+ transaction: await buildTransaction(chainId, {
636
+ chain: CHAIN_MAP[chainId],
637
+ account: userAddress,
638
+ address: CONTRACT_ADDRESSES[chainId].Controller,
639
+ abi: CONTROLLER_ABI,
640
+ functionName: 'cancel',
641
+ args: [
642
+ orders.map(({ id }) => ({
643
+ id,
644
+ leftQuoteAmount: 0n,
645
+ hookData: zeroHash,
646
+ })),
647
+ tokensToSettle,
648
+ [],
649
+ getDeadlineTimestampInSeconds(),
650
+ ],
651
+ }, options?.gasLimit),
652
+ result: orders.reduce((acc, { cancelable: { currency, value } }) => {
653
+ const index = acc.findIndex((c) => isAddressEqual(c.currency.address, currency.address));
654
+ if (index === -1) {
655
+ return [...acc, { currency, amount: value, direction: 'out' }];
656
+ }
657
+ acc[index].amount = (Number(acc[index].amount) + Number(value)).toString();
658
+ return acc;
659
+ }, []),
660
+ };
540
661
  });
541
662
  //# sourceMappingURL=call.js.map