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