@drakkar.software/octobot-client 0.4.0

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 (306) hide show
  1. package/README.md +140 -0
  2. package/dist/client/adapters/accounts.d.ts +66 -0
  3. package/dist/client/adapters/accounts.d.ts.map +1 -0
  4. package/dist/client/adapters/accounts.js +214 -0
  5. package/dist/client/adapters/accounts.js.map +1 -0
  6. package/dist/client/adapters/actionHandle.d.ts +29 -0
  7. package/dist/client/adapters/actionHandle.d.ts.map +1 -0
  8. package/dist/client/adapters/actionHandle.js +34 -0
  9. package/dist/client/adapters/actionHandle.js.map +1 -0
  10. package/dist/client/adapters/automations.d.ts +31 -0
  11. package/dist/client/adapters/automations.d.ts.map +1 -0
  12. package/dist/client/adapters/automations.js +79 -0
  13. package/dist/client/adapters/automations.js.map +1 -0
  14. package/dist/client/adapters/documents.d.ts +55 -0
  15. package/dist/client/adapters/documents.d.ts.map +1 -0
  16. package/dist/client/adapters/documents.js +66 -0
  17. package/dist/client/adapters/documents.js.map +1 -0
  18. package/dist/client/adapters/nodeApi.d.ts +25 -0
  19. package/dist/client/adapters/nodeApi.d.ts.map +1 -0
  20. package/dist/client/adapters/nodeApi.js +81 -0
  21. package/dist/client/adapters/nodeApi.js.map +1 -0
  22. package/dist/client/adapters/settings.d.ts +16 -0
  23. package/dist/client/adapters/settings.d.ts.map +1 -0
  24. package/dist/client/adapters/settings.js +43 -0
  25. package/dist/client/adapters/settings.js.map +1 -0
  26. package/dist/client/adapters/strategies.d.ts +17 -0
  27. package/dist/client/adapters/strategies.d.ts.map +1 -0
  28. package/dist/client/adapters/strategies.js +75 -0
  29. package/dist/client/adapters/strategies.js.map +1 -0
  30. package/dist/client/connect/connect.d.ts +40 -0
  31. package/dist/client/connect/connect.d.ts.map +1 -0
  32. package/dist/client/connect/connect.js +133 -0
  33. package/dist/client/connect/connect.js.map +1 -0
  34. package/dist/client/connect/readOnly.d.ts +97 -0
  35. package/dist/client/connect/readOnly.d.ts.map +1 -0
  36. package/dist/client/connect/readOnly.js +167 -0
  37. package/dist/client/connect/readOnly.js.map +1 -0
  38. package/dist/client/core/errors.d.ts +80 -0
  39. package/dist/client/core/errors.d.ts.map +1 -0
  40. package/dist/client/core/errors.js +154 -0
  41. package/dist/client/core/errors.js.map +1 -0
  42. package/dist/client/core/options.d.ts +44 -0
  43. package/dist/client/core/options.d.ts.map +1 -0
  44. package/dist/client/core/options.js +2 -0
  45. package/dist/client/core/options.js.map +1 -0
  46. package/dist/client/core/session.d.ts +90 -0
  47. package/dist/client/core/session.d.ts.map +1 -0
  48. package/dist/client/core/session.js +72 -0
  49. package/dist/client/core/session.js.map +1 -0
  50. package/dist/client/core/views.d.ts +40 -0
  51. package/dist/client/core/views.d.ts.map +1 -0
  52. package/dist/client/core/views.js +32 -0
  53. package/dist/client/core/views.js.map +1 -0
  54. package/dist/client/index.d.ts +16 -0
  55. package/dist/client/index.d.ts.map +1 -0
  56. package/dist/client/index.js +9 -0
  57. package/dist/client/index.js.map +1 -0
  58. package/dist/client/mirror/collections.d.ts +125 -0
  59. package/dist/client/mirror/collections.d.ts.map +1 -0
  60. package/dist/client/mirror/collections.js +118 -0
  61. package/dist/client/mirror/collections.js.map +1 -0
  62. package/dist/client/mirror/index.d.ts +4 -0
  63. package/dist/client/mirror/index.d.ts.map +1 -0
  64. package/dist/client/mirror/index.js +4 -0
  65. package/dist/client/mirror/index.js.map +1 -0
  66. package/dist/client/mirror/writer.d.ts +39 -0
  67. package/dist/client/mirror/writer.d.ts.map +1 -0
  68. package/dist/client/mirror/writer.js +50 -0
  69. package/dist/client/mirror/writer.js.map +1 -0
  70. package/dist/client/pairing/mirrorGrant.d.ts +91 -0
  71. package/dist/client/pairing/mirrorGrant.d.ts.map +1 -0
  72. package/dist/client/pairing/mirrorGrant.js +99 -0
  73. package/dist/client/pairing/mirrorGrant.js.map +1 -0
  74. package/dist/client/pairing/mirrorReader.d.ts +99 -0
  75. package/dist/client/pairing/mirrorReader.d.ts.map +1 -0
  76. package/dist/client/pairing/mirrorReader.js +117 -0
  77. package/dist/client/pairing/mirrorReader.js.map +1 -0
  78. package/dist/client/pairing/pairingGrantExchange.d.ts +135 -0
  79. package/dist/client/pairing/pairingGrantExchange.d.ts.map +1 -0
  80. package/dist/client/pairing/pairingGrantExchange.js +186 -0
  81. package/dist/client/pairing/pairingGrantExchange.js.map +1 -0
  82. package/dist/client/pairing/pairingRequest.d.ts +82 -0
  83. package/dist/client/pairing/pairingRequest.d.ts.map +1 -0
  84. package/dist/client/pairing/pairingRequest.js +120 -0
  85. package/dist/client/pairing/pairingRequest.js.map +1 -0
  86. package/dist/client/strategy.d.ts +36 -0
  87. package/dist/client/strategy.d.ts.map +1 -0
  88. package/dist/client/strategy.js +26 -0
  89. package/dist/client/strategy.js.map +1 -0
  90. package/dist/collections/index.d.ts +3 -0
  91. package/dist/collections/index.d.ts.map +1 -0
  92. package/dist/collections/index.js +3 -0
  93. package/dist/collections/index.js.map +1 -0
  94. package/dist/collections/nodeCollections.d.ts +57 -0
  95. package/dist/collections/nodeCollections.d.ts.map +1 -0
  96. package/dist/collections/nodeCollections.js +40 -0
  97. package/dist/collections/nodeCollections.js.map +1 -0
  98. package/dist/collections/paths.d.ts +7 -0
  99. package/dist/collections/paths.d.ts.map +1 -0
  100. package/dist/collections/paths.js +13 -0
  101. package/dist/collections/paths.js.map +1 -0
  102. package/dist/crypto/collectionKeys.d.ts +28 -0
  103. package/dist/crypto/collectionKeys.d.ts.map +1 -0
  104. package/dist/crypto/collectionKeys.js +53 -0
  105. package/dist/crypto/collectionKeys.js.map +1 -0
  106. package/dist/crypto/hkdf.d.ts +14 -0
  107. package/dist/crypto/hkdf.d.ts.map +1 -0
  108. package/dist/crypto/hkdf.js +19 -0
  109. package/dist/crypto/hkdf.js.map +1 -0
  110. package/dist/crypto/index.d.ts +5 -0
  111. package/dist/crypto/index.d.ts.map +1 -0
  112. package/dist/crypto/index.js +5 -0
  113. package/dist/crypto/index.js.map +1 -0
  114. package/dist/crypto/secretEncryptor.d.ts +20 -0
  115. package/dist/crypto/secretEncryptor.d.ts.map +1 -0
  116. package/dist/crypto/secretEncryptor.js +82 -0
  117. package/dist/crypto/secretEncryptor.js.map +1 -0
  118. package/dist/crypto/wireConstants.d.ts +14 -0
  119. package/dist/crypto/wireConstants.d.ts.map +1 -0
  120. package/dist/crypto/wireConstants.js +17 -0
  121. package/dist/crypto/wireConstants.js.map +1 -0
  122. package/dist/identity/address.d.ts +3 -0
  123. package/dist/identity/address.d.ts.map +1 -0
  124. package/dist/identity/address.js +17 -0
  125. package/dist/identity/address.js.map +1 -0
  126. package/dist/identity/bip39-wordlist.d.ts +2 -0
  127. package/dist/identity/bip39-wordlist.d.ts.map +1 -0
  128. package/dist/identity/bip39-wordlist.js +2051 -0
  129. package/dist/identity/bip39-wordlist.js.map +1 -0
  130. package/dist/identity/capProvider.d.ts +45 -0
  131. package/dist/identity/capProvider.d.ts.map +1 -0
  132. package/dist/identity/capProvider.js +80 -0
  133. package/dist/identity/capProvider.js.map +1 -0
  134. package/dist/identity/derivationSchemes.d.ts +25 -0
  135. package/dist/identity/derivationSchemes.d.ts.map +1 -0
  136. package/dist/identity/derivationSchemes.js +34 -0
  137. package/dist/identity/derivationSchemes.js.map +1 -0
  138. package/dist/identity/evm.d.ts +8 -0
  139. package/dist/identity/evm.d.ts.map +1 -0
  140. package/dist/identity/evm.js +78 -0
  141. package/dist/identity/evm.js.map +1 -0
  142. package/dist/identity/index.d.ts +10 -0
  143. package/dist/identity/index.d.ts.map +1 -0
  144. package/dist/identity/index.js +10 -0
  145. package/dist/identity/index.js.map +1 -0
  146. package/dist/identity/keys.d.ts +17 -0
  147. package/dist/identity/keys.d.ts.map +1 -0
  148. package/dist/identity/keys.js +36 -0
  149. package/dist/identity/keys.js.map +1 -0
  150. package/dist/identity/mnemonic.d.ts +4 -0
  151. package/dist/identity/mnemonic.d.ts.map +1 -0
  152. package/dist/identity/mnemonic.js +93 -0
  153. package/dist/identity/mnemonic.js.map +1 -0
  154. package/dist/identity/pairing.d.ts +45 -0
  155. package/dist/identity/pairing.d.ts.map +1 -0
  156. package/dist/identity/pairing.js +91 -0
  157. package/dist/identity/pairing.js.map +1 -0
  158. package/dist/identity/pairingRequest.d.ts +99 -0
  159. package/dist/identity/pairingRequest.d.ts.map +1 -0
  160. package/dist/identity/pairingRequest.js +217 -0
  161. package/dist/identity/pairingRequest.js.map +1 -0
  162. package/dist/identity/secret.d.ts +32 -0
  163. package/dist/identity/secret.d.ts.map +1 -0
  164. package/dist/identity/secret.js +54 -0
  165. package/dist/identity/secret.js.map +1 -0
  166. package/dist/index.d.ts +9 -0
  167. package/dist/index.d.ts.map +1 -0
  168. package/dist/index.js +18 -0
  169. package/dist/index.js.map +1 -0
  170. package/dist/internal/bytes.d.ts +11 -0
  171. package/dist/internal/bytes.d.ts.map +1 -0
  172. package/dist/internal/bytes.js +38 -0
  173. package/dist/internal/bytes.js.map +1 -0
  174. package/dist/node-api/dexPair.d.ts +24 -0
  175. package/dist/node-api/dexPair.d.ts.map +1 -0
  176. package/dist/node-api/dexPair.js +39 -0
  177. package/dist/node-api/dexPair.js.map +1 -0
  178. package/dist/node-api/dsl.d.ts +10 -0
  179. package/dist/node-api/dsl.d.ts.map +1 -0
  180. package/dist/node-api/dsl.js +7 -0
  181. package/dist/node-api/dsl.js.map +1 -0
  182. package/dist/node-api/exchanges.d.ts +49 -0
  183. package/dist/node-api/exchanges.d.ts.map +1 -0
  184. package/dist/node-api/exchanges.js +32 -0
  185. package/dist/node-api/exchanges.js.map +1 -0
  186. package/dist/node-api/index.d.ts +12 -0
  187. package/dist/node-api/index.d.ts.map +1 -0
  188. package/dist/node-api/index.js +12 -0
  189. package/dist/node-api/index.js.map +1 -0
  190. package/dist/node-api/marketMaking.d.ts +39 -0
  191. package/dist/node-api/marketMaking.d.ts.map +1 -0
  192. package/dist/node-api/marketMaking.js +44 -0
  193. package/dist/node-api/marketMaking.js.map +1 -0
  194. package/dist/node-api/octobots.d.ts +14 -0
  195. package/dist/node-api/octobots.d.ts.map +1 -0
  196. package/dist/node-api/octobots.js +16 -0
  197. package/dist/node-api/octobots.js.map +1 -0
  198. package/dist/node-api/orderBookPreview.d.ts +11 -0
  199. package/dist/node-api/orderBookPreview.d.ts.map +1 -0
  200. package/dist/node-api/orderBookPreview.js +7 -0
  201. package/dist/node-api/orderBookPreview.js.map +1 -0
  202. package/dist/node-api/pairing.d.ts +39 -0
  203. package/dist/node-api/pairing.d.ts.map +1 -0
  204. package/dist/node-api/pairing.js +61 -0
  205. package/dist/node-api/pairing.js.map +1 -0
  206. package/dist/node-api/pairs.d.ts +32 -0
  207. package/dist/node-api/pairs.d.ts.map +1 -0
  208. package/dist/node-api/pairs.js +72 -0
  209. package/dist/node-api/pairs.js.map +1 -0
  210. package/dist/node-api/requiredFunds.d.ts +11 -0
  211. package/dist/node-api/requiredFunds.d.ts.map +1 -0
  212. package/dist/node-api/requiredFunds.js +7 -0
  213. package/dist/node-api/requiredFunds.js.map +1 -0
  214. package/dist/node-api/setup.d.ts +25 -0
  215. package/dist/node-api/setup.d.ts.map +1 -0
  216. package/dist/node-api/setup.js +13 -0
  217. package/dist/node-api/setup.js.map +1 -0
  218. package/dist/node-api/wallet.d.ts +55 -0
  219. package/dist/node-api/wallet.d.ts.map +1 -0
  220. package/dist/node-api/wallet.js +87 -0
  221. package/dist/node-api/wallet.js.map +1 -0
  222. package/dist/protocol/actions.d.ts +40 -0
  223. package/dist/protocol/actions.d.ts.map +1 -0
  224. package/dist/protocol/actions.js +118 -0
  225. package/dist/protocol/actions.js.map +1 -0
  226. package/dist/protocol/documents.d.ts +25 -0
  227. package/dist/protocol/documents.d.ts.map +1 -0
  228. package/dist/protocol/documents.js +2 -0
  229. package/dist/protocol/documents.js.map +1 -0
  230. package/dist/protocol/index.d.ts +10 -0
  231. package/dist/protocol/index.d.ts.map +1 -0
  232. package/dist/protocol/index.js +12 -0
  233. package/dist/protocol/index.js.map +1 -0
  234. package/dist/protocol/orchestration/createAutomation.d.ts +61 -0
  235. package/dist/protocol/orchestration/createAutomation.d.ts.map +1 -0
  236. package/dist/protocol/orchestration/createAutomation.js +71 -0
  237. package/dist/protocol/orchestration/createAutomation.js.map +1 -0
  238. package/dist/protocol/poll.d.ts +4 -0
  239. package/dist/protocol/poll.d.ts.map +1 -0
  240. package/dist/protocol/poll.js +4 -0
  241. package/dist/protocol/poll.js.map +1 -0
  242. package/dist/protocol/proposal.d.ts +36 -0
  243. package/dist/protocol/proposal.d.ts.map +1 -0
  244. package/dist/protocol/proposal.js +39 -0
  245. package/dist/protocol/proposal.js.map +1 -0
  246. package/dist/protocol/state.d.ts +87 -0
  247. package/dist/protocol/state.d.ts.map +1 -0
  248. package/dist/protocol/state.js +303 -0
  249. package/dist/protocol/state.js.map +1 -0
  250. package/dist/protocol/strategy/build.d.ts +44 -0
  251. package/dist/protocol/strategy/build.d.ts.map +1 -0
  252. package/dist/protocol/strategy/build.js +50 -0
  253. package/dist/protocol/strategy/build.js.map +1 -0
  254. package/dist/protocol/strategy/builders.d.ts +252 -0
  255. package/dist/protocol/strategy/builders.d.ts.map +1 -0
  256. package/dist/protocol/strategy/builders.js +382 -0
  257. package/dist/protocol/strategy/builders.js.map +1 -0
  258. package/dist/protocol/strategy/index.d.ts +5 -0
  259. package/dist/protocol/strategy/index.d.ts.map +1 -0
  260. package/dist/protocol/strategy/index.js +4 -0
  261. package/dist/protocol/strategy/index.js.map +1 -0
  262. package/dist/protocol/strategy/kinds.d.ts +2 -0
  263. package/dist/protocol/strategy/kinds.d.ts.map +1 -0
  264. package/dist/protocol/strategy/kinds.js +2 -0
  265. package/dist/protocol/strategy/kinds.js.map +1 -0
  266. package/dist/protocol/strategy/patch.d.ts +59 -0
  267. package/dist/protocol/strategy/patch.d.ts.map +1 -0
  268. package/dist/protocol/strategy/patch.js +253 -0
  269. package/dist/protocol/strategy/patch.js.map +1 -0
  270. package/dist/protocol/symbols.d.ts +8 -0
  271. package/dist/protocol/symbols.d.ts.map +1 -0
  272. package/dist/protocol/symbols.js +11 -0
  273. package/dist/protocol/symbols.js.map +1 -0
  274. package/dist/transport/constants.d.ts +8 -0
  275. package/dist/transport/constants.d.ts.map +1 -0
  276. package/dist/transport/constants.js +8 -0
  277. package/dist/transport/constants.js.map +1 -0
  278. package/dist/transport/documents.d.ts +27 -0
  279. package/dist/transport/documents.d.ts.map +1 -0
  280. package/dist/transport/documents.js +34 -0
  281. package/dist/transport/documents.js.map +1 -0
  282. package/dist/transport/index.d.ts +8 -0
  283. package/dist/transport/index.d.ts.map +1 -0
  284. package/dist/transport/index.js +8 -0
  285. package/dist/transport/index.js.map +1 -0
  286. package/dist/transport/probe.d.ts +44 -0
  287. package/dist/transport/probe.d.ts.map +1 -0
  288. package/dist/transport/probe.js +121 -0
  289. package/dist/transport/probe.js.map +1 -0
  290. package/dist/transport/rendezvous.d.ts +116 -0
  291. package/dist/transport/rendezvous.d.ts.map +1 -0
  292. package/dist/transport/rendezvous.js +139 -0
  293. package/dist/transport/rendezvous.js.map +1 -0
  294. package/dist/transport/rest.d.ts +35 -0
  295. package/dist/transport/rest.d.ts.map +1 -0
  296. package/dist/transport/rest.js +58 -0
  297. package/dist/transport/rest.js.map +1 -0
  298. package/dist/transport/syncClient.d.ts +14 -0
  299. package/dist/transport/syncClient.d.ts.map +1 -0
  300. package/dist/transport/syncClient.js +30 -0
  301. package/dist/transport/syncClient.js.map +1 -0
  302. package/dist/transport/urls.d.ts +35 -0
  303. package/dist/transport/urls.d.ts.map +1 -0
  304. package/dist/transport/urls.js +126 -0
  305. package/dist/transport/urls.js.map +1 -0
  306. package/package.json +55 -0
