├── .editorconfig
├── .env
├── .eslintrc.js
├── .gitignore
├── .prettierrc.js
├── .stylelintrc.js
├── README.md
├── antd-theme
└── theme.less
├── config
├── env.js
├── jest
│ ├── cssTransform.js
│ └── fileTransform.js
├── paths.js
├── polyfills.js
├── webpack.config.dev.js
├── webpack.config.prod.js
└── webpackDevServer.config.js
├── lang
├── cn.json
├── en.json
└── index.js
├── package.json
├── public
├── charting_library
│ ├── charting_library.min.d.ts
│ ├── charting_library.min.js
│ ├── datafeed-api.d.ts
│ └── static
│ │ ├── ar-tv-chart.4983fae3fbe165749507.html
│ │ ├── bundles
│ │ ├── 10.5fc4bebecf627d0a0f2f.js
│ │ ├── 13.44339b003e12eadcd24e.js
│ │ ├── 15.14e44c9fe762e0c75635.js
│ │ ├── 9.8309436d1561a99a7fad.js
│ │ ├── crosshair.6c091f7d5427d0c5e6d9dc3a90eb2b20.cur
│ │ ├── dot.ed68e83c16f77203e73dbc4c3a7c7fa1.cur
│ │ ├── ds-property-pages.bfd2564e4fd770bc0b0c.js
│ │ ├── editobjectdialog.c39226f8a9a3231aef9a.js
│ │ ├── eraser.0579d40b812fa2c3ffe72e5803a6e14c.cur
│ │ ├── go-to-date-dialog-impl.c121ad9ddaf13331c500.js
│ │ ├── grab.bc156522a6b55a60be9fae15c14b66c5.cur
│ │ ├── grabbing.1c0862a8a8c0fb02885557bc97fdafe7.cur
│ │ ├── ie-fallback-logos.8319ee6d7ee230348d2d.js
│ │ ├── lazy-jquery-ui.e4174a65a8360a06f2da.js
│ │ ├── lazy-velocity.832705322dfa540785f6.js
│ │ ├── library.5dad2b9a34c29a058bba.js
│ │ ├── library.d8f5cc7dfd69730985ef782d21a1321f.css
│ │ ├── lt-pane-views.7df9edb244fbdda2ee13.js
│ │ ├── objecttreedialog.33adfe386aa3612bb60e.js
│ │ ├── propertypagesfactory.37bd38e8744b0cc04a07.js
│ │ ├── symbol-info-dialog-impl.eba97409764f2b04ac83.js
│ │ ├── take-chart-image-dialog-impl.b60665314521ef3361a1.js
│ │ ├── vendors.a94ef44ed5c201cefcf6ad7460788c1a.css
│ │ ├── vendors.f495e82849a430ceb659.js
│ │ └── zoom.e21f24dd632c7069139bc47ae89c54b5.cur
│ │ ├── cs-tv-chart.4983fae3fbe165749507.html
│ │ ├── da_DK-tv-chart.4983fae3fbe165749507.html
│ │ ├── de-tv-chart.4983fae3fbe165749507.html
│ │ ├── el-tv-chart.4983fae3fbe165749507.html
│ │ ├── en-tv-chart.4983fae3fbe165749507.html
│ │ ├── es-tv-chart.4983fae3fbe165749507.html
│ │ ├── et_EE-tv-chart.4983fae3fbe165749507.html
│ │ ├── fa-tv-chart.4983fae3fbe165749507.html
│ │ ├── fonts
│ │ ├── fontawesome-webfont.svg
│ │ ├── fontawesome-webfont.ttf
│ │ └── fontawesome-webfont.woff
│ │ ├── fr-tv-chart.4983fae3fbe165749507.html
│ │ ├── he_IL-tv-chart.4983fae3fbe165749507.html
│ │ ├── hu_HU-tv-chart.4983fae3fbe165749507.html
│ │ ├── id_ID-tv-chart.4983fae3fbe165749507.html
│ │ ├── images
│ │ ├── balloon.png
│ │ ├── bar-loader.gif
│ │ ├── button-bg.png
│ │ ├── charting_library
│ │ │ ├── logo-widget-copyright-faded.png
│ │ │ └── logo-widget-copyright.png
│ │ ├── controlll.png
│ │ ├── delayed.png
│ │ ├── dialogs
│ │ │ ├── checkbox.png
│ │ │ ├── close-flat.png
│ │ │ ├── large-slider-handle.png
│ │ │ ├── linewidth-slider.png
│ │ │ └── opacity-slider.png
│ │ ├── icons.png
│ │ ├── prediction-clock-black.png
│ │ ├── prediction-clock-white.png
│ │ ├── prediction-failure-white.png
│ │ ├── prediction-success-white.png
│ │ ├── select-bg.png
│ │ ├── sidetoolbar
│ │ │ ├── instruments.png
│ │ │ └── toolgroup.png
│ │ ├── svg
│ │ │ ├── chart
│ │ │ │ ├── bucket2.svg
│ │ │ │ ├── font.svg
│ │ │ │ ├── large-slider-handle.svg
│ │ │ │ └── pencil2.svg
│ │ │ └── question-mark-rounded.svg
│ │ ├── tvcolorpicker-bg-gradient.png
│ │ ├── tvcolorpicker-bg.png
│ │ ├── tvcolorpicker-check.png
│ │ ├── tvcolorpicker-sprite.png
│ │ └── warning-icon.png
│ │ ├── it-tv-chart.4983fae3fbe165749507.html
│ │ ├── ja-tv-chart.4983fae3fbe165749507.html
│ │ ├── ko-tv-chart.4983fae3fbe165749507.html
│ │ ├── lib
│ │ └── external
│ │ │ └── spin.min.js
│ │ ├── ms_MY-tv-chart.4983fae3fbe165749507.html
│ │ ├── nl_NL-tv-chart.4983fae3fbe165749507.html
│ │ ├── no-tv-chart.4983fae3fbe165749507.html
│ │ ├── pl-tv-chart.4983fae3fbe165749507.html
│ │ ├── pt-tv-chart.4983fae3fbe165749507.html
│ │ ├── ro-tv-chart.4983fae3fbe165749507.html
│ │ ├── ru-tv-chart.4983fae3fbe165749507.html
│ │ ├── sk_SK-tv-chart.4983fae3fbe165749507.html
│ │ ├── sv-tv-chart.4983fae3fbe165749507.html
│ │ ├── th-tv-chart.4983fae3fbe165749507.html
│ │ ├── tr-tv-chart.4983fae3fbe165749507.html
│ │ ├── vi-tv-chart.4983fae3fbe165749507.html
│ │ ├── zh-tv-chart.4983fae3fbe165749507.html
│ │ └── zh_TW-tv-chart.4983fae3fbe165749507.html
├── datafeeds
│ ├── README.md
│ └── udf
│ │ ├── .npmrc
│ │ ├── README.md
│ │ ├── dist
│ │ ├── bundle.js
│ │ └── polyfills.js
│ │ ├── lib
│ │ ├── data-pulse-provider.js
│ │ ├── helpers.js
│ │ ├── history-provider.js
│ │ ├── iquotes-provider.js
│ │ ├── quotes-provider.js
│ │ ├── quotes-pulse-provider.js
│ │ ├── requester.js
│ │ ├── symbols-storage.js
│ │ ├── udf-compatible-datafeed-base.js
│ │ └── udf-compatible-datafeed.js
│ │ ├── package.json
│ │ ├── rollup.config.js
│ │ ├── src
│ │ ├── data-pulse-provider.ts
│ │ ├── helpers.ts
│ │ ├── history-provider.ts
│ │ ├── iquotes-provider.ts
│ │ ├── polyfills.es6
│ │ ├── quotes-provider.ts
│ │ ├── quotes-pulse-provider.ts
│ │ ├── requester.ts
│ │ ├── symbols-storage.ts
│ │ ├── udf-compatible-datafeed-base.ts
│ │ └── udf-compatible-datafeed.ts
│ │ └── tsconfig.json
├── favicon.ico
├── index.html
└── manifest.json
├── scripts
├── build.js
├── start.js
└── test.js
├── server
├── config.js
├── controller
│ ├── kline.js
│ └── user.js
├── index.js
├── mock
│ ├── index.js
│ ├── kline.js
│ └── lib
│ │ └── utils.js
├── router
│ ├── exchange.js
│ ├── index.js
│ └── user.js
└── socket.js
├── src
├── actions
│ ├── exchangeActions.js
│ ├── globalActions.js
│ ├── index.js
│ └── userActions.js
├── components
│ └── Layout
│ │ ├── LayoutView.js
│ │ ├── LayoutView.scss
│ │ └── index.js
├── history.js
├── index.js
├── pages
│ └── Exchange
│ │ ├── Deals
│ │ ├── DealsView.js
│ │ ├── DealsView.scss
│ │ └── index.js
│ │ ├── Depth
│ │ ├── DepthView.js
│ │ ├── DepthView.scss
│ │ └── index.js
│ │ ├── Footer
│ │ ├── Footer.scss
│ │ └── index.js
│ │ ├── Grid
│ │ ├── GridView.js
│ │ └── GridView.scss
│ │ ├── Header
│ │ ├── Header.scss
│ │ └── index.js
│ │ ├── KLine
│ │ ├── KLineView.js
│ │ ├── KLineView.scss
│ │ └── index.js
│ │ ├── Markets
│ │ ├── List.js
│ │ ├── MarketsView.js
│ │ ├── MarketsView.scss
│ │ └── index.js
│ │ ├── Mscy
│ │ ├── Mscy.js
│ │ ├── Mscy.scss
│ │ └── package.json
│ │ ├── Notice
│ │ ├── Notice.js
│ │ ├── Notice.scss
│ │ └── package.json
│ │ ├── Orders
│ │ ├── OrdersView.js
│ │ ├── OrdersView.scss
│ │ └── index.js
│ │ ├── TradePanel
│ │ ├── Limit.js
│ │ ├── Market.js
│ │ ├── TradePanel.scss
│ │ └── index.js
│ │ ├── assets
│ │ └── logo.svg
│ │ ├── common.scss
│ │ └── index.js
├── reducers
│ ├── exchangeReducer.js
│ ├── index.js
│ └── userReducer.js
├── registerServiceWorker.js
├── sagas
│ ├── exchangeActions.js
│ ├── index.js
│ └── userActions.js
├── services
│ ├── connection.js
│ ├── constants.js
│ ├── language.js
│ └── lib
│ │ └── re-websocket.js
├── store.js
└── utils
│ ├── common.js
│ └── converter.js
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # http://editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 |
9 | # Change these settings to your own preference
10 | indent_style = space
11 | indent_size = 2
12 |
13 | # We recommend you to keep these unchanged
14 | end_of_line = lf
15 | charset = utf-8
16 | trim_trailing_whitespace = true
17 | insert_final_newline = true
18 |
19 | # editorconfig-tools is unable to ignore longs strings or urls
20 | max_line_length = null
21 |
--------------------------------------------------------------------------------
/.env:
--------------------------------------------------------------------------------
1 | GENERATE_SOURCEMAP=true
2 | REACT_APP_API=http://localhost:8000/api
3 | REACT_APP_WS=ws://localhost:8000/ws
4 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "env": {
3 | "browser": true,
4 | "commonjs": true,
5 | "es6": true,
6 | "node": true
7 | },
8 | "extends": [
9 | "eslint:recommended",
10 | "react-app",
11 | 'plugin:css-modules/recommended',
12 | 'prettier',
13 | 'prettier/flowtype',
14 | 'prettier/react',
15 | ],
16 | "parserOptions": {
17 | "ecmaFeatures": {
18 | "experimentalObjectRestSpread": true,
19 | "jsx": true
20 | },
21 | "sourceType": "module"
22 | },
23 | "plugins": [
24 | "react", 'css-modules', 'prettier'
25 | ],
26 | "rules": {
27 | "css-modules/no-unused-class": [1, { "camelCase": true }],
28 | "css-modules/no-undef-class": [1, { "camelCase": true }],
29 | 'prettier/prettier': 'error',
30 | 'no-console': [
31 | 0,
32 | {
33 | allow: ['warn', 'error', 'info'],
34 | },
35 | ],
36 | 'no-undef': 0,
37 | 'jsx-a11y/href-no-hash': 'off',
38 | }
39 | };
40 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # webstorm
13 | .idea
14 |
15 | # node-sass-chokidar
16 | src/**/*.css
17 |
18 | # misc
19 | .DS_Store
20 | .env.local
21 | .env.development.local
22 | .env.test.local
23 | .env.production.local
24 |
25 | npm-debug.log*
26 | yarn-debug.log*
27 | yarn-error.log*
28 |
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | // Prettier configuration
2 | // https://prettier.io/docs/en/configuration.html
3 | module.exports = {
4 | semi: true,
5 | printWidth: 80,
6 | singleQuote: true,
7 | trailingComma: 'all',
8 | };
9 |
--------------------------------------------------------------------------------
/.stylelintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "extends": "stylelint-config-standard",
3 | "plugins": [
4 | "stylelint-order"
5 | ],
6 | "rules": {
7 | "string-quotes": "single",
8 | "number-leading-zero": "never",
9 | "property-no-unknown": [
10 | true,
11 | {
12 | "ignoreProperties": [
13 | "composes"
14 | ]
15 | }
16 | ],
17 | "selector-pseudo-class-no-unknown": [
18 | true,
19 | {
20 | "ignorePseudoClasses": [
21 | "global"
22 | ]
23 | }
24 | ],
25 | "order/order": [
26 | "declarations",
27 | "custom-properties",
28 | "dollar-variables",
29 | "rules",
30 | "at-rules"
31 | ],
32 | "order/properties-order": [
33 | "position",
34 | "top",
35 | "right",
36 | "bottom",
37 | "left",
38 | "float",
39 | "clear",
40 | "display",
41 | "flex",
42 | "flex-grow",
43 | "flex-shrink",
44 | "flex-basis",
45 | "flex-flow",
46 | "flex-direction",
47 | "flex-wrap",
48 | "justify-content",
49 | "align-content",
50 | "align-items",
51 | "align-self",
52 | "order",
53 | "grid",
54 | "grid-template-rows",
55 | "grid-template-columns",
56 | "grid-template-areas",
57 | "grid-auto-rows",
58 | "grid-auto-columns",
59 | "grid-auto-flow",
60 | "grid-column-gap",
61 | "grid-row-gap",
62 | "grid-template",
63 | "grid-template-rows",
64 | "grid-template-columns",
65 | "grid-template-areas",
66 | "grid-gap",
67 | "grid-row-gap",
68 | "grid-column-gap",
69 | "grid-area",
70 | "grid-row-start",
71 | "grid-row-end",
72 | "grid-column-start",
73 | "grid-column-end",
74 | "grid-column",
75 | "grid-column-start",
76 | "grid-column-end",
77 | "grid-row",
78 | "grid-row-start",
79 | "grid-row-end",
80 | "table-layout",
81 | "empty-cells",
82 | "caption-side",
83 | "border-collapse",
84 | "border-spacing",
85 | "list-style",
86 | "list-style-type",
87 | "list-style-position",
88 | "list-style-image",
89 | "ruby-align",
90 | "ruby-merge",
91 | "ruby-position",
92 | "box-sizing",
93 | "width",
94 | "min-width",
95 | "max-width",
96 | "height",
97 | "min-height",
98 | "max-height",
99 | "padding",
100 | "padding-top",
101 | "padding-right",
102 | "padding-bottom",
103 | "padding-left",
104 | "border",
105 | "border-width",
106 | "border-top-width",
107 | "border-right-width",
108 | "border-bottom-width",
109 | "border-left-width",
110 | "border-style",
111 | "border-top-style",
112 | "border-right-style",
113 | "border-bottom-style",
114 | "border-left-style",
115 | "border-color",
116 | "border-top-color",
117 | "border-right-color",
118 | "border-bottom-color",
119 | "border-left-color",
120 | "border-image",
121 | "border-image-source",
122 | "border-image-slice",
123 | "border-image-width",
124 | "border-image-outset",
125 | "border-image-repeat",
126 | "border-top",
127 | "border-top-width",
128 | "border-top-style",
129 | "border-top-color",
130 | "border-top",
131 | "border-right-width",
132 | "border-right-style",
133 | "border-right-color",
134 | "border-bottom",
135 | "border-bottom-width",
136 | "border-bottom-style",
137 | "border-bottom-color",
138 | "border-left",
139 | "border-left-width",
140 | "border-left-style",
141 | "border-left-color",
142 | "border-radius",
143 | "border-top-right-radius",
144 | "border-bottom-right-radius",
145 | "border-bottom-left-radius",
146 | "border-top-left-radius",
147 | "outline",
148 | "outline-width",
149 | "outline-color",
150 | "outline-style",
151 | "outline-offset",
152 | "margin",
153 | "margin-top",
154 | "margin-right",
155 | "margin-bottom",
156 | "margin-left",
157 | "color",
158 | "background",
159 | "background-image",
160 | "background-position",
161 | "background-size",
162 | "background-repeat",
163 | "background-origin",
164 | "background-clip",
165 | "background-attachment",
166 | "background-color",
167 | "background-blend-mode",
168 | "isolation",
169 | "clip-path",
170 | "mask",
171 | "mask-image",
172 | "mask-mode",
173 | "mask-position",
174 | "mask-size",
175 | "mask-repeat",
176 | "mask-origin",
177 | "mask-clip",
178 | "mask-composite",
179 | "mask-type",
180 | "filter",
181 | "box-shadow",
182 | "opacity",
183 | "visibility",
184 | "overflow",
185 | "overflow-x",
186 | "overflow-y",
187 | "vertical-align",
188 | "columns",
189 | "columns-width",
190 | "columns-count",
191 | "column-rule",
192 | "column-rule-width",
193 | "column-rule-style",
194 | "column-rule-color",
195 | "column-fill",
196 | "column-span",
197 | "column-gap",
198 | "orphans",
199 | "writing-mode",
200 | "text-combine-upright",
201 | "unicode-bidi",
202 | "text-orientation",
203 | "direction",
204 | "text-rendering",
205 | "font-feature-settings",
206 | "font-language-override",
207 | "font",
208 | "font-style",
209 | "font-variant",
210 | "font-weight",
211 | "font-stretch",
212 | "font-size",
213 | "font-family",
214 | "line-height",
215 | "text-overflow",
216 | "white-space",
217 | "overflow-wrap",
218 | "word-wrap",
219 | "word-break",
220 | "line-break",
221 | "hyphens",
222 | "text-align",
223 | "text-align-last",
224 | "text-justify",
225 | "font-synthesis",
226 | "font-size-adjust",
227 | "letter-spacing",
228 | "font-kerning",
229 | "word-spacing",
230 | "text-transform",
231 | "quotes",
232 | "tab-size",
233 | "text-indent",
234 | "text-emphasis",
235 | "text-emphasis-style",
236 | "text-emphasis-color",
237 | "text-emphasis-position",
238 | "text-decoration",
239 | "text-decoration-color",
240 | "text-decoration-style",
241 | "text-decoration-line",
242 | "text-underline-position",
243 | "text-shadow",
244 | "image-rendering",
245 | "image-orientation",
246 | "image-resolution",
247 | "shape-image-threshold",
248 | "shape-outside",
249 | "shape-margin",
250 | "transform-style",
251 | "transform",
252 | "transform-box",
253 | "transform-origin",
254 | "perspective",
255 | "perspective-origin",
256 | "backface-visibility",
257 | "transition",
258 | "transition-property",
259 | "transition-duration",
260 | "transition-timing-function",
261 | "transition-delay",
262 | "animation",
263 | "animation-name",
264 | "animation-duration",
265 | "animation-timing-function",
266 | "animation-delay",
267 | "animation-iteration-count",
268 | "animation-direction",
269 | "animation-fill-mode",
270 | "animation-play-state",
271 | "scroll-behavior",
272 | "scroll-snap-type",
273 | "scroll-snap-destination",
274 | "scroll-snap-coordinate",
275 | "resize",
276 | "cursor",
277 | "touch-action",
278 | "caret-color",
279 | "ime-mode",
280 | "object-fit",
281 | "object-position",
282 | "content",
283 | "counter-reset",
284 | "counter-increment",
285 | "will-change",
286 | "pointer-events",
287 | "z-index",
288 | "all",
289 | "page-break-before",
290 | "page-break-after",
291 | "page-break-inside",
292 | "widows"
293 | ],
294 | }
295 | };
296 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 对不起大伙,这个区块链前端项目我停止更新了。sorry sorry sorry。
2 |
3 | 仿火币交易所,要做的东西比较多,一点点更新。最终要实现typescript、服务端渲染、完整流程的交易所。
4 |
5 | ## 预置命令
6 |
7 | 安装
8 | ```shell
9 | $ yarn install
10 | ```
11 |
12 | 运行
13 | ```shell
14 | $ yarn start
15 | ```
16 |
17 | 带调试(sourcemap和css原命名)打包
18 | ```shell
19 | $ yarn build
20 | ```
21 |
22 | 启动伪服务端(提供http和ws测试数据)
23 | ```shell
24 | $ yarn fake-server
25 | ```
26 |
27 | 产品打包
28 | ```shell
29 | $ yarn build:release
30 | ```
31 |
32 | ### 订阅
33 |
34 | ***客户端***
35 | 成功建立和 WebSocket API 的连接之后,向 Server 发送如下格式的数据来订阅数据:
36 | ```js
37 | {
38 | "sub": "market.$symbol.kline.$period",
39 | "id": "id generate by client"
40 | }
41 | ```
42 |
43 | - sub 订阅
44 | - id 客户端自定义
45 |
46 | 参数名称 | 描述 | 取值
47 | ---|---|---
48 | symbol | 交易对 | ethbtc, ltcbtc, etcbtc, bchbtc......
49 | period | K线周期 | 1min, 5min, 15min, 30min, 60min, 1day, 1mon, 1week, 1year
50 |
51 | ***服务端***
52 | 返回订阅成功消息
53 | ```js
54 | {
55 | "id":"",
56 | "status":"ok",
57 | "subbed":"market.$symbol.markets",
58 | "ts":1535445731347
59 | }
60 | ```
61 |
62 | > 便于阅读,以下socket订阅api均先返回订阅成功信息后,再推送订阅数据。
63 |
64 | ### 取消订阅
65 |
66 | ***客户端***
67 | 取消当前订阅
68 | ```js
69 | {"unsub":"market.$symbol.markets"}
70 | ```
71 |
72 | ***服务端***
73 | 返回取消订阅成功消息
74 |
75 | ```js
76 | {
77 | "id":"",
78 | "status":"ok",
79 | "unsubbed":"market.usdt.markets",
80 | "ts":1535447792757
81 | }
82 | ```
83 | ## API
84 |
85 | ### 市场行情
86 |
87 | 订阅锚定货币的所有行情
88 |
89 | - $symbol 交易对。可选:usdt/btc/eth
90 |
91 | ```js
92 | {"sub":"market.$symbol.markets"}
93 | ```
94 |
95 | *订阅成功返回*
96 |
97 | ```js
98 | {
99 | "id":"",
100 | "status":"ok",
101 | "subbed":"market.$symbol.markets",
102 | "ts":1535445731347
103 | }
104 | ```
105 |
106 | *推送返回*
107 | - coins: 币种、最新价、涨幅
108 |
109 | ```js
110 | {
111 | "ch":"market.usdt.markets",
112 | "ts":1535445731347,
113 | "tick":{
114 | "coins":[
115 | ["ENB",1,1],
116 | ["ECHO",0,0]
117 | ]
118 | }
119 | }
120 | ```
121 |
122 | ### 交易对最新行情
123 |
124 | 提供交易对名称,订阅该最新交易数据
125 |
126 | - $symbol 交易对。如:ethusdt/btcusdt/etceth
127 |
128 | ```js
129 | {"sub":"market.$symbol.latest"}
130 | ```
131 |
132 | *返回*
133 |
134 | - 当前价、涨跌幅、最高价、最低价、24小时成交量
135 |
136 | ```js
137 | {
138 | "ch":"market.eth.latest",
139 | "ts":1535445731844,
140 | "tick":{
141 | "latest":[281.51,-1.67,292.08,269.48,98794]
142 | }
143 | }
144 | ```
145 |
146 | ### 盘口数据
147 |
148 | 订阅买卖上方挂盘数据
149 |
150 | - $symbol 交易对
151 |
152 | ```js
153 | {"sub":"market.$symbol.orders"}
154 | ```
155 |
156 | *返回*
157 | - sell: 卖盘 [价格、量、累计] *价格降序*
158 | - buy: 买盘 [价格、量、累计] *价格升序*
159 |
160 | ```js
161 | {
162 | "ch":"market.eth.orders",
163 | "ts":1535445731844,
164 | "tick":{
165 | "sell":[
166 | [281.96,0.5,5.5038],
167 | [282,0.5,5.5038],
168 | ...
169 | ],
170 | "buy":[
171 | [282.37,3.0309,7.8876],
172 | ...
173 | ]
174 | }
175 | }
176 | ```
177 |
178 | ### 成交明细
179 |
180 | 订阅实时成交
181 |
182 | ```js
183 | {"sub":"market.$symbol.deals"}
184 | ```
185 |
186 | *返回*
187 |
188 | [timestamp, 方向, 成交价, 数量]
189 |
190 | ```js
191 | {
192 | "ch":"market.ethusdt.deals",
193 | "ts":1535529998712,
194 | "tick":{
195 | "deals":[
196 | [1535529998712,0,100,200],
197 | ...
198 | ]
199 | }
200 | }
201 | ```
202 |
203 | ### 挂盘深度
204 |
205 | 订阅市场深度。为了让图表显示可读性强,**买卖挂盘价格边界(买盘最低价和卖盘最高价)必须保持对称,并且有挂盘量。**
206 |
207 | ```js
208 | {"sub":"market.$symbol.depth"}
209 | ```
210 |
211 | *返回*
212 |
213 | ```js
214 | {
215 | "ch":"market.ethusdt.depth",
216 | "ts":1535529998712,
217 | "tick":{
218 | bids: [
219 | [999, 20],
220 | ...
221 | ], // 买1价,买1量
222 | asks: [
223 | [0, 0],
224 | ...
225 | ], // 卖1价,卖1量
226 | }
227 | }
228 | ```
229 |
--------------------------------------------------------------------------------
/antd-theme/theme.less:
--------------------------------------------------------------------------------
1 | // 这个主题会批量替换./node_modules/antd/lib/style/themes/default.less中的属性
2 | @ant-prefix : ant;
3 |
4 | @primary-1: color(~`colorPalette('@{primary-color}', 10)`);
5 | @font-size-base: 12px;
6 | @text-color: #c7cce6;
7 | @heading-color: #c7cce6;
8 | @text-color-secondary: #4e5b85; // table 排序图标
9 | @background-color-base: transparent; // 排序选中的背景
10 | @table-header-bg: none;
11 | @table-padding-vertical: 3px;
12 | @table-padding-horizontal: 8px;
13 | @border-color-base: #4e5b85;
14 | @input-bg: #1e2235;
15 | @component-background: transparent; // no data - placeholder
16 | @border-color-split: #1f2943;
17 |
--------------------------------------------------------------------------------
/config/env.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const fs = require('fs');
4 | const path = require('path');
5 | const paths = require('./paths');
6 |
7 | // Make sure that including paths.js after env.js will read .env variables.
8 | delete require.cache[require.resolve('./paths')];
9 |
10 | const NODE_ENV = process.env.NODE_ENV;
11 | if (!NODE_ENV) {
12 | throw new Error(
13 | 'The NODE_ENV environment variable is required but was not specified.'
14 | );
15 | }
16 |
17 | // https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
18 | var dotenvFiles = [
19 | `${paths.dotenv}.${NODE_ENV}.local`,
20 | `${paths.dotenv}.${NODE_ENV}`,
21 | // Don't include `.env.local` for `test` environment
22 | // since normally you expect tests to produce the same
23 | // results for everyone
24 | NODE_ENV !== 'test' && `${paths.dotenv}.local`,
25 | paths.dotenv,
26 | ].filter(Boolean);
27 |
28 | // Load environment variables from .env* files. Suppress warnings using silent
29 | // if this file is missing. dotenv will never modify any environment variables
30 | // that have already been set. Variable expansion is supported in .env files.
31 | // https://github.com/motdotla/dotenv
32 | // https://github.com/motdotla/dotenv-expand
33 | dotenvFiles.forEach(dotenvFile => {
34 | if (fs.existsSync(dotenvFile)) {
35 | require('dotenv-expand')(
36 | require('dotenv').config({
37 | path: dotenvFile,
38 | })
39 | );
40 | }
41 | });
42 |
43 | // We support resolving modules according to `NODE_PATH`.
44 | // This lets you use absolute paths in imports inside large monorepos:
45 | // https://github.com/facebookincubator/create-react-app/issues/253.
46 | // It works similar to `NODE_PATH` in Node itself:
47 | // https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
48 | // Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.
49 | // Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims.
50 | // https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421
51 | // We also resolve them to make sure all tools using them work consistently.
52 | const appDirectory = fs.realpathSync(process.cwd());
53 | process.env.NODE_PATH = (process.env.NODE_PATH || '')
54 | .split(path.delimiter)
55 | .filter(folder => folder && !path.isAbsolute(folder))
56 | .map(folder => path.resolve(appDirectory, folder))
57 | .join(path.delimiter);
58 |
59 | // Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
60 | // injected into the application via DefinePlugin in Webpack configuration.
61 | const REACT_APP = /^REACT_APP_/i;
62 |
63 | function getClientEnvironment(publicUrl) {
64 | const raw = Object.keys(process.env)
65 | .filter(key => REACT_APP.test(key))
66 | .reduce(
67 | (env, key) => {
68 | env[key] = process.env[key];
69 | return env;
70 | },
71 | {
72 | // Useful for determining whether we’re running in production mode.
73 | // Most importantly, it switches React into the correct mode.
74 | NODE_ENV: process.env.NODE_ENV || 'development',
75 | // Useful for resolving the correct path to static assets in `public`.
76 | // For example, .
77 | // This should only be used as an escape hatch. Normally you would put
78 | // images into the `src` and `import` them in code to get their paths.
79 | PUBLIC_URL: publicUrl,
80 | }
81 | );
82 | // Stringify all values so we can feed into Webpack DefinePlugin
83 | const stringified = {
84 | 'process.env': Object.keys(raw).reduce((env, key) => {
85 | env[key] = JSON.stringify(raw[key]);
86 | return env;
87 | }, {}),
88 | };
89 |
90 | return { raw, stringified };
91 | }
92 |
93 | module.exports = getClientEnvironment;
94 |
--------------------------------------------------------------------------------
/config/jest/cssTransform.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // This is a custom Jest transformer turning style imports into empty objects.
4 | // http://facebook.github.io/jest/docs/en/webpack.html
5 |
6 | module.exports = {
7 | process() {
8 | return 'module.exports = {};';
9 | },
10 | getCacheKey() {
11 | // The output is always the same.
12 | return 'cssTransform';
13 | },
14 | };
15 |
--------------------------------------------------------------------------------
/config/jest/fileTransform.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const path = require('path');
4 |
5 | // This is a custom Jest transformer turning file imports into filenames.
6 | // http://facebook.github.io/jest/docs/en/webpack.html
7 |
8 | module.exports = {
9 | process(src, filename) {
10 | return `module.exports = ${JSON.stringify(path.basename(filename))};`;
11 | },
12 | };
13 |
--------------------------------------------------------------------------------
/config/paths.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const path = require('path');
4 | const fs = require('fs');
5 | const url = require('url');
6 |
7 | // Make sure any symlinks in the project folder are resolved:
8 | // https://github.com/facebookincubator/create-react-app/issues/637
9 | const appDirectory = fs.realpathSync(process.cwd());
10 | const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
11 |
12 | const envPublicUrl = process.env.PUBLIC_URL;
13 |
14 | function ensureSlash(path, needsSlash) {
15 | const hasSlash = path.endsWith('/');
16 | if (hasSlash && !needsSlash) {
17 | return path.substr(path, path.length - 1);
18 | } else if (!hasSlash && needsSlash) {
19 | return `${path}/`;
20 | } else {
21 | return path;
22 | }
23 | }
24 |
25 | const getPublicUrl = appPackageJson =>
26 | envPublicUrl || require(appPackageJson).homepage;
27 |
28 | // We use `PUBLIC_URL` environment variable or "homepage" field to infer
29 | // "public path" at which the app is served.
30 | // Webpack needs to know it to put the right
14 |
15 |
16 |
25 |