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