package/README.md ADDED
@@ -0,0 +1,140 @@
1
+ # @drakkar.software/octobot-client
2
+
3
+ Talk to a self-hosted OctoBot node from TypeScript: wallet identity, accounts, automations,
4
+ strategies, and user actions over the Starfish sync transport.
5
+
6
+ ## What this is not
7
+
8
+ - **No local state.** Every read is a fresh pull from the node; nothing is cached.
9
+ - **No persistence.** There is no store, no database, no `AsyncStorage`.
10
+ - **No offline queue.** If the node is unreachable, a call fails — it does not queue for later.
11
+ - **No CRDT merge.** This package has no concept of "local edits reconciled with remote state."
12
+ - **No React.** No hooks, no components, no dependency on any UI framework.
13
+
14
+ If you need any of the above (an offline-first mobile app syncing across devices, say), build that
15
+ layer on top of this package — see [Advanced: building an offline layer on top](https://docs.octobot.cloud/client-sdk/advanced-primitives)
16
+ for the subpath exports meant for exactly that.
17
+
18
+ ## Install
19
+
20
+ ```bash
21
+ npm install @drakkar.software/octobot-client
22
+ ```
23
+
24
+ **Runtime requirements:** WebCrypto (`crypto.subtle` — SHA-256/512, HMAC, PBKDF2, AES-GCM, HKDF),
25
+ `fetch`, `btoa`/`atob`, `AbortController`. Available natively in Node ≥18, all modern browsers, and
26
+ Deno/Bun. React Native needs a crypto polyfill (`react-native-quick-crypto` or similar) — this
27
+ package does not bundle one.
28
+
29
+ ## Hello world
30
+
31
+ ```ts
32
+ import { connectOctoBot, strategy } from '@drakkar.software/octobot-client'
33
+
34
+ const octobot = await connectOctoBot({
35
+ url: 'http://192.168.1.10:5001',
36
+ seed: process.env.OCTOBOT_PRIVATE_KEY!, // a raw 0x-prefixed private key
37
+ })
38
+
39
+ const [account] = await octobot.accounts.list()
40
+
41
+ const dca = strategy.dca({ pairs: ['BTC/USDT'], buyOrderAmount: '25' })
42
+ const action = await octobot.automations.create({
43
+ name: 'My DCA',
44
+ strategy: dca,
45
+ accountIds: [account.id],
46
+ })
47
+
48
+ const automation = await action.settled() // polls the node until it confirms
49
+ console.log(automation.id, automation.status) // 'live'
50
+ ```
51
+
52
+ ## Five concepts
53
+
54
+ 1. **A node is a server you point at.** `connectOctoBot({ url, seed })` — no registration, no
55
+ cloud account. Anyone running their own OctoBot node can be your `url`.
56
+ 2. **The wallet IS the identity.** There's no separate login. The private key (or a BIP39 mnemonic,
57
+ which derives one) deterministically derives both the address the node authorizes and the
58
+ encryption key for everything synced to it. See
59
+ [Identity](https://docs.octobot.cloud/client-sdk/identity) — this is the single most important
60
+ thing to get right, and the easiest to get subtly wrong.
61
+ 3. **Collections, not tables.** `accounts`, `settings`, `strategies`, `user-data` are documents at
62
+ fixed paths under `users/{identity}/...`, pulled and pushed as whole blobs, encrypted per-collection.
63
+ 4. **User actions are a queue, not an RPC call.** Creating an account or starting an automation
64
+ doesn't happen synchronously — it appends one element to an append-only queue the node consumes
65
+ and executes. `ActionHandle.settled()` is how you wait for the result. See
66
+ [User actions](https://docs.octobot.cloud/client-sdk/user-actions).
67
+ 5. **`ActionHandle` work starts eagerly.** The moment `accounts.create()`/`automations.create()`
68
+ returns a handle, the underlying action is already appended (and, for automations, the two-phase
69
+ orchestration is already running). `settled()` just lets you observe the outcome — a caller who
70
+ never awaits it still leaves nothing half-done.
71
+
72
+ ## API map
73
+
74
+ | | |
75
+ |---|---|
76
+ | `connectOctoBot(options)` | Connect to a node. Returns an `OctoBotClient`. |
77
+ | `strategy.dca/grid/marketMaking/copy/signal/index/genericProcess(input)` | Pure, zero-I/O strategy builders. |
78
+ | `strategy.build(input)` / `.toInput(strategy)` / `.bumpVersion(v)` | The discriminated-union entry point, its inverse, and version bumping. |
79
+ | `client.accounts.list/get/create/update/delete/refresh/trading` | Exchange, wallet, and generic accounts. |
80
+ | `client.automations.list/get/create/update/stop` | Running bots. |
81
+ | `client.strategies.list/get/create/update/delete` | Reconstructed from the action history — the node has no strategies collection of its own. |
82
+ | `client.settings.get/patch/replace` | An opaque document the node stores encrypted and never reads. |
83
+ | `client.node.status/tradedPairs/predictedOrderBook/requiredFunds/dslKeywords/exportWallet/createGenericProcessBot` | The node's direct REST API. The last three need `basicAuth`. |
84
+ | `client.documents.pull/push/append` + `.raw` | Escape hatch: any collection, the raw `StarfishClient`. |
85
+ | `client.close()` | Drops the derived-key cache. |
86
+ | `createReadOnlyPairing(seed, derivation, node)` | Mint a scoped, node-enforced read-only credential for a less-trusted device. See [Read-only devices](https://docs.octobot.cloud/client-sdk/read-only-pairing). |
87
+ | `connectReadOnlyDevice(pairingPayload)` | Connect with that credential instead of a seed. Write methods return a `ProposedAction` (build, don't send) instead of an `ActionHandle`. |
88
+ | `startPairingRequest(options)` / `fetchPairingRequestByCode({code, rendezvous})` | Website side: publish a device-code pairing request; phone side: look it up (returns `{request, hash}`). See [Website pairing](https://docs.octobot.cloud/client-sdk/website-pairing). |
89
+ | `mintPairingGrant(session, request)` / `publishPairingGrant(...)` | Phone side, on approval: invite the website's device into the cloud mirror as a read-only `space:member`, then seal and publish the grant. |
90
+ | `awaitPairingGrant(session, options)` / `fetchPairingGrant(session, options)` | Website side: wait for (or poll for) the grant, unseal it, and live-read the mirror collections it covers. |
91
+ | `revokePairingGrant(...)` / `clearPairingGrant(...)` | Unpair: remove the website's space membership and clear the rendezvous slot. |
92
+
93
+ ## Errors
94
+
95
+ Every `OctoBotClient`/`ReadOnlyOctoBotClient` method, and the `client/pairing/*` functions above
96
+ (`startPairingRequest`, `fetchPairingGrant`, etc.), throw an `OctoBotError` subclass (or let an
97
+ `AbortError` `DOMException` through unwrapped, per the platform convention). Switch on `.code`
98
+ rather than `instanceof` if you need the check to survive a duplicated package instance. Full
99
+ taxonomy, extra fields, and handling patterns: [Errors](https://docs.octobot.cloud/client-sdk/errors).
100
+ The two exceptions are the I/O-free `identity/pairingRequest.js` and `identity/pairing.js` pure
101
+ functions (`createPairingRequest`, `parsePairingRequest`, `createReadOnlyPairing`,
102
+ `parseReadOnlyPairing`) — they validate/build payloads only, never touch the network, and throw a
103
+ plain `Error` rather than an `OctoBotError`.
104
+
105
+ | Class | `code` | When |
106
+ |---|---|---|
107
+ | `OctoBotConfigError` | `'config'` | Bad `ConnectOptions` — unparseable `url`, or a `node.*` call made without `basicAuth`. |
108
+ | `OctoBotConnectionError` | `'unreachable' \| 'timeout' \| 'aborted'` | The node could not be reached. |
109
+ | `OctoBotAuthError` | `'unauthorized'` | The node answered but didn't authorize this wallet — carries `.address`/`.userId`/`.derivation` so you can see what was tried. |
110
+ | `OctoBotHttpError` | `'http'` | A node REST call answered non-2xx. Carries `.status`. |
111
+ | `OctoBotConflictError` | `'conflict'` | A document push raced another writer. Carries `.serverHash` — pull again and retry. |
112
+ | `OctoBotActionError` | `'action_failed'` | The node executed a queued action and rejected it. Not retriable by resubmitting unchanged. |
113
+ | `OctoBotTimeoutError` | `'action_timeout'` | `settled()` gave up waiting — the action may still complete. |
114
+ | `OctoBotScopeError` | `'forbidden_collection'` | A read-only session reached a collection outside its pairing grant — thrown client-side, before any request. |
115
+
116
+ ## Escape hatches
117
+
118
+ - **Custom `fetch`** — `ConnectOptions.fetch`, for proxies, mTLS, or a React Native polyfill.
119
+ - **`verify: false`** — skip the connect-time probe; `connectOctoBot()` does zero I/O and the first
120
+ real call surfaces any problem.
121
+ - **Raw documents** — `client.documents.pull/push/append` for any collection, typed loosely; and
122
+ `client.documents.raw` for the underlying `StarfishClient` and cap provider directly.
123
+ - **`seedDerivation: 'auto'`** — tries every registered derivation scheme and keeps whichever the
124
+ node authorizes.
125
+
126
+ Full detail: [Escape hatches](https://docs.octobot.cloud/client-sdk/escape-hatches).
127
+
128
+ ## Compatibility
129
+
130
+ | This package | `@drakkar.software/octobot-protocol` | Minimum node |
131
+ |---|---|---|
132
+ | `0.3.0` | `^0.6.0` | protocol 0.4.0 |
133
+
134
+ ## More
135
+
136
+ - [Client SDK docs](https://docs.octobot.cloud/client-sdk/getting-started) — one topic per page,
137
+ start with Getting Started.
138
+ - [`CHANGELOG.md`](CHANGELOG.md)
139
+ - [Wire contract](https://docs.octobot.cloud/client-sdk/wire-contract) — every literal string shared
140
+ with the node's Python implementation, for anyone changing either side.
@@ -0,0 +1,66 @@
1
+ import type { Account as ProtocolAccount, AccountAuthentication, ExchangeConfig, UserActionConfiguration } from '@drakkar.software/octobot-protocol';
2
+ import type { ClientSession } from '../core/session.js';
3
+ import type { CallOptions } from '../core/options.js';
4
+ import { type AccountView, type Holding } from '../core/views.js';
5
+ import { type ActionHandle } from './actionHandle.js';
6
+ export type { AccountView, AccountKind } from '../core/views.js';
7
+ export type { AccountTradingDocument } from '../../protocol/documents.js';
8
+ export type AccountInput = {
9
+ id?: string;
10
+ name: string;
11
+ type: 'exchange';
12
+ exchange: string;
13
+ credentials: {
14
+ apiKey: string;
15
+ apiSecret: string;
16
+ passphrase?: string;
17
+ };
18
+ simulated?: boolean;
19
+ holdings?: Holding[];
20
+ } | {
21
+ id?: string;
22
+ name: string;
23
+ type: 'wallet';
24
+ address: string;
25
+ chain?: string;
26
+ holdings?: Holding[];
27
+ } | {
28
+ id?: string;
29
+ name: string;
30
+ type: 'generic';
31
+ description?: string;
32
+ holdings?: Holding[];
33
+ };
34
+ /** The three protocol items one `AccountInput` maps to. `auth`/`exchangeConfig`
35
+ * are null for kinds that don't need them (a wallet/generic account still
36
+ * gets an `AccountAuthentication` carrying its address; only credentials
37
+ * proper are exchange-only). Exported for the read-only facade
38
+ * (`readOnly.ts`), which builds the same protocol items without appending
39
+ * them. */
40
+ export declare function toAccountGraph(input: AccountInput): {
41
+ account: ProtocolAccount;
42
+ auth: AccountAuthentication | null;
43
+ exchangeConfig: ExchangeConfig | null;
44
+ };
45
+ export interface AccountsApi {
46
+ list(opts?: CallOptions): Promise<AccountView[]>;
47
+ get(id: string, opts?: CallOptions): Promise<AccountView | null>;
48
+ create(input: AccountInput, opts?: CallOptions): Promise<ActionHandle<AccountView | null>>;
49
+ update(id: string, input: AccountInput, opts?: CallOptions): Promise<ActionHandle<AccountView | null>>;
50
+ /** The node does NOT cascade deletes — this emits `account_delete` plus
51
+ * the two companion deletes (auth, exchange config) itself. */
52
+ delete(id: string, opts?: CallOptions): Promise<ActionHandle<void>>;
53
+ refresh(ids?: string[], opts?: CallOptions): Promise<ActionHandle<AccountView[]>>;
54
+ trading(id: string, opts?: CallOptions): ReturnType<DocumentsApiTrading>;
55
+ }
56
+ type DocumentsApiTrading = (id: string, opts?: CallOptions) => Promise<import('../../protocol/documents.js').AccountTradingDocument | null>;
57
+ export type AppendAction = (configuration: UserActionConfiguration) => Promise<string>;
58
+ /** Pull the raw `accounts` collection document. Exported for the read-only
59
+ * facade (`readOnly.ts`), which needs an existing account's `created_at`
60
+ * when proposing an edit, same as `update()` below does. */
61
+ export declare function pullAccountsDocument(session: ClientSession): Promise<import("../../transport/documents.js").PulledDocument<{
62
+ accounts?: ProtocolAccount[];
63
+ exchange_configs?: ExchangeConfig[];
64
+ }>>;
65
+ export declare function createAccountsApi(session: ClientSession, appendAction: AppendAction): AccountsApi;
66
+ //# sourceMappingURL=accounts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["../../../src/client/adapters/accounts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,214 @@
1
+ import { accountViewOf } from '../core/views.js';
2
+ import { createActionHandle } from './actionHandle.js';
3
+ import { pullDocument } from '../../transport/documents.js';
4
+ import { accountAuthIdFor, exchangeConfigIdFor, buildCreateAccountConfig, buildEditAccountConfig, buildDeleteAccountConfig, buildRefreshAccountsConfig, buildCreateAccountAuthConfig, buildEditAccountAuthConfig, buildDeleteAccountAuthConfig, buildCreateExchangeConfigConfig, buildEditExchangeConfigConfig, buildDeleteExchangeConfigConfig, } from '../../protocol/actions.js';
5
+ import { rethrowAsOctoBotError } from '../core/errors.js';
6
+ const SPOT_TRADING_TYPE = 'spot';
7
+ function holdingsToAssets(holdings) {
8
+ if (!holdings?.length)
9
+ return undefined;
10
+ return [{
11
+ trading_type: SPOT_TRADING_TYPE,
12
+ assets: holdings.map((h) => ({ symbol: h.symbol, total: h.total, available: h.free })),
13
+ }];
14
+ }
15
+ function newAccountId() {
16
+ return `acc_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
17
+ }
18
+ /** The three protocol items one `AccountInput` maps to. `auth`/`exchangeConfig`
19
+ * are null for kinds that don't need them (a wallet/generic account still
20
+ * gets an `AccountAuthentication` carrying its address; only credentials
21
+ * proper are exchange-only). Exported for the read-only facade
22
+ * (`readOnly.ts`), which builds the same protocol items without appending
23
+ * them. */
24
+ export function toAccountGraph(input) {
25
+ const id = input.id ?? newAccountId();
26
+ const now = new Date().toISOString();
27
+ if (input.type === 'exchange') {
28
+ return {
29
+ account: {
30
+ id,
31
+ name: input.name,
32
+ is_simulated: Boolean(input.simulated),
33
+ created_at: now,
34
+ updated_at: now,
35
+ authentication_id: accountAuthIdFor(id),
36
+ specifics: { account_type: 'exchange', remote_account_id: '', exchange_config_ids: [exchangeConfigIdFor(id)] },
37
+ ...(holdingsToAssets(input.holdings) ? { assets: holdingsToAssets(input.holdings) } : {}),
38
+ },
39
+ auth: {
40
+ id: accountAuthIdFor(id),
41
+ api_key: input.credentials.apiKey,
42
+ api_secret: input.credentials.apiSecret,
43
+ ...(input.credentials.passphrase ? { api_passphrase: input.credentials.passphrase } : {}),
44
+ },
45
+ exchangeConfig: {
46
+ id: exchangeConfigIdFor(id),
47
+ name: input.name,
48
+ exchange: input.exchange,
49
+ sandboxed: Boolean(input.simulated),
50
+ },
51
+ };
52
+ }
53
+ if (input.type === 'wallet') {
54
+ return {
55
+ account: {
56
+ id,
57
+ name: input.name,
58
+ is_simulated: false,
59
+ created_at: now,
60
+ updated_at: now,
61
+ authentication_id: accountAuthIdFor(id),
62
+ specifics: { account_type: 'generic' },
63
+ ...(input.chain ? { description: input.chain } : {}),
64
+ ...(holdingsToAssets(input.holdings) ? { assets: holdingsToAssets(input.holdings) } : {}),
65
+ },
66
+ auth: { id: accountAuthIdFor(id), public_key: input.address },
67
+ exchangeConfig: null,
68
+ };
69
+ }
70
+ // 'generic' — no credentials, node has nothing to authenticate.
71
+ return {
72
+ account: {
73
+ id,
74
+ name: input.name,
75
+ is_simulated: false,
76
+ created_at: now,
77
+ updated_at: now,
78
+ specifics: { account_type: 'generic' },
79
+ ...(input.description ? { description: input.description } : {}),
80
+ ...(holdingsToAssets(input.holdings) ? { assets: holdingsToAssets(input.holdings) } : {}),
81
+ },
82
+ auth: null,
83
+ exchangeConfig: null,
84
+ };
85
+ }
86
+ /** Pull the raw `accounts` collection document. Exported for the read-only
87
+ * facade (`readOnly.ts`), which needs an existing account's `created_at`
88
+ * when proposing an edit, same as `update()` below does. */
89
+ export async function pullAccountsDocument(session) {
90
+ const encryptor = await session.collectionEncryptor('accounts');
91
+ return pullDocument(session.syncClient, 'accounts', { identity: session.userId }, encryptor);
92
+ }
93
+ export function createAccountsApi(session, appendAction) {
94
+ const pullAccounts = () => pullAccountsDocument(session);
95
+ async function list() {
96
+ try {
97
+ const { data } = await pullAccounts();
98
+ const configs = data.exchange_configs ?? [];
99
+ return (data.accounts ?? []).map((a) => accountViewOf(a, configs));
100
+ }
101
+ catch (err) {
102
+ rethrowAsOctoBotError(err);
103
+ }
104
+ }
105
+ async function get(id) {
106
+ const all = await list();
107
+ return all.find((a) => a.id === id) ?? null;
108
+ }
109
+ async function afterSettle(id) {
110
+ return get(id);
111
+ }
112
+ return {
113
+ list,
114
+ get,
115
+ async create(input) {
116
+ const { account, auth, exchangeConfig } = toAccountGraph(input);
117
+ const ids = [];
118
+ const work = (async () => {
119
+ if (auth)
120
+ ids.push(await appendAction(buildCreateAccountAuthConfig(auth)));
121
+ if (exchangeConfig)
122
+ ids.push(await appendAction(buildCreateExchangeConfigConfig(exchangeConfig)));
123
+ ids.push(await appendAction(buildCreateAccountConfig(account)));
124
+ return afterSettle(account.id);
125
+ })();
126
+ // ids[] is populated synchronously as `work` progresses; the handle
127
+ // reflects whatever has been appended by the time it's inspected.
128
+ return createActionHandle(session, ids, work);
129
+ },
130
+ async update(id, input) {
131
+ const ids = [];
132
+ const work = (async () => {
133
+ const { account, auth, exchangeConfig } = toAccountGraph({ ...input, id });
134
+ const existing = await pullAccounts()
135
+ .then(({ data }) => (data.accounts ?? []).find((a) => a.id === id))
136
+ .catch(() => undefined);
137
+ if (existing?.created_at)
138
+ account.created_at = existing.created_at;
139
+ // Credentials/exchange config are rotated BEFORE the account edit so
140
+ // the node's account re-validation reads the new keys, not the old ones.
141
+ if (auth)
142
+ ids.push(await appendAction(buildEditAccountAuthConfig(auth)));
143
+ if (exchangeConfig)
144
+ ids.push(await appendAction(buildEditExchangeConfigConfig(exchangeConfig)));
145
+ ids.push(await appendAction(buildEditAccountConfig(id, account)));
146
+ return afterSettle(id);
147
+ })();
148
+ return createActionHandle(session, ids, work);
149
+ },
150
+ async delete(id) {
151
+ const ids = [];
152
+ const work = (async () => {
153
+ // Which companion deletes actually apply depends on account kind —
154
+ // a 'generic' account has no AccountAuthentication at all
155
+ // (toAccountGraph: auth: null), and an ExchangeConfig only exists
156
+ // when `specifics.exchange_config_ids` is actually populated (every
157
+ // AccountSpecifics variant, including 'blockchain', CAN carry it —
158
+ // this is not exclusive to 'exchange'). Emitting a delete for a
159
+ // companion that was never created queues a guaranteed non-retriable
160
+ // failed action on the node (it deletes-by-id; the id never
161
+ // existed). Pulling first to check is the same pattern update()
162
+ // already uses for created_at.
163
+ //
164
+ // If the pull itself fails (network blip, decrypt error — NOT "the
165
+ // account doesn't exist"), `existing` is undefined and we can't tell
166
+ // which companions exist. Defaulting to "delete nothing but the
167
+ // account" would silently orphan real credentials on the node with
168
+ // no error surfaced anywhere — worse than the bug being fixed here.
169
+ // Fall back to the old unconditional-three behavior instead: a
170
+ // delete for a companion that never existed is a harmless failed
171
+ // action, not a data leak.
172
+ let existing;
173
+ let pullFailed = false;
174
+ try {
175
+ const { data } = await pullAccounts();
176
+ existing = (data.accounts ?? []).find((a) => a.id === id);
177
+ }
178
+ catch {
179
+ pullFailed = true;
180
+ }
181
+ const specifics = existing?.specifics;
182
+ const hasAuth = pullFailed || Boolean(existing?.authentication_id);
183
+ const hasExchangeConfig = pullFailed || (specifics !== undefined && 'exchange_config_ids' in specifics && (specifics.exchange_config_ids?.length ?? 0) > 0);
184
+ ids.push(await appendAction(buildDeleteAccountConfig(id)));
185
+ if (hasAuth) {
186
+ ids.push(await appendAction(buildDeleteAccountAuthConfig(accountAuthIdFor(id))));
187
+ }
188
+ if (hasExchangeConfig) {
189
+ ids.push(await appendAction(buildDeleteExchangeConfigConfig(exchangeConfigIdFor(id))));
190
+ }
191
+ })();
192
+ return createActionHandle(session, ids, work);
193
+ },
194
+ async refresh(accountIds) {
195
+ const ids = [];
196
+ const work = (async () => {
197
+ ids.push(await appendAction(buildRefreshAccountsConfig(accountIds)));
198
+ return list();
199
+ })();
200
+ return createActionHandle(session, ids, work);
201
+ },
202
+ async trading(id) {
203
+ try {
204
+ const encryptor = await session.collectionEncryptor('accountTrading');
205
+ const { data } = await pullDocument(session.syncClient, 'accountTrading', { identity: session.userId, accountId: id }, encryptor);
206
+ return data;
207
+ }
208
+ catch (err) {
209
+ rethrowAsOctoBotError(err);
210
+ }
211
+ },
212
+ };
213
+ }
214
+ //# sourceMappingURL=accounts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accounts.js","sourceRoot":"","sources":["../../../src/client/adapters/accounts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { UserAction } from '@drakkar.software/octobot-protocol';
2
+ import type { ClientSession } from '../core/session.js';
3
+ import type { CallOptions } from '../core/options.js';
4
+ export interface ActionHandle<T = void> {
5
+ /** Action ids appended so far. For a multi-phase operation (e.g.
6
+ * `automations.create`, which emits a strategy action before the
7
+ * automation action) this grows as each phase starts. */
8
+ readonly ids: readonly string[];
9
+ /** Resolves once the node reports every phase completed. Memoized — safe
10
+ * to await twice, from different call sites, without double-polling.
11
+ * The underlying work started the moment the method that returned this
12
+ * handle returned (tuning like `timeoutMs`/`onProgress` belongs on THAT
13
+ * call, not here) — a caller who never awaits `settled()` still leaves
14
+ * nothing half-done, it just won't know the outcome.
15
+ * Rejects with `OctoBotActionError` (the node rejected an action) or
16
+ * `OctoBotTimeoutError` (the node never confirmed in time). */
17
+ settled(): Promise<T>;
18
+ /** One-shot, non-blocking read of the node's current verdict for `ids` —
19
+ * does not wait, does not affect the in-flight `settled()` work. */
20
+ status(opts?: CallOptions): Promise<{
21
+ settled: boolean;
22
+ actions: UserAction[];
23
+ }>;
24
+ }
25
+ /** Wrap an already-started promise (and the action ids it's driving) as a
26
+ * public `ActionHandle`. `work` must already be running — see the
27
+ * `settled()` doc comment on why eager-start matters. */
28
+ export declare function createActionHandle<T>(session: ClientSession, ids: readonly string[], work: Promise<T>): ActionHandle<T>;
29
+ //# sourceMappingURL=actionHandle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actionHandle.d.ts","sourceRoot":"","sources":["../../../src/client/adapters/actionHandle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAA;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAKrD,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,IAAI;IACpC;;8DAE0D;IAC1D,QAAQ,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,CAAA;IAC/B;;;;;;;oEAOgE;IAChE,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,CAAA;IACrB;yEACqE;IACrE,MAAM,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,UAAU,EAAE,CAAA;KAAE,CAAC,CAAA;CACjF;AAED;;0DAE0D;AAC1D,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,OAAO,EAAE,aAAa,EACtB,GAAG,EAAE,SAAS,MAAM,EAAE,EACtB,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GACf,YAAY,CAAC,CAAC,CAAC,CAiCjB"}
@@ -0,0 +1,34 @@
1
+ import { pullDocument } from '../../transport/documents.js';
2
+ import { parseNodeUserActions } from '../../protocol/state.js';
3
+ import { rethrowAsOctoBotError } from '../core/errors.js';
4
+ /** Wrap an already-started promise (and the action ids it's driving) as a
5
+ * public `ActionHandle`. `work` must already be running — see the
6
+ * `settled()` doc comment on why eager-start matters. */
7
+ export function createActionHandle(session, ids, work) {
8
+ // Attach a no-op rejection handler so an unawaited handle never surfaces
9
+ // an unhandled promise rejection — settled() still gets the real outcome.
10
+ work.catch(() => undefined);
11
+ return {
12
+ ids,
13
+ settled: () => work.catch((err) => rethrowAsOctoBotError(err)),
14
+ async status(_opts) {
15
+ try {
16
+ const encryptor = await session.collectionEncryptor('userData');
17
+ const { data } = await pullDocument(session.syncClient, 'userData', { identity: session.userId }, encryptor);
18
+ const nodeActions = parseNodeUserActions(data);
19
+ const actions = nodeActions.filter((a) => ids.includes(a.id));
20
+ // `ids.length > 0` matters: before any phase has appended,
21
+ // `ids` is still `[]`, making `actions.length === ids.length` true
22
+ // (0 === 0) and `[].every(...)` vacuously true — without this guard
23
+ // a caller polling status() immediately after getting a handle back
24
+ // would see `settled: true` before a single action exists.
25
+ const settledAll = ids.length > 0 && actions.length === ids.length && actions.every((a) => a.status === 'completed' || a.status === 'failed');
26
+ return { settled: settledAll, actions };
27
+ }
28
+ catch (err) {
29
+ rethrowAsOctoBotError(err);
30
+ }
31
+ },
32
+ };
33
+ }
34
+ //# sourceMappingURL=actionHandle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actionHandle.js","sourceRoot":"","sources":["../../../src/client/adapters/actionHandle.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAqBzD;;0DAE0D;AAC1D,MAAM,UAAU,kBAAkB,CAChC,OAAsB,EACtB,GAAsB,EACtB,IAAgB;IAEhB,yEAAyE;IACzE,0EAA0E;IAC1E,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAA;IAE3B,OAAO;QACL,GAAG;QACH,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC;QAC9D,KAAK,CAAC,MAAM,CAAC,KAAmB;YAC9B,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAA;gBAC/D,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,YAAY,CACjC,OAAO,CAAC,UAAU,EAClB,UAAU,EACV,EAAE,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE,EAC5B,SAAS,CACV,CAAA;gBACD,MAAM,WAAW,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAA;gBAC9C,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;gBAC7D,2DAA2D;gBAC3D,mEAAmE;gBACnE,oEAAoE;gBACpE,oEAAoE;gBACpE,2DAA2D;gBAC3D,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,OAAO,CAAC,KAAK,CACjF,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,IAAI,CAAC,CAAC,MAAM,KAAK,QAAQ,CACzD,CAAA;gBACD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,CAAA;YACzC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,qBAAqB,CAAC,GAAG,CAAC,CAAA;YAC5B,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,31 @@
1
+ import type { Strategy as ProtocolStrategy } from '@drakkar.software/octobot-protocol';
2
+ import type { ClientSession } from '../core/session.js';
3
+ import type { CallOptions } from '../core/options.js';
4
+ import type { AppendAction } from './accounts.js';
5
+ import { type AutomationView } from '../core/views.js';
6
+ import { type ActionHandle } from './actionHandle.js';
7
+ import { type CreateAutomationProgress } from '../../protocol/orchestration/createAutomation.js';
8
+ export type { AutomationView, CreateAutomationProgress };
9
+ export type CreateAutomationInput = {
10
+ name: string;
11
+ description?: string;
12
+ strategy: ProtocolStrategy;
13
+ accountIds: string[];
14
+ };
15
+ export interface AutomationsApi {
16
+ list(opts?: CallOptions): Promise<AutomationView[]>;
17
+ get(id: string, opts?: CallOptions): Promise<AutomationView | null>;
18
+ /** Two-phase under the hood: `strategy_create` is appended and confirmed
19
+ * BEFORE `automation_create` is appended, avoiding a node-side race where
20
+ * the automation would resolve its strategy before the node's
21
+ * StrategyProvider had registered it. See `protocol/orchestration/createAutomation.ts`. */
22
+ create(input: CreateAutomationInput, opts?: {
23
+ onProgress?: (p: CreateAutomationProgress) => void;
24
+ timeoutMs?: number;
25
+ signal?: AbortSignal;
26
+ }): Promise<ActionHandle<AutomationView | null>>;
27
+ update(id: string, input: CreateAutomationInput, opts?: CallOptions): Promise<ActionHandle<AutomationView | null>>;
28
+ stop(id: string, opts?: CallOptions): Promise<ActionHandle<void>>;
29
+ }
30
+ export declare function createAutomationsApi(session: ClientSession, appendAction: AppendAction): AutomationsApi;
31
+ //# sourceMappingURL=automations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"automations.d.ts","sourceRoot":"","sources":["../../../src/client/adapters/automations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,IAAI,gBAAgB,EAAc,MAAM,oCAAoC,CAAA;AAClG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAoB,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACxE,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAIzE,OAAO,EAA2C,KAAK,wBAAwB,EAAE,MAAM,kDAAkD,CAAA;AAGzI,YAAY,EAAE,cAAc,EAAE,wBAAwB,EAAE,CAAA;AAExD,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB,CAAA;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAA;IACnD,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAA;IACnE;;;gGAG4F;IAC5F,MAAM,CAAC,KAAK,EAAE,qBAAqB,EAAE,IAAI,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,wBAAwB,KAAK,IAAI,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC,CAAA;IAC3L,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,qBAAqB,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC,CAAA;IAClH,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAA;CAClE;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,GAAG,cAAc,CA0EvG"}
@@ -0,0 +1,79 @@
1
+ import { automationViewOf } from '../core/views.js';
2
+ import { createActionHandle } from './actionHandle.js';
3
+ import { pullDocument } from '../../transport/documents.js';
4
+ import { parseNodeAutomationStates, parseNodeUserActions } from '../../protocol/state.js';
5
+ import { buildEditAutomationConfig, buildEditStrategyConfig, buildStopAutomationConfig } from '../../protocol/actions.js';
6
+ import { runCreateAutomation } from '../../protocol/orchestration/createAutomation.js';
7
+ import { rethrowAsOctoBotError } from '../core/errors.js';
8
+ export function createAutomationsApi(session, appendAction) {
9
+ async function pullUserData() {
10
+ const encryptor = await session.collectionEncryptor('userData');
11
+ return pullDocument(session.syncClient, 'userData', { identity: session.userId }, encryptor);
12
+ }
13
+ async function listWithActions() {
14
+ const { data } = await pullUserData();
15
+ const states = parseNodeAutomationStates(data);
16
+ const actions = parseNodeUserActions(data);
17
+ return { views: states.map((s) => automationViewOf(s, actions)), actions };
18
+ }
19
+ async function list() {
20
+ try {
21
+ return (await listWithActions()).views;
22
+ }
23
+ catch (err) {
24
+ rethrowAsOctoBotError(err);
25
+ }
26
+ }
27
+ async function get(id) {
28
+ const all = await list();
29
+ return all.find((a) => a.id === id) ?? null;
30
+ }
31
+ const emitter = {
32
+ emit: (configuration) => appendAction(configuration),
33
+ poll: async () => {
34
+ const { data } = await pullUserData();
35
+ return parseNodeUserActions(data);
36
+ },
37
+ };
38
+ return {
39
+ list,
40
+ get,
41
+ async create(input, opts) {
42
+ const ids = [];
43
+ const io = {
44
+ emit: async (configuration) => {
45
+ const id = await emitter.emit(configuration);
46
+ ids.push(id);
47
+ return id;
48
+ },
49
+ poll: emitter.poll,
50
+ };
51
+ const buildInput = input;
52
+ const work = runCreateAutomation(io, buildInput, {
53
+ onProgress: opts?.onProgress,
54
+ timeoutMs: opts?.timeoutMs,
55
+ signal: opts?.signal,
56
+ }).then(({ automationId }) => (automationId ? get(automationId) : null));
57
+ return createActionHandle(session, ids, work);
58
+ },
59
+ async update(id, input) {
60
+ const ids = [];
61
+ const work = (async () => {
62
+ // Same strategy id, bumped version: the node treats strategy items
63
+ // as replace-by-id, so edits flow through strategy_edit.
64
+ ids.push(await appendAction(buildEditStrategyConfig(input.strategy)));
65
+ ids.push(await appendAction(buildEditAutomationConfig({ ...input, automationId: id })));
66
+ return get(id);
67
+ })();
68
+ return createActionHandle(session, ids, work);
69
+ },
70
+ async stop(id) {
71
+ const ids = [];
72
+ const work = (async () => {
73
+ ids.push(await appendAction(buildStopAutomationConfig(id)));
74
+ })();
75
+ return createActionHandle(session, ids, work);
76
+ },
77
+ };
78
+ }
79
+ //# sourceMappingURL=automations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"automations.js","sourceRoot":"","sources":["../../../src/client/adapters/automations.ts"],"names":[],"mappings":"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"}