');
12 | $('.copy-clipboard').on('click', function() {
13 | copyToClipboard(this.parentNode.children[1]);
14 | });
15 | }
16 |
--------------------------------------------------------------------------------
/lib/nesting_unique_head.rb:
--------------------------------------------------------------------------------
1 | # Nested unique header generation
2 | require 'middleman-core/renderers/redcarpet'
3 |
4 | class NestingUniqueHeadCounter < Middleman::Renderers::MiddlemanRedcarpetHTML
5 | def initialize
6 | super
7 | @@headers_history = {} if !defined?(@@headers_history)
8 | end
9 |
10 | def header(text, header_level)
11 | friendly_text = text.gsub(/<[^>]*>/,"").parameterize
12 | @@headers_history[header_level] = text.parameterize
13 |
14 | if header_level > 1
15 | for i in (header_level - 1).downto(1)
16 | friendly_text.prepend("#{@@headers_history[i]}-") if @@headers_history.key?(i)
17 | end
18 | end
19 |
20 | return "#{text}"
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/source/index.html.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: مستندات API نوبیتکس
3 | lang: fa
4 | language_tabs:
5 | - shell
6 | - plaintext
7 | includes:
8 | - intro
9 | - market_data
10 | - user_data
11 | - market_trade
12 | - position
13 | - withdraw
14 | - websocket
15 | - address_book
16 | - security
17 | - referral
18 | - auth
19 | - portfolio
20 | - other
21 | - general_notes
22 | - faq
23 | - symbols
24 | toc_footers:
25 | - سابقه تغییرات API
26 | - شرایط استفاده از API
27 | - مخزن گیتهاب
28 | - کالکشن Postman
29 | - سایت نوبیتکس
30 | ---
31 |
--------------------------------------------------------------------------------
/source/javascripts/all_nosearch.js:
--------------------------------------------------------------------------------
1 | //= require ./lib/_energize
2 | //= require ./app/_copy
3 | //= require ./app/_toc
4 | //= require ./app/_lang
5 |
6 | function adjustLanguageSelectorWidth() {
7 | const elem = $('.dark-box > .lang-selector');
8 | elem.width(elem.parent().width());
9 | }
10 |
11 | $(function() {
12 | loadToc($('#toc'), '.toc-link', '.toc-list-h2', 10);
13 | setupLanguages($('body').data('languages'));
14 | $('.content').imagesLoaded( function() {
15 | window.recacheHeights();
16 | window.refreshToc();
17 | });
18 |
19 | $(window).resize(function() {
20 | adjustLanguageSelectorWidth();
21 | });
22 | adjustLanguageSelectorWidth();
23 | });
24 |
25 | window.onpopstate = function() {
26 | activateLanguage(getLanguageFromQueryString());
27 | };
28 |
--------------------------------------------------------------------------------
/lib/toc_data.rb:
--------------------------------------------------------------------------------
1 | require 'nokogiri'
2 |
3 | def toc_data(page_content)
4 | html_doc = Nokogiri::HTML::DocumentFragment.parse(page_content)
5 |
6 | # get a flat list of headers
7 | headers = []
8 | html_doc.css('h1, h2, h3').each do |header|
9 | headers.push({
10 | id: header.attribute('id').to_s,
11 | content: header.children,
12 | title: header.children.to_s.gsub(/<[^>]*>/, ''),
13 | level: header.name[1].to_i,
14 | children: []
15 | })
16 | end
17 |
18 | [3,2].each do |header_level|
19 | header_to_nest = nil
20 | headers = headers.reject do |header|
21 | if header[:level] == header_level
22 | header_to_nest[:children].push header if header_to_nest
23 | true
24 | else
25 | header_to_nest = header if header[:level] < header_level
26 | false
27 | end
28 | end
29 | end
30 | headers
31 | end
32 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Nobitex API Documentation
2 | [](https://apidocs.nobitex.ir)
3 | [](https://github.com/nobitex/docs-api/actions/workflows/deploy.yml)
4 |
5 | This repository contains documentation for connecting to the Nobitex cryptocurrency exchange market and using the
6 | official APIs. Feel free to create new issues for reporting documentation ambiguities and suggesting
7 | improvements to documentation or the underlying API.
8 |
9 | Built API documentation is available on [https://apidocs.nobitex.ir/](https://apidocs.nobitex.ir).
10 | The documentation is generated using [Slate](https://github.com/lord/slate).
11 | If you want to contribute to the documentation itself, see [Contributing](https://github.com/nobitex/docs-api/blob/master/CONTRIBUTING.md).
12 |
--------------------------------------------------------------------------------
/lib/unique_head.rb:
--------------------------------------------------------------------------------
1 | # Unique header generation
2 | require 'middleman-core/renderers/redcarpet'
3 | require 'digest'
4 | class UniqueHeadCounter < Middleman::Renderers::MiddlemanRedcarpetHTML
5 | def initialize
6 | super
7 | @head_count = {}
8 | end
9 | def header(text, header_level)
10 | friendly_text = text.gsub(/<[^>]*>/,"").parameterize
11 | if friendly_text.strip.length == 0
12 | # Looks like parameterize removed the whole thing! It removes many unicode
13 | # characters like Chinese and Russian. To get a unique URL, let's just
14 | # URI escape the whole header
15 | friendly_text = Digest::SHA1.hexdigest(text)[0,10]
16 | end
17 | @head_count[friendly_text] ||= 0
18 | @head_count[friendly_text] += 1
19 | if @head_count[friendly_text] > 1
20 | friendly_text += "-#{@head_count[friendly_text]}"
21 | end
22 | return "#{text}"
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/source/stylesheets/_icon-font.scss:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'slate';
3 | src:font-url('slate.eot?-syv14m');
4 | src:font-url('slate.eot?#iefix-syv14m') format('embedded-opentype'),
5 | font-url('slate.woff2?-syv14m') format('woff2'),
6 | font-url('slate.woff?-syv14m') format('woff'),
7 | font-url('slate.ttf?-syv14m') format('truetype'),
8 | font-url('slate.svg?-syv14m#slate') format('svg');
9 | font-weight: normal;
10 | font-style: normal;
11 | }
12 |
13 | %icon {
14 | font-family: 'slate';
15 | speak: none;
16 | font-style: normal;
17 | font-weight: normal;
18 | font-variant: normal;
19 | text-transform: none;
20 | line-height: 1;
21 | }
22 |
23 | %icon-exclamation-sign {
24 | @extend %icon;
25 | content: "\e600";
26 | }
27 | %icon-info-sign {
28 | @extend %icon;
29 | content: "\e602";
30 | }
31 | %icon-ok-sign {
32 | @extend %icon;
33 | content: "\e606";
34 | }
35 | %icon-search {
36 | @extend %icon;
37 | content: "\e607";
38 | }
39 |
--------------------------------------------------------------------------------
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | name: Deploy
2 |
3 | on:
4 | push:
5 | branches: [ 'master' ]
6 |
7 | jobs:
8 | deploy:
9 | runs-on: ubuntu-latest
10 | env:
11 | ruby-version: 3.3.8
12 |
13 | steps:
14 | - uses: actions/checkout@v4
15 | - name: Set up Ruby
16 | uses: ruby/setup-ruby@v1
17 | with:
18 | ruby-version: ${{ env.ruby-version }}
19 |
20 |
21 | - uses: actions/cache@v4
22 | with:
23 | path: vendor/bundle
24 | key: gems-${{ runner.os }}-${{ env.ruby-version }}-${{ hashFiles('**/Gemfile.lock') }}
25 | restore-keys: |
26 | gems-${{ runner.os }}-${{ env.ruby-version }}-
27 | gems-${{ runner.os }}-
28 |
29 | - run: bundle config set deployment 'true'
30 | - name: bundle install
31 | run: |
32 | bundle config path vendor/bundle
33 | bundle install --jobs 4 --retry 3
34 |
35 | - run: bundle exec middleman build
36 |
37 | - name: Deploy
38 | uses: peaceiris/actions-gh-pages@v3
39 | with:
40 | github_token: ${{ secrets.GITHUB_TOKEN }}
41 | publish_dir: ./build
42 | keep_files: true
43 |
--------------------------------------------------------------------------------
/source/deprecated/index.html.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: موارد قدیمی API
3 | lang: fa
4 | toc_footers:
5 | - مستندات API نوبیتکس
6 | - سابقه تغییرات API
7 | - شرایط استفاده از API
8 | - سایت نوبیتکس
9 | ---
10 |
11 | # موارد قدیمی API
12 | برخی از APIها به دلیل تغییرات ساختاری یا کارکردی، قدیمی و deprecated محسوب میشوند و نباید دیگر از آنها استفاده شود. این موارد صرفاً جهت ثبت در ادامه خواهند آمد، ولی ممکن است در حال حاضر یا هر یک از نسخههای آتی نوبیتکس این APIها غیرفعال شوند یا دیگر پاسخگو نباشند.
13 |
14 | ## کد دعوت پیشفرض
15 |
16 | ```shell
17 | curl 'https://apiv2.nobitex.ir/users/get-referral-code' \
18 | -H "Authorization: Token yourTOKENhereHEX0000000000"
19 | ```
20 |
21 | ```plaintext
22 | http POST https://apiv2.nobitex.ir/users/get-referral-code \
23 | ```
24 |
25 | > در صورت فراخوانی درست، پاسخ به این صورت خواهد بود:
26 |
27 | ```json
28 | {
29 | "status": "ok",
30 | "referredUsersCount": 0,
31 | "referralCode": "84440",
32 | "referralFeeTotalCount": 0,
33 | "referralFeeTotal": 0
34 | }
35 | ```
36 |
37 | برای دریافت کد دعوت پیشفرض از این نوع درخواست استفاده نمایید:
38 |
39 | - آدرس : `GET /users/get-referral-code`
40 |
--------------------------------------------------------------------------------
/source/includes/internal/_active_order_count.md:
--------------------------------------------------------------------------------
1 | # معامله در بازار
2 |
3 | ## تعداد سفارشهای باز کاربر
4 |
5 |
6 | ```shell
7 | curl 'https://apiv2.nobitex.ir/market/orders/open-count?tradeType=margin' \
8 | -H "Authorization: Token yourTOKENhereHEX0000000000"
9 | ```
10 |
11 | ```plaintext
12 | http GET https://apiv2.nobitex.ir/market/orders/open-count?tradeType=margin
13 | ```
14 |
15 | > در صورت فراخوانی درست، پاسخ به این صورت خواهد بود:
16 |
17 | ```json
18 | {
19 | "status": "ok",
20 | "count": 2
21 | }
22 | ```
23 |
24 | برای دریافت تعداد سفارشهای باز خود، از این درخواست استفاده نمایید.
25 |
26 | - **درخواست:** `GET /market/orders/open-count`
27 | - **محدودیت فراخوانی:** 15 درخواست در دقیقه
28 |
29 | ### پارامترهای ورودی
30 | | پارامتر | نوع | پیشفرض | توضیحات | نمونه |
31 | |-----------|--------|------------------|-------------------------------|--------------------|
32 | | tradeType | string | تمام انواع سفارش | نوع سفارش اسپات یا فروش تعهدی | `spot` یا `margin` |
33 |
34 | ### پارامترهای پاسخ
35 | | پارامتر | نوع | توضیحات | نمونه |
36 | |---------|---------|-------------------------|-------|
37 | | count | integer | تعداد سفارشات باز کاربر | 2 |
38 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yml:
--------------------------------------------------------------------------------
1 | name: درخواست فیچر
2 | description: امکانات مورد نیاز خود را به ما پیشنهاد دهید
3 | title: "[پیشنهاد]: "
4 | labels: ["enhancement"]
5 | body:
6 | - type: markdown
7 | attributes:
8 | value: |
9 | **توجه:** قبل از ثبت مورد جدید، [مستندات امکانات موجود](https://apidocs.nobitex.ir/) و [موردهای قدیمی فیچر](https://github.com/nobitex/docs-api/issues?q=is%3Aissue+label%3Aenhancement) را بخوانید. در صورت یافتن مورد مشابه همانجا مسئله خود را مطرح کنید
10 | - type: textarea
11 | id: requirement
12 | attributes:
13 | label: نیازمندی
14 | description: |
15 | چرا به این امکان نیازمند شدهاید؟ مشکلی که با آن روبرو شدهاید را دقیقا شرح دهید:
16 | validations:
17 | required: true
18 | - type: textarea
19 | id: solution
20 | attributes:
21 | label: راهحل
22 | description: |
23 | چه راهحلی برای رفع این نیاز میتوانیم به شما ارائه کنیم؟ پیشنهاد(های) خود را شفاف و دقیق شرح دهید:
24 | validations:
25 | required: true
26 | - type: textarea
27 | id: similar-features
28 | attributes:
29 | label: امکانات مشابه
30 | description: |
31 | سایر صرافیهای بزرگ چه امکانات مشابهی برای رفع این نیاز در نظر گرفتهاند؟ با ضمیمه کردن پیوند به مستندات آنها ما را در تحلیل سریعتر درخواستهای شما یاری کنید:
32 | - type: textarea
33 | id: additional-words
34 | attributes:
35 | label: توضیح تکمیلی
36 | description: |
37 | هر چیزی که از قلم مانده و به فهم بهتر ما کمک میکند در اینجا شرح دهید:
38 |
--------------------------------------------------------------------------------
/source/internal.html.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: مستندات API داخلی نوبیتکس
3 | lang: fa
4 | language_tabs:
5 | - shell
6 | - javascript
7 | - java
8 | - swift
9 | - plaintext
10 | includes:
11 | - internal/2fa
12 | - internal/notifications
13 | - internal/wallet_invoice
14 | - internal/price_alerts
15 | - internal/transactions
16 | - internal/gift
17 | - internal/ticketing
18 | - internal/batch_actions
19 | - internal/active_order_count
20 | - internal/cobank_withdraw
21 | toc_footers:
22 | - سایت نوبیتکس
23 | ---
24 |
25 | # مستندات API داخلی نوبیتکس
26 |
27 | > جهت استفاده از نمونه کدهای مستند ابتدا تنظیمات زیر را استفاده نمایید.
28 |
29 | ```shell
30 | sudo apt install curl
31 | ```
32 |
33 | ```javascript
34 | const axios = require("axios");
35 |
36 | const api = axios.create({baseURL: "https://apiv2.nobitex.ir"});
37 | ```
38 |
39 | ```java
40 | import com.google.gson.JsonObject;
41 | import retrofit2.Call;
42 | import retrofit2.http.GET;
43 | import retrofit2.http.POST;
44 | import retrofit2.http.Headers;
45 | import retrofit2.http.Query;
46 | import retrofit2.http.Field;
47 | import retrofit2.http.FormUrlEncoded;
48 | import retrofit2.converter.gson.GsonConverterFactory;
49 |
50 | Retrofit retrofit = new Retrofit.Builder()
51 | .baseUrl('https://apiv2.nobitex.ir')
52 | .addConverterFactory(GsonConverterFactory.create())
53 | .build();
54 | ```
55 |
56 | ```swift
57 | // Contact us
58 | ```
59 |
60 | مستندات این بخش، سایر APIهای نوبیتکس را که عموما با بازار نوبیتکس ارتباطی نداشته و بیشتر ناظر به نیازهای ارتباطی و عملکردی سایت و اپلیکیشن نوبیتکس میباشد، توضیح میدهد.
61 |
62 | توجه داشته باشید بعضی از APIها نیاز به احراز هویت و دریافت توکن دارد که میتوانید از [مستندات احراز هویت](/#intro-auth) نحوه عملکرد آن را مطالعه کنید.
63 |
--------------------------------------------------------------------------------
/Vagrantfile:
--------------------------------------------------------------------------------
1 | Vagrant.configure(2) do |config|
2 | config.vm.box = "ubuntu/bionic64"
3 | config.vm.network :forwarded_port, guest: 4567, host: 4567
4 | config.vm.provider "virtualbox" do |vb|
5 | vb.memory = "2048"
6 | end
7 |
8 | config.vm.provision "bootstrap",
9 | type: "shell",
10 | inline: <<-SHELL
11 | # add nodejs v12 repository
12 | curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
13 |
14 | sudo apt-get update
15 | sudo apt-get install -yq ruby ruby-dev
16 | sudo apt-get install -yq pkg-config build-essential nodejs git libxml2-dev libxslt-dev
17 | sudo apt-get autoremove -yq
18 | gem install --no-ri --no-rdoc bundler
19 | SHELL
20 |
21 | # add the local user git config to the vm
22 | config.vm.provision "file", source: "~/.gitconfig", destination: ".gitconfig"
23 |
24 | config.vm.provision "install",
25 | type: "shell",
26 | privileged: false,
27 | inline: <<-SHELL
28 | echo "=============================================="
29 | echo "Installing app dependencies"
30 | cd /vagrant
31 | sudo gem install bundler -v "$(grep -A 1 "BUNDLED WITH" Gemfile.lock | tail -n 1)"
32 | bundle config build.nokogiri --use-system-libraries
33 | bundle install
34 | SHELL
35 |
36 | config.vm.provision "run",
37 | type: "shell",
38 | privileged: false,
39 | run: "always",
40 | inline: <<-SHELL
41 | echo "=============================================="
42 | echo "Starting up middleman at http://localhost:4567"
43 | echo "If it does not come up, check the ~/middleman.log file for any error messages"
44 | cd /vagrant
45 | bundle exec middleman server --watcher-force-polling --watcher-latency=1 &> ~/middleman.log &
46 | SHELL
47 | end
48 |
--------------------------------------------------------------------------------
/source/includes/_faq.md:
--------------------------------------------------------------------------------
1 |
سوالات متداول
2 |
3 |
سوالی در مورد لاگین و دریافت توکن دارم
4 | در این زمینه ابتدا مطالعه توضیحات [احراز هویت و توکن](#intro-auth)، [راهنمای شروع به کار با API](#quickstart) و [روش پیشنهادی دریافت توکن](#auth-intro) پیشنهاد میشود. سپس میتوانید در بخش [سوالات متداول دریافت توکن](#login-faq) برخی سوالات متداول در این زمینه را مشاهده کنید.
5 |
6 |
7 | ## آیا نوبیتکس محیط آزمایشی (Test) دارد؟
8 | بله، شما میتوانید برای استفاده از کلیه امکانات بازار نوبیتکس و همچنین api ها از محیط آزمایشی نوبیتکس به آدرسهای ذیل استفاده نمائید:
9 |
10 | آدرس نوبیتکس آزمایشی : https://testnet.nobitex.ir
11 |
12 | آدرس api آزمایشی : https://testnetapiv2.nobitex.ir
13 |
14 |
15 | ## آیا برای استفاده از apiها محدودیتی وجود دارد؟
16 | بله، برای مثال شما حتماً باید از IPهای ایران درخواست خود را ارسال نمائید، و یا محدودیتهای مخصوص به هر api که در توضیحات هر کدام از endpointها آورده شده است.
17 |
18 |
19 | ## فرمت استفاده شده برای تاریخ چیست؟
20 | ساعت یونیکس Unix Time
21 | یکی از مقیاس اندازهگیری زمان آنی است. این عدد که تعداد ثانیهها از ساعت ۰۰:۰۰:۰۰ ساعت هماهنگ جهانی اول ژانویه ۱۹۷۰ است، شامل ثانیههای کبیسه نمیشود. برای زمانهای قبل از اول ژانویه از اعداد منفی استفاده میشود.
22 |
23 | به عنوان مثال [۰۱/۰۱/۱۹۷۰ ۰۰:۰۰:۰۰] برابر با صفر (۰) و [۰۱/۰۱/۱۹۷۰ ۰۰:۰۱:۰۰] برابر با شصت(۶۰) است.
24 |
25 | فرمول اصلی آن به این صورت میباشد:
26 |
27 | تعداد (روزهای گذشته از اول ژانویه ۱۹۷۰) × ۸۶۴۰۰(تعداد ثانیههای هر روز)
28 |
29 | به منظور مطالعه بیشتر به آدرس زیر مراجعه نمائید
30 | https://en.wikipedia.org/wiki/Unix_time
31 |
32 |
33 | ## آیا برای apiها کدهای نمونه تهیه شده است؟
34 | بله، collection کلیه api ها برای استفاده در برنامه postman تهیه و از اینجا میتوانید به آن دسترسی داشته باشید. در این collection شما میتوانید نمونه فراخوانی هر کدام از این apiها را به زبانهای مختلف برنامه نویسی نظیر پی اچ پی، پایتون، سی شارپ و … در این مجموعه مشاهده کرده و آن را در سیستم خود اجرا نمائید.
35 |
--------------------------------------------------------------------------------
/config.rb:
--------------------------------------------------------------------------------
1 | # Unique header generation
2 | require './lib/unique_head.rb'
3 |
4 | # Markdown
5 | set :markdown_engine, :redcarpet
6 | set :markdown,
7 | fenced_code_blocks: true,
8 | smartypants: true,
9 | disable_indented_code_blocks: true,
10 | prettify: true,
11 | strikethrough: true,
12 | tables: true,
13 | with_toc_data: true,
14 | no_intra_emphasis: true,
15 | renderer: UniqueHeadCounter
16 |
17 | # Assets
18 | set :css_dir, 'stylesheets'
19 | set :js_dir, 'javascripts'
20 | set :images_dir, 'images'
21 | set :fonts_dir, 'fonts'
22 |
23 | # Activate the syntax highlighter
24 | activate :syntax
25 | ready do
26 | require './lib/monokai_sublime_slate.rb'
27 | require './lib/multilang.rb'
28 | end
29 |
30 | activate :sprockets
31 |
32 | activate :autoprefixer do |config|
33 | config.browsers = ['last 2 version', 'Firefox ESR']
34 | config.cascade = false
35 | config.inline = true
36 | end
37 |
38 | # Github pages require relative links
39 | activate :relative_assets
40 | set :relative_links, true
41 |
42 | # Build Configuration
43 | configure :build do
44 | # We do want to hash woff and woff2 as there's a bug where woff2 will use
45 | # woff asset hash which breaks things. Trying to use a combination of ignore and
46 | # rewrite_ignore does not work as it conflicts weirdly with relative_assets. Disabling
47 | # the .woff2 extension only does not work as .woff will still activate it so have to
48 | # have both. See https://github.com/slatedocs/slate/issues/1171 for more details.
49 | activate :asset_hash, :exts => app.config[:asset_extensions] - %w[.woff .woff2]
50 | # If you're having trouble with Middleman hanging, commenting
51 | # out the following two lines has been known to help
52 | activate :minify_css
53 | activate :minify_javascript
54 | # activate :gzip
55 | end
56 |
57 | # Deploy Configuration
58 | # If you want Middleman to listen on a different port, you can set that below
59 | set :port, 4567
60 |
61 | helpers do
62 | require './lib/toc_data.rb'
63 | end
64 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/support_question.yml:
--------------------------------------------------------------------------------
1 | name: سوال پشتیبانی
2 | description: برای نحوه استفاده از ما کمک بخواهید
3 | title: "[پشتیبانی]: "
4 | labels: ["api-usage"]
5 | body:
6 | - type: markdown
7 | attributes:
8 | value: |
9 | **توجه:** قبل از ثبت مورد جدید [مستندات مربوطه](https://apidocs.nobitex.ir/) و [موردهای قدیمی پشتیبانی](https://github.com/nobitex/docs-api/issues?q=is%3Aissue+label%3Aapi-usage) را بخوانید. در صورت یافتن مورد مشابه همانجا مسئله خود را مطرح کنید
10 | - type: textarea
11 | id: goal
12 | attributes:
13 | label: هدف
14 | description: |
15 | به طور اجمالی شرح دهید میخواهید چه کاری از طریق نوبیتکس انجام دهید:
16 | placeholder: |
17 | مثلا: ثبت سفارش خرید دوج کوین به قیمت بازار
18 | validations:
19 | required: true
20 | - type: textarea
21 | id: environment
22 | attributes:
23 | label: محیط درخواست
24 | description: |
25 | ویژگیهای موثر در درخواست را طبق مستندات آن ارائه کنید:
26 | placeholder: |
27 | - ابزار درخواست (مرورگر/ابزار/برنامه/...)
28 | - زبان برنامه (cURL/Python/PHP/...)
29 | - محل درخواست (local/VPS/...)
30 | - درخواست IP (داخلی/خارجی)
31 | - ...
32 | value: |
33 | - ابزار درخواست (مرورگر/ابزار/برنامه/...)
34 | - زبان برنامه (cURL/Python/PHP/...)
35 | - محل درخواست (local/VPS/...)
36 | - درخواست IP (داخلی/خارجی)
37 | - ...
38 | - type: textarea
39 | id: request
40 | attributes:
41 | label: نحوه درخواست
42 | description: |
43 | کد مورد استفاده خود را ضمیمه کنید:
44 | این بخش از کد باید شامل اطلاعات زیر باشد: 1. آدرس 2. داده 3. هدر 4. محیط (آدرس پایه)
45 | دادههای حساس خود مانند توکن هویت یا شناسه سفارشات را با * مخدوش نمایید
46 | placeholder: |
47 | مثلا:
48 | ```python
49 | import requests
50 | url = 'https://apiv2.nobitex.ir/market/orders/add'
51 | headers = {'Authorization': 'Token abt*********************xz'}
52 | data = {'srcCurrency': 'doge', 'type': 'buy', 'execution': 'market', ...}
53 | response = requests.post(url, json=data, headers=headers)
54 | print(response.json())
55 | ```
56 | validations:
57 | required: true
58 | - type: textarea
59 | id: response
60 | attributes:
61 | label: پاسخ دریافتی
62 | description: |
63 | پیغام خطای نوبیتکس را در اینجا درج کنید:
64 | placeholder: |
65 | ```{"status": "failed", "code": "SampleCode",...}```
66 | validations:
67 | required: true
68 | - type: textarea
69 | id: additional-data
70 | attributes:
71 | label: اطلاعات تکمیلی
72 | description: |
73 | هر اطلاعات دیگری که برای کشف ریشه مشکل میتواند به ما کمک کند در اینجا ضمیمه کنید:
74 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.yml:
--------------------------------------------------------------------------------
1 | name: گزارش خطا
2 | description: برای کمک به بهبود ما، مشاهدات خود را گزارش کنید
3 | title: "[خطا]: "
4 | labels: ["bug"]
5 | body:
6 | - type: markdown
7 | attributes:
8 | value: |
9 | **توجه:** قبل از ثبت مورد جدید، [مستندات عملکرد فعلی](https://apidocs.nobitex.ir/) و [موردهای قدیمی خطا](https://github.com/nobitex/docs-api/issues?q=is%3Aissue+label%3Abug) را بخوانید. در صورت یافتن مورد مشابه همانجا مسئله خود را مطرح کنید
10 | - type: textarea
11 | id: description
12 | attributes:
13 | label: شرح خطا
14 | description: |
15 | خطای مشاهده شده را به طور اجمالی شرح دهید:
16 | - type: textarea
17 | id: request
18 | attributes:
19 | label: جزئیات درخواست
20 | placeholder: |
21 | 1. آدرس: `POST /sample/url`
22 | 2. داده:
23 | - key1: value1
24 | - key2: value2
25 | - ...
26 | 3. هدر:
27 | - Authorization: yes
28 | - ...
29 | 4. محیط:
30 | - تستنت
31 | - اصلی
32 | value: |
33 | 1. آدرس: `POST /sample/url`
34 | 2. داده:
35 | - key1: value1
36 | - key2: value2
37 | - ...
38 | 3. هدر:
39 | - Authorization: yes
40 | - ...
41 | 4. محیط:
42 | - تستنت
43 | - اصلی
44 | validations:
45 | required: true
46 | - type: textarea
47 | id: current-response
48 | attributes:
49 | label: پاسخ دریافتی
50 | description: |
51 | پاسخ کامل نوبیتکس را در اینجا درج کنید. دادههای حساس خود را در آن با * مخدوش نمایید:
52 | placeholder: |
53 | ```{"status": "ok", "result": {"id": 12***5,...}```
54 | validations:
55 | required: true
56 | - type: textarea
57 | id: expected-response
58 | attributes:
59 | label: پاسخ مورد انتظار
60 | description: |
61 | شرح دقیقی از رفتار مورد انتظار خود از نوبیتکس بدهید:
62 | validations:
63 | required: true
64 | - type: textarea
65 | id: reference
66 | attributes:
67 | label: پیوند مراجع
68 | description: |
69 | در صورتی که رفتار نوبیتکس با توصیفات مستندات مغایرت دارد، لینک یا تصویر بخش مد نظر خود را ضمیمه کنید/
70 | در صورتی که رفتار با منطق کاری صرافیها تفاوت دارد، لینک مقاله تایید کننده پاسخ مورد انتظار را ضمیمه کنید:
71 | placeholder: |
72 | - https://apidocs.nobitex.ir/#example-section
73 | - https://www.investopedia.com/...
74 | - ...
75 | - type: textarea
76 | id: additional-data
77 | attributes:
78 | label: اطلاعات تکمیلی
79 | description: |
80 | هر اطلاعات دیگری که برای کشف ریشه خطا میتواند به ما کمک کند:
81 | placeholder: |
82 | - محل استفاده (محلی/VPS/...)
83 | - محل IP (داخلی/خارجی)
84 | - ...
85 |
--------------------------------------------------------------------------------
/source/terms/index.html.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: قوانین و شرایط استفاده از API نوبیتکس
3 | lang: fa
4 | toc_footers:
5 | - مستندات API نوبیتکس
6 | - سابقه تغییرات API
7 | - سایت نوبیتکس
8 | ---
9 |
10 | # قوانین و شرایط استفاده از API نوبیتکس
11 |
12 | ## ملاحظات استفاده عمومی
13 |
14 | * تنها بخشی از API نوبیتکس که در مستندات ذکر شده باشند، API عمومی و قابل استفاده نوبیتکس به شمار میآیند. اگر endpoint یا فیلدی در مستندات ذکر نشده باشد، ممکن است بدون اطلاع قبلی دچار تغییر شود.
15 | * ممکن است در طول زمان تغییراتی در API عمومی نوبیتکس رخ دهد. این تغییرات در صفحه
16 | «[سابقه تغییرات API نوبیتکس](/changelog/)»
17 | اطلاعرسانی خواهند شد. لازم است استفاده کنندگان به صورت منظم و هفتگی این صفحه را رصد نمایند و تغییرات لازم را در برنامههای خود اعمال نمایند.
18 | * نوبیتکس تضمین سطح سرویس SLA برای API خود به عموم مشتریان ارائه نمیدهد و استفاده کنندگان از API باید تمهیدات لازم در خصوص تشخیص و واکنش به اختلالات احتمالی در سرویس را انجام دهند. نوبیتکس در قبال هیچ گونه شرایط یا تغییراتی در API که احتمالاً باعث ایجاد مشکل در کد نوشته شده توسط کاربران شود، نخواهد داشت.
19 | * در صورت دریافت پاسخ مبنی بر استفاده نادرست از API، مانند خطای 429 یا سایر خطاهای ناشی از نرخ بالای درخواستها یا ورودی نامعتبر، استفاده کننده ملزم است که واکنش مناسب را نسبت به خطا نشان داده و از تکرار اشتباه با بسامد بالا خودداری نماید. در صورت تشخیص استفاده نادرست و عدم واکنش مناسب به پیامهای خطای دریافتی، ممکن است IP درخواست دهنده به صورت موقت یا دائمی در سرویس نوبیتکس مسدود شود.
20 | * استفاده آگاهانه از API نوبیتکس جهت نفوذ یا حملات DDoS یا سایر اعمال مخرب خلاف شرایط استفاده نوبیتکس است و در صورت مشاهده حسابهای کاربری دخیل در آن مسدود خواهند شد.
21 |
22 |
23 | ## ملاحظات برنامهنویسی
24 |
25 | * خروجی API نوبیتکس معمولاً در قالب JSON ارائه میشود. لازم به دقت است که ممکن است علاوه بر فیلدهایی که در مستندات برای خروجی ذکر شدهاند، فیلدهای دیگری نیز در خروجی پاسخ وجود داشته باشند. پیشنهاد میشود که برنامه خود را به صورتی توسعه دهید که در صورت وجود فیلدهای دیگری علاوه بر فیلدهای مورد انتظار، دچار خطا نشود.
26 |
27 |
28 | ## ملاحظات مرتبط با سرویس کلادفلر
29 |
30 | * نوبیتکس از سرویس کلادفلر به عنوان CDN و واسط API استفاده مینماید. در صورتی که به هر دلیل کلادفلر ترافیک ارسالی شما را مشکوک یا مخرب تشخیص دهد ممکن است برخی یا تمام درخواستهای شما را رد کند. مدیریت این شرایط به دلیل اهمیت سرویس کلادفلر جهت جلوگیری از حملات DDoS ضروری و خارج از کنترل نوبیتکس است و استفاده کنندگان از API ملزم هستند نکات عمومی Fair Use را لحاظ نمایند.
31 | * امکان استفاده از API نوبیتکس هم از آیپی داخل و هم از آیپی خارج از کشور ممکن است و محدودیتی بابت استفاده از آیپی ایرانی روی درخواستها اعمال نمیشود.
32 | * اتصال تمامی کاربران عادی سایت و اپ و API نوبیتکس به واسطه سرویس کلادفلر با سرورهای نوبیتکس که در داخل ایران مستقر هستند، برقرار میشود و امکان ارائه کانال مستقیمتر ارتباطی وجود ندارد. کاربران میتوانند در صورت نیاز به کاهش تاخیر ارتباطی، نسبت به حداقلسازی تاخیر ارتباطی خود تا سرورهای لبه کلادفلر اقدام نمایند.
33 |
--------------------------------------------------------------------------------
/source/fonts/slate.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
15 |
--------------------------------------------------------------------------------
/source/javascripts/app/_search.js:
--------------------------------------------------------------------------------
1 | //= require ../lib/_lunr
2 | //= require ../lib/_jquery
3 | //= require ../lib/_jquery.highlight
4 | ;(function () {
5 | 'use strict';
6 |
7 | var content, searchResults;
8 | var highlightOpts = { element: 'span', className: 'search-highlight' };
9 | var searchDelay = 0;
10 | var timeoutHandle = 0;
11 | var index;
12 |
13 | function populate() {
14 | index = lunr(function(){
15 |
16 | this.ref('id');
17 | this.field('title', { boost: 10 });
18 | this.field('body');
19 | this.pipeline.add(lunr.trimmer, lunr.stopWordFilter);
20 | var lunrConfig = this;
21 |
22 | $('h1, h2').each(function() {
23 | var title = $(this);
24 | var body = title.nextUntil('h1, h2');
25 | lunrConfig.add({
26 | id: title.prop('id'),
27 | title: title.text(),
28 | body: body.text()
29 | });
30 | });
31 |
32 | });
33 | determineSearchDelay();
34 | }
35 |
36 | $(populate);
37 | $(bind);
38 |
39 | function determineSearchDelay() {
40 | if (index.tokenSet.toArray().length>5000) {
41 | searchDelay = 300;
42 | }
43 | }
44 |
45 | function bind() {
46 | content = $('.content');
47 | searchResults = $('.search-results');
48 |
49 | $('#input-search').on('keyup',function(e) {
50 | var wait = function() {
51 | return function(executingFunction, waitTime){
52 | clearTimeout(timeoutHandle);
53 | timeoutHandle = setTimeout(executingFunction, waitTime);
54 | };
55 | }();
56 | wait(function(){
57 | search(e);
58 | }, searchDelay);
59 | });
60 | }
61 |
62 | function search(event) {
63 |
64 | var searchInput = $('#input-search')[0];
65 |
66 | unhighlight();
67 | searchResults.addClass('visible');
68 |
69 | // ESC clears the field
70 | if (event.keyCode === 27) searchInput.value = '';
71 |
72 | if (searchInput.value) {
73 | var results = index.search(searchInput.value).filter(function(r) {
74 | return r.score > 0.0001;
75 | });
76 |
77 | if (results.length) {
78 | searchResults.empty();
79 | $.each(results, function (index, result) {
80 | var elem = document.getElementById(result.ref);
81 | searchResults.append("
111 | <% if current_page.data.toc_footers %>
112 |
113 | <% current_page.data.toc_footers.each do |footer| %>
114 |
<%= footer %>
115 | <% end %>
116 |
117 | <% end %>
118 |
119 |
120 |
121 |
122 | <%= page_content %>
123 |
124 |
125 | <% if language_tabs.any? %>
126 |
127 | <% language_tabs.each do |lang| %>
128 | <% if lang.is_a? Hash %>
129 | <%= lang.values.first %>
130 | <% else %>
131 | <%= lang %>
132 | <% end %>
133 | <% end %>
134 |
135 | <% end %>
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/source/includes/_security.md:
--------------------------------------------------------------------------------
1 | # امنیت
2 |
3 | ## سابقه ورود
4 |
5 | ```shell
6 | curl 'https://apiv2.nobitex.ir/users/login-attempts' \
7 | -H "Authorization: Token yourTOKENhereHEX0000000000"
8 | ```
9 |
10 | ```plaintext
11 | http POST https://apiv2.nobitex.ir/users/login-attempts \
12 | ```
13 |
14 | > در صورت فراخوانی درست، پاسخ به این صورت خواهد بود:
15 |
16 | ```json
17 | {
18 | "status": "ok",
19 | "attempts": [
20 | {
21 | "ip": "46.209.130.106",
22 | "username": "name@example.com",
23 | "status": "Successful",
24 | "createdAt": "2018-11-28T14:16:08.264308+00:00"
25 | },
26 | ...
27 | ]
28 | }
29 | ```
30 |
31 | برای دریافت سابقه ورود از این نوع درخواست استفاده نمایید:
32 |
33 | - **درخواست:** `GET /users/login-attempts`
34 |
35 |
36 | ## فعالسازی لغو اضطراری
37 |
38 | ```shell
39 | curl 'https://apiv2.nobitex.ir/security/emergency-cancel/activate' \
40 | -X GET \
41 | -H "Authorization: Token yourTOKENhereHEX0000000000"
42 | ```
43 |
44 | ```plaintext
45 | http GET https://apiv2.nobitex.ir/security/emergency-cancel/activate \
46 | Authorization: Token yourTOKENhereHEX0000000000
47 | ```
48 |
49 | > در صورت فراخوانی درست، پاسخ به این صورت خواهد بود:
50 |
51 | ```json
52 | {
53 | "status": "ok",
54 | "cancelCode": {
55 | "code": "seJlef35L3"
56 | }
57 | }
58 | ```
59 |
60 |
61 | جهت فعالسازی امکان لغو اضطراریِ درخواست های برداشت از این درخواست استفاده نمائید.
62 | پس از فعالسازی این امکان، پیامک و ایمیل ارسالی پس از ثبت درخواست برداشت،
63 | حاوی لینکی خواهد بود که شما میتوانید با استفاده از آن در صورتی که درخواست برداشت توسط شما ثبت نشده است، در کمترین زمان ممکن و بدون نیاز به لاگین، درخواست های برداشت خود را لغو نمایید.
64 |
65 | - **درخواست:** `GET /security/emergency-cancel/activate`
66 |
67 |
68 | ### نکات و ملاحظات
69 | توجه داشته باشید: در صورتی که درخواست برداشت شما توسط این امکان لغو گردد، امکان ثبت درخواست برداشت تا ۷۲ ساعت برای شما غیرفعال خواهد شد.
70 |
71 |
72 |
73 | ## آنتی فیشینگ
74 |
75 | جهت امنیت حساب کاربری و همچنین اعتماد بیشتر کاربران به ایمیل هایی که از سمت توبیتکس ارسال میشود نیاز هست که کاربر بتواند کد یونیک برای حساب کاربری خود انتخاب کند که تمامی ایمیل هایی که از سمت نوبیتکس به صورت اتوماتیک ارسال میشود حاوی این کد باشد.
76 | .این کد به کاربر این اطمینان را میدهد که این ایمیل قطعا از نوبیتکس ارسال شده است.
77 |
78 |
79 | ### ایجاد کد آنتی فیشینگ
80 |
81 | >نمونه درخواست:
82 |
83 | ```shell
84 | curl --location --request POST 'https://apiv2.nobitex.ir/security/anti-phishing' \
85 | --header 'Authorization: Token yourTOKENhereHEX0000000000' \
86 | --form 'code="sample_anti_phishing"' \
87 | --form 'otpCode="123456"'
88 | ```
89 |
90 |
91 | > در صورت فراخوانی درست، پاسخ به این صورت خواهد بود:
92 |
93 | ```json
94 | {
95 | "status": "ok"
96 | }
97 | ```
98 |
99 | > برای دریافت رمزیکبارمصرف otpCode باید از API زیر با پارامترهای مشخص شده استفاده نمایید:
100 |
101 | ```shell
102 | curl -X POST 'https://apiv2.nobitex.ir/v2/otp/request' \
103 | -H 'Authorization: Token yourTOKENhereHEX0000000000' \
104 | --data '{"type": "email", "usage": "anti_phishing_code"}'
105 | ```
106 |
107 | > **حالت های خطا**
108 |
109 | > در صورتی که پارامتر کدیکبارمصرف یا آنتی فیشینگ را ارسال نکرده باشید با این خطا روبرو خواهید شد.
110 |
111 | ```json
112 | {
113 | "status": "failed",
114 | "code": "ParseError",
115 | "message": "Missing string value"
116 | }
117 | ```
118 |
119 |
120 | > در صورتی که کدیکبار مصرف ارسال شده، نامعتبر باشد با این خطا روبرو خواهید بود.
121 |
122 | ```json
123 | {
124 | "status": "failed",
125 | "code": "InvalidOTPCode",
126 | "message": "Please use otp/request endpoint"
127 | }
128 | ```
129 |
130 | > در صورتی که طول عبارت ارسالی نامناسب باشد با این خطا مواجه خواهید شد
131 |
132 | ```json
133 | {
134 | "status": "failed",
135 | "code": "InvalidCodeLength",
136 | "message": "Code length must be between 4 and 15 characters"
137 | }
138 | ```
139 |
140 |
141 | * **درخواست:** `POST /security/anti-phishing`
142 | * **محدودیت فراخوانی:** ۱۰ درخواست در هر دقیقه
143 |
144 |
145 | * پارامترهای ورودی
146 |
147 | پارامتر | نوع | پیشفرض | توضیحات | نمونه
148 | ------- |--------|---------|----------------------------------------------| ---------
149 | code | string | الزامی | کد آنتی فیشینگ تعیین شده توسط کاربر | sample_anti_phishing
150 | otpCode | number | الزامی | کد یکبار مصرف ارسال شده به شماره همراه کاربر | 12345
151 |
152 |
153 |
154 |
155 | ### دریافت کد آنتی فیشینگ
156 |
157 | * **درخواست:** `GET /security/anti-phishing`
158 | * **محدودیت فراخوانی:** ۱۰ درخواست در هر دقیقه
159 |
160 |
161 | >نمونه درخواست:
162 |
163 | ```shell
164 | curl --location --request GET 'https://apiv2.nobitex.ir/security/anti-phishing' \
165 | --header 'Authorization: Token yourTOKENhereHEX0000000000'
166 | ```
167 |
168 |
169 | > در صورت فراخوانی درست، پاسخ به این صورت خواهد بود:
170 |
171 | ```json
172 | {
173 | "status": "ok",
174 | "antiPhishingCode": "s*********g"
175 | }
176 | ```
177 |
178 | > در صورتی که آنتیفیشینگ کد برای کاربر فعال نشده باشد با این پاسخ مواجه خواهید شد
179 |
180 | ```json
181 | {
182 | "status": "failed",
183 | "code": "NotFound",
184 | "message": "AntiPhishingCode is not declared for this user"
185 | }
186 | ```
187 |
--------------------------------------------------------------------------------
/font-selection.json:
--------------------------------------------------------------------------------
1 | {
2 | "IcoMoonType": "selection",
3 | "icons": [
4 | {
5 | "icon": {
6 | "paths": [
7 | "M438.857 73.143q119.429 0 220.286 58.857t159.714 159.714 58.857 220.286-58.857 220.286-159.714 159.714-220.286 58.857-220.286-58.857-159.714-159.714-58.857-220.286 58.857-220.286 159.714-159.714 220.286-58.857zM512 785.714v-108.571q0-8-5.143-13.429t-12.571-5.429h-109.714q-7.429 0-13.143 5.714t-5.714 13.143v108.571q0 7.429 5.714 13.143t13.143 5.714h109.714q7.429 0 12.571-5.429t5.143-13.429zM510.857 589.143l10.286-354.857q0-6.857-5.714-10.286-5.714-4.571-13.714-4.571h-125.714q-8 0-13.714 4.571-5.714 3.429-5.714 10.286l9.714 354.857q0 5.714 5.714 10t13.714 4.286h105.714q8 0 13.429-4.286t6-10z"
8 | ],
9 | "attrs": [],
10 | "isMulticolor": false,
11 | "tags": [
12 | "exclamation-circle"
13 | ],
14 | "defaultCode": 61546,
15 | "grid": 14
16 | },
17 | "attrs": [],
18 | "properties": {
19 | "id": 100,
20 | "order": 4,
21 | "prevSize": 28,
22 | "code": 58880,
23 | "name": "exclamation-sign",
24 | "ligatures": ""
25 | },
26 | "setIdx": 0,
27 | "iconIdx": 0
28 | },
29 | {
30 | "icon": {
31 | "paths": [
32 | "M585.143 786.286v-91.429q0-8-5.143-13.143t-13.143-5.143h-54.857v-292.571q0-8-5.143-13.143t-13.143-5.143h-182.857q-8 0-13.143 5.143t-5.143 13.143v91.429q0 8 5.143 13.143t13.143 5.143h54.857v182.857h-54.857q-8 0-13.143 5.143t-5.143 13.143v91.429q0 8 5.143 13.143t13.143 5.143h256q8 0 13.143-5.143t5.143-13.143zM512 274.286v-91.429q0-8-5.143-13.143t-13.143-5.143h-109.714q-8 0-13.143 5.143t-5.143 13.143v91.429q0 8 5.143 13.143t13.143 5.143h109.714q8 0 13.143-5.143t5.143-13.143zM877.714 512q0 119.429-58.857 220.286t-159.714 159.714-220.286 58.857-220.286-58.857-159.714-159.714-58.857-220.286 58.857-220.286 159.714-159.714 220.286-58.857 220.286 58.857 159.714 159.714 58.857 220.286z"
33 | ],
34 | "attrs": [],
35 | "isMulticolor": false,
36 | "tags": [
37 | "info-circle"
38 | ],
39 | "defaultCode": 61530,
40 | "grid": 14
41 | },
42 | "attrs": [],
43 | "properties": {
44 | "id": 85,
45 | "order": 3,
46 | "name": "info-sign",
47 | "prevSize": 28,
48 | "code": 58882
49 | },
50 | "setIdx": 0,
51 | "iconIdx": 2
52 | },
53 | {
54 | "icon": {
55 | "paths": [
56 | "M733.714 419.429q0-16-10.286-26.286l-52-51.429q-10.857-10.857-25.714-10.857t-25.714 10.857l-233.143 232.571-129.143-129.143q-10.857-10.857-25.714-10.857t-25.714 10.857l-52 51.429q-10.286 10.286-10.286 26.286 0 15.429 10.286 25.714l206.857 206.857q10.857 10.857 25.714 10.857 15.429 0 26.286-10.857l310.286-310.286q10.286-10.286 10.286-25.714zM877.714 512q0 119.429-58.857 220.286t-159.714 159.714-220.286 58.857-220.286-58.857-159.714-159.714-58.857-220.286 58.857-220.286 159.714-159.714 220.286-58.857 220.286 58.857 159.714 159.714 58.857 220.286z"
57 | ],
58 | "attrs": [],
59 | "isMulticolor": false,
60 | "tags": [
61 | "check-circle"
62 | ],
63 | "defaultCode": 61528,
64 | "grid": 14
65 | },
66 | "attrs": [],
67 | "properties": {
68 | "id": 83,
69 | "order": 9,
70 | "prevSize": 28,
71 | "code": 58886,
72 | "name": "ok-sign"
73 | },
74 | "setIdx": 0,
75 | "iconIdx": 6
76 | },
77 | {
78 | "icon": {
79 | "paths": [
80 | "M658.286 475.429q0-105.714-75.143-180.857t-180.857-75.143-180.857 75.143-75.143 180.857 75.143 180.857 180.857 75.143 180.857-75.143 75.143-180.857zM950.857 950.857q0 29.714-21.714 51.429t-51.429 21.714q-30.857 0-51.429-21.714l-196-195.429q-102.286 70.857-228 70.857-81.714 0-156.286-31.714t-128.571-85.714-85.714-128.571-31.714-156.286 31.714-156.286 85.714-128.571 128.571-85.714 156.286-31.714 156.286 31.714 128.571 85.714 85.714 128.571 31.714 156.286q0 125.714-70.857 228l196 196q21.143 21.143 21.143 51.429z"
81 | ],
82 | "width": 951,
83 | "attrs": [],
84 | "isMulticolor": false,
85 | "tags": [
86 | "search"
87 | ],
88 | "defaultCode": 61442,
89 | "grid": 14
90 | },
91 | "attrs": [],
92 | "properties": {
93 | "id": 2,
94 | "order": 1,
95 | "prevSize": 28,
96 | "code": 58887,
97 | "name": "icon-search"
98 | },
99 | "setIdx": 0,
100 | "iconIdx": 7
101 | }
102 | ],
103 | "height": 1024,
104 | "metadata": {
105 | "name": "slate",
106 | "license": "SIL OFL 1.1"
107 | },
108 | "preferences": {
109 | "showGlyphs": true,
110 | "showQuickUse": true,
111 | "showQuickUse2": true,
112 | "showSVGs": true,
113 | "fontPref": {
114 | "prefix": "icon-",
115 | "metadata": {
116 | "fontFamily": "slate",
117 | "majorVersion": 1,
118 | "minorVersion": 0,
119 | "description": "Based on FontAwesome",
120 | "license": "SIL OFL 1.1"
121 | },
122 | "metrics": {
123 | "emSize": 1024,
124 | "baseline": 6.25,
125 | "whitespace": 50
126 | },
127 | "resetPoint": 58880,
128 | "showSelector": false,
129 | "selector": "class",
130 | "classSelector": ".icon",
131 | "showMetrics": false,
132 | "showMetadata": true,
133 | "showVersion": true,
134 | "ie7": false
135 | },
136 | "imagePref": {
137 | "prefix": "icon-",
138 | "png": true,
139 | "useClassSelector": true,
140 | "color": 4473924,
141 | "bgColor": 16777215
142 | },
143 | "historySize": 100,
144 | "showCodes": true,
145 | "gridSize": 16,
146 | "showLiga": false
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/source/javascripts/lib/_imagesloaded.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * imagesLoaded PACKAGED v4.1.4
3 | * JavaScript is all like "You images are done yet or what?"
4 | * MIT License
5 | */
6 |
7 | !function(e,t){"function"==typeof define&&define.amd?define("ev-emitter/ev-emitter",t):"object"==typeof module&&module.exports?module.exports=t():e.EvEmitter=t()}("undefined"!=typeof window?window:this,function(){function e(){}var t=e.prototype;return t.on=function(e,t){if(e&&t){var i=this._events=this._events||{},n=i[e]=i[e]||[];return n.indexOf(t)==-1&&n.push(t),this}},t.once=function(e,t){if(e&&t){this.on(e,t);var i=this._onceEvents=this._onceEvents||{},n=i[e]=i[e]||{};return n[t]=!0,this}},t.off=function(e,t){var i=this._events&&this._events[e];if(i&&i.length){var n=i.indexOf(t);return n!=-1&&i.splice(n,1),this}},t.emitEvent=function(e,t){var i=this._events&&this._events[e];if(i&&i.length){i=i.slice(0),t=t||[];for(var n=this._onceEvents&&this._onceEvents[e],o=0;o= 1) {
101 | var language = parseURL(location.search).language;
102 | if (language) {
103 | return language;
104 | } else if (jQuery.inArray(location.search.substr(1), languages) != -1) {
105 | return location.search.substr(1);
106 | }
107 | }
108 |
109 | return false;
110 | }
111 |
112 | // returns a new query string with the new language in it
113 | function generateNewQueryString(language) {
114 | var url = parseURL(location.search);
115 | if (url.language) {
116 | url.language = language;
117 | return stringifyURL(url);
118 | }
119 | return language;
120 | }
121 |
122 | // if a button is clicked, add the state to the history
123 | function pushURL(language) {
124 | if (!history) { return; }
125 | var hash = window.location.hash;
126 | if (hash) {
127 | hash = hash.replace(/^#+/, '');
128 | }
129 | history.pushState({}, '', '?' + generateNewQueryString(language) + '#' + hash);
130 |
131 | // save language as next default
132 | if (localStorage) {
133 | localStorage.setItem("language", language);
134 | }
135 | }
136 |
137 | function setupLanguages(l) {
138 | var defaultLanguage = null;
139 | if (localStorage) {
140 | defaultLanguage = localStorage.getItem("language");
141 | }
142 |
143 | languages = l;
144 |
145 | var presetLanguage = getLanguageFromQueryString();
146 | if (presetLanguage) {
147 | // the language is in the URL, so use that language!
148 | activateLanguage(presetLanguage);
149 |
150 | if (localStorage) {
151 | localStorage.setItem("language", presetLanguage);
152 | }
153 | } else if ((defaultLanguage !== null) && (jQuery.inArray(defaultLanguage, languages) != -1)) {
154 | // the language was the last selected one saved in localstorage, so use that language!
155 | activateLanguage(defaultLanguage);
156 | } else {
157 | // no language selected, so use the default
158 | activateLanguage(languages[0]);
159 | }
160 | }
161 |
162 | // if we click on a language tab, activate that language
163 | $(function() {
164 | $(".lang-selector a").on("click", function() {
165 | var language = $(this).data("language-name");
166 | pushURL(language);
167 | activateLanguage(language);
168 | return false;
169 | });
170 | });
171 | })();
172 |
--------------------------------------------------------------------------------
/source/includes/_referral.md:
--------------------------------------------------------------------------------
1 | # طرح معرفی دوستان
2 |
3 | نوبیتکس طرحی به نام معرفی دوستان در نظر گرفته است که از طریق آن هم به گسترش نوبیتکس کمک میکنید و هم از مزایای آن بهرهمند میشوید. براساس این طرح شما میتوانید دوستان خود را با لینک اختصاصی خود به نوبیتکس دعوت کنید و درصدی از کارمزد معاملات آنها را به عنوان پاداش دریافت نمایید. برای اطلاعات بیشتر به [صفحه قوانین طرح معرفی دوستان](https://nobitex.ir/policies/referral/) مراجعه کنید.
4 |
5 | معرفی دوستان با استفاده از ایجاد «کد دعوت» انجام میشود. هر کاربر نوبیتکس میتواند برای خود یک یا چند کد دعوت بسازد. کدهای دعوت معمولاً شامل شش رقم هستند ولی میتوانند طول متفاوتی داشته باشند یا حتی رشتههای دلخواه باشند. در زمان ساخت هر کد دعوت میتوان سهم کاربر معرف و کاربر دعوت شده از کارمزد اهدایی را مشخص نمود.
6 |
7 | با استفاده از «فهرست کدهای دعوت» میتوانید فهرستی از کدهای دعوت فعلی خود را دریافت نمایید. به همراه این فهرست، میزان سود شما و برخی دیگر از آمار مربوط به کاربران ثبتنامی با آن کد دعوت ارسال میشود. اگر هنوز کد دعوتی ندارید، برای شروع استفاده از طرح معرفی دوستان میتوانید با استفاده از «ایجاد کد دعوت»، یک کد دعوت بسازید.
8 |
9 |
13 |
14 |
15 | ## فهرست کدهای دعوت
16 |
17 | ```shell
18 | curl -X GET 'https://apiv2.nobitex.ir/users/referral/links-list' \
19 | --header 'Authorization: Token yourTOKENhereHEX0000000000'
20 | ```
21 |
22 | ```plaintext
23 | http --follow --timeout 3600 GET https://apiv2.nobitex.ir/users/referral/links-list \
24 | Authorization:'Token yourTOKENhereHEX0000000000'
25 | ```
26 |
27 | * **درخواست:** `POST /users/referral/links-list`
28 | * **محدودیت فراخوانی:** ۵۰ درخواست در هر ۱۰ دقیقه
29 |
30 | ### پارامترهای پاسخ
31 | پارامتر | نوع | توضیحات | نمونه
32 | ---- | ---- | ---- | ----
33 | links | list of ReferralLink | فهرست کدهای دعوت این کاربر | `[{...ReferralLink...}, ...]`
34 |
35 | ### شی ReferralLink
36 | فیلد | نوع | توضیحات | نمونه
37 | ---- | ---- | ---- | ----
38 | id | int | شناسه یکتای لینک | `1001`
39 | referralCode | string | کد دعوت | `40404`
40 | createdAt | datetime | تاریخ ایجاد کد | `2020-07-15T11:32:38.326809+00:00`
41 | userShare | int | سهم کاربر معرف از کارمزد معاملات کاربر دعوت شده | `20`
42 | friendShare | int | سهم کاربر دعوت شده از کارمزد معاملات خود | `10`
43 | description | string | توضیحات اختیاری کاربر برای این کد | `Shared on Instagram page X`
44 | statsRegisters | int | آمار: کاربران ثبتنام کرده با این کد | `20`
45 | statsTrades | int | آمار: مجموع تعداد معاملات کاربران ثبتنام کرده با این کد | `240`
46 | statsProfit | monetary: IRR | آمار: مجموع ریالی درآمد کاربر از این کد دعوت | `3200000`
47 |
48 |
49 | ## ایجاد کد دعوت
50 |
51 | ```shell
52 | curl -X GET 'https://apiv2.nobitex.ir/users/get-referral-code' \
53 | --header 'Authorization: Token yourTOKENhereHEX0000000000'
54 | ```
55 |
56 | ```plaintext
57 | http --follow --timeout 3600 GET https://apiv2.nobitex.ir/users/get-referral-code \
58 | Authorization:'Token yourTOKENhereHEX0000000000'
59 | ```
60 | برای ایجاد یک کد دعوت جدید برای کاربر، از «ایجاد کد دعوت» استفاده نمایید.
61 |
62 | * **درخواست:** `POST /users/referral/links-add`
63 | * **محدودیت فراخوانی:** ۵ درخواست در هر دقیقه
64 |
65 | ### پارامترهای ورودی
66 | پارامتر | نوع | پیشفرض | توضیحات | نمونه
67 | ------- | ---- | --------- | --------- | -----
68 | friendShare | int | `0` | سهم کارمزد اهدایی به دوست دعوت شده با این کد | `10`
69 |
70 | ### حالتهای خطا
71 | کد خطا | توضیحات
72 | ---- | ----
73 | InvalidGivebackShare | سهم کارمزد دوست قابل قبول نیست. پارامتر friendShare را بررسی کنید.
74 | TooManyReferralLinks | سهمیه ۳۰ تایی کدهای دعوت قابل ساخت برای هر کاربر به پایان رسیده است.
75 | ReferralCodeUnavailable | امکان ایجاد کد دعوت در حال حاضر وجود ندارد.
76 | ReferralCodeExists | خطایی در ثبت کد دعوت رخ داده است.
77 |
78 |
79 | ## وضعیت دعوت کاربر
80 |
81 |
82 | ```shell
83 | curl -X GET 'https://apiv2.nobitex.ir/users/referral/referral-status' \
84 | --header 'Authorization: Token yourTOKENhereHEX0000000000'
85 | ```
86 |
87 | ```plaintext
88 | http --follow --timeout 3600 GET https://apiv2.nobitex.ir/users/referral/referral-status \
89 | Authorization:'Token yourTOKENhereHEX0000000000'
90 | ```
91 |
92 | برای اطلاع از این که کاربر فعلی توسط کاربر دیگری به نوبیتکس دعوت شده است یا خیر، از «وضعیت دعوت کاربر» استفاده نمایید.
93 |
94 | * **درخواست:** `POST /users/referral/referral-status`
95 | * **محدودیت فراخوانی:** ۵۰ درخواست در هر ۱۰ دقیقه
96 |
97 | ### پارامترهای پاسخ
98 | پارامتر | نوع | توضیحات | نمونه
99 | ---- | ---- | ---- | ----
100 | hasReferrer | boolean | آیا کاربر توسط کاربر دیگری دعوت شده است؟ | `true`
101 |
102 |
103 | ## ثبت معرف کاربر
104 |
105 | ```shell
106 | curl -X GET 'https://apiv2.nobitex.ir/users/referral/set-referrer' \
107 | --header 'Authorization: Token yourTOKENhereHEX0000000000'
108 | ```
109 |
110 | ```plaintext
111 | http --follow --timeout 3600 GET https://apiv2.nobitex.ir/users/referral/set-referrer \
112 | Authorization:'Token yourTOKENhereHEX0000000000'
113 | ```
114 |
115 | کد دعوت باید در زمان ثبتنام توسط کاربر وارد شده یا با استفاده از پیوند دعوت به صورت خودکار پر شود. با این حال تا ۲۴ ساعت
116 | پس از ثبتنام نیز امکان ثبت معرف توسط کاربر با استفاده از این API وجود دارد. منظور از کاربر معرف، کاربری است که کاربر فعلی
117 | را دعوت نموده است.
118 |
119 | * **درخواست:** `POST /users/referral/set-referrer`
120 | * **محدودیت فراخوانی:** ۵۰ درخواست در هر ۱۰ دقیقه
121 |
122 | ### پارامترهای ورودی
123 | پارامتر | نوع | پیشفرض | توضیحات | نمونه
124 | ------- | ---- | --------- | --------- | -----
125 | referrerCode | string | الزامی | کد دعوت کاربر دعوت کننده | `40404`
126 |
127 | ### حالتهای خطا
128 | کد خطا | توضیحات
129 | ---- | ----
130 | ReferrerChangeUnavailable | بیش از ۲۴ ساعت از ثبتنام کاربر گذشته است و تعریف معرف دیگر ممکن نیست.
131 |
--------------------------------------------------------------------------------
/source/javascripts/lib/_energize.js:
--------------------------------------------------------------------------------
1 | /**
2 | * energize.js v0.1.0
3 | *
4 | * Speeds up click events on mobile devices.
5 | * https://github.com/davidcalhoun/energize.js
6 | */
7 |
8 | (function() { // Sandbox
9 | /**
10 | * Don't add to non-touch devices, which don't need to be sped up
11 | */
12 | if(!('ontouchstart' in window)) return;
13 |
14 | var lastClick = {},
15 | isThresholdReached, touchstart, touchmove, touchend,
16 | click, closest;
17 |
18 | /**
19 | * isThresholdReached
20 | *
21 | * Compare touchstart with touchend xy coordinates,
22 | * and only fire simulated click event if the coordinates
23 | * are nearby. (don't want clicking to be confused with a swipe)
24 | */
25 | isThresholdReached = function(startXY, xy) {
26 | return Math.abs(startXY[0] - xy[0]) > 5 || Math.abs(startXY[1] - xy[1]) > 5;
27 | };
28 |
29 | /**
30 | * touchstart
31 | *
32 | * Save xy coordinates when the user starts touching the screen
33 | */
34 | touchstart = function(e) {
35 | this.startXY = [e.touches[0].clientX, e.touches[0].clientY];
36 | this.threshold = false;
37 | };
38 |
39 | /**
40 | * touchmove
41 | *
42 | * Check if the user is scrolling past the threshold.
43 | * Have to check here because touchend will not always fire
44 | * on some tested devices (Kindle Fire?)
45 | */
46 | touchmove = function(e) {
47 | // NOOP if the threshold has already been reached
48 | if(this.threshold) return false;
49 |
50 | this.threshold = isThresholdReached(this.startXY, [e.touches[0].clientX, e.touches[0].clientY]);
51 | };
52 |
53 | /**
54 | * touchend
55 | *
56 | * If the user didn't scroll past the threshold between
57 | * touchstart and touchend, fire a simulated click.
58 | *
59 | * (This will fire before a native click)
60 | */
61 | touchend = function(e) {
62 | // Don't fire a click if the user scrolled past the threshold
63 | if(this.threshold || isThresholdReached(this.startXY, [e.changedTouches[0].clientX, e.changedTouches[0].clientY])) {
64 | return;
65 | }
66 |
67 | /**
68 | * Create and fire a click event on the target element
69 | * https://developer.mozilla.org/en/DOM/event.initMouseEvent
70 | */
71 | var touch = e.changedTouches[0],
72 | evt = document.createEvent('MouseEvents');
73 | evt.initMouseEvent('click', true, true, window, 0, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
74 | evt.simulated = true; // distinguish from a normal (nonsimulated) click
75 | e.target.dispatchEvent(evt);
76 | };
77 |
78 | /**
79 | * click
80 | *
81 | * Because we've already fired a click event in touchend,
82 | * we need to listed for all native click events here
83 | * and suppress them as necessary.
84 | */
85 | click = function(e) {
86 | /**
87 | * Prevent ghost clicks by only allowing clicks we created
88 | * in the click event we fired (look for e.simulated)
89 | */
90 | var time = Date.now(),
91 | timeDiff = time - lastClick.time,
92 | x = e.clientX,
93 | y = e.clientY,
94 | xyDiff = [Math.abs(lastClick.x - x), Math.abs(lastClick.y - y)],
95 | target = closest(e.target, 'A') || e.target, // needed for standalone apps
96 | nodeName = target.nodeName,
97 | isLink = nodeName === 'A',
98 | standAlone = window.navigator.standalone && isLink && e.target.getAttribute("href");
99 |
100 | lastClick.time = time;
101 | lastClick.x = x;
102 | lastClick.y = y;
103 |
104 | /**
105 | * Unfortunately Android sometimes fires click events without touch events (seen on Kindle Fire),
106 | * so we have to add more logic to determine the time of the last click. Not perfect...
107 | *
108 | * Older, simpler check: if((!e.simulated) || standAlone)
109 | */
110 | if((!e.simulated && (timeDiff < 500 || (timeDiff < 1500 && xyDiff[0] < 50 && xyDiff[1] < 50))) || standAlone) {
111 | e.preventDefault();
112 | e.stopPropagation();
113 | if(!standAlone) return false;
114 | }
115 |
116 | /**
117 | * Special logic for standalone web apps
118 | * See http://stackoverflow.com/questions/2898740/iphone-safari-web-app-opens-links-in-new-window
119 | */
120 | if(standAlone) {
121 | window.location = target.getAttribute("href");
122 | }
123 |
124 | /**
125 | * Add an energize-focus class to the targeted link (mimics :focus behavior)
126 | * TODO: test and/or remove? Does this work?
127 | */
128 | if(!target || !target.classList) return;
129 | target.classList.add("energize-focus");
130 | window.setTimeout(function(){
131 | target.classList.remove("energize-focus");
132 | }, 150);
133 | };
134 |
135 | /**
136 | * closest
137 | * @param {HTMLElement} node current node to start searching from.
138 | * @param {string} tagName the (uppercase) name of the tag you're looking for.
139 | *
140 | * Find the closest ancestor tag of a given node.
141 | *
142 | * Starts at node and goes up the DOM tree looking for a
143 | * matching nodeName, continuing until hitting document.body
144 | */
145 | closest = function(node, tagName){
146 | var curNode = node;
147 |
148 | while(curNode !== document.body) { // go up the dom until we find the tag we're after
149 | if(!curNode || curNode.nodeName === tagName) { return curNode; } // found
150 | curNode = curNode.parentNode; // not found, so keep going up
151 | }
152 |
153 | return null; // not found
154 | };
155 |
156 | /**
157 | * Add all delegated event listeners
158 | *
159 | * All the events we care about bubble up to document,
160 | * so we can take advantage of event delegation.
161 | *
162 | * Note: no need to wait for DOMContentLoaded here
163 | */
164 | document.addEventListener('touchstart', touchstart, false);
165 | document.addEventListener('touchmove', touchmove, false);
166 | document.addEventListener('touchend', touchend, false);
167 | document.addEventListener('click', click, true); // TODO: why does this use capture?
168 |
169 | })();
--------------------------------------------------------------------------------
/source/postman/Nobitex Gateway.postman_collection.json:
--------------------------------------------------------------------------------
1 | {
2 | "info": {
3 | "_postman_id": "0c525a53-2c6a-48f5-8111-5ae3657f28aa",
4 | "name": "Nobitex Gateway",
5 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
6 | },
7 | "item": [
8 | {
9 | "name": "token",
10 | "request": {
11 | "method": "POST",
12 | "header": [
13 | {
14 | "key": "Content-Type",
15 | "name": "Content-Type",
16 | "value": "application/json",
17 | "type": "text"
18 | }
19 | ],
20 | "body": {
21 | "mode": "raw",
22 | "raw": "{\n\t\"api\":\"DemoApiKey\",\n\t\"amount\":1000000,\n\t\"callbackURL\":\"https://nobitex.ir\",\n\t\"factorNumber\":\"10\",\n\t\"mobile\":\"09123456789\",\n\t\"description\":\"Payment with Nobitex\",\n\t\"currencies\":\"btc\"\n}"
23 | },
24 | "url": {
25 | "raw": "https://apiv2.nobitex.ir/pg/send/",
26 | "protocol": "https",
27 | "host": [
28 | "api",
29 | "nobitex",
30 | "market"
31 | ],
32 | "path": [
33 | "pg",
34 | "send",
35 | ""
36 | ]
37 | }
38 | },
39 | "response": [
40 | {
41 | "name": "token",
42 | "originalRequest": {
43 | "method": "POST",
44 | "header": [
45 | {
46 | "key": "Content-Type",
47 | "name": "Content-Type",
48 | "value": "application/json",
49 | "type": "text"
50 | }
51 | ],
52 | "body": {
53 | "mode": "raw",
54 | "raw": "{\n\t\"api\":\"DemoApiKey\",\n\t\"amount\":1000000,\n\t\"callbackURL\":\"https://nobitex.ir\",\n\t\"factorNumber\":\"10\",\n\t\"mobile\":\"09123456789\",\n\t\"description\":\"Payment with Nobitex\",\n\t\"currencies\":\"btc\"\n}"
55 | },
56 | "url": {
57 | "raw": "https://apiv2.nobitex.ir/pg/send/",
58 | "protocol": "https",
59 | "host": [
60 | "api",
61 | "nobitex",
62 | "market"
63 | ],
64 | "path": [
65 | "pg",
66 | "send",
67 | ""
68 | ]
69 | }
70 | },
71 | "status": "OK",
72 | "code": 200,
73 | "_postman_previewlanguage": "json",
74 | "header": [
75 | {
76 | "key": "Server",
77 | "value": "nginx/1.14.0 (Ubuntu)"
78 | },
79 | {
80 | "key": "Date",
81 | "value": "Sat, 14 Sep 2019 11:00:56 GMT"
82 | },
83 | {
84 | "key": "Content-Type",
85 | "value": "application/json"
86 | },
87 | {
88 | "key": "Content-Length",
89 | "value": "66"
90 | },
91 | {
92 | "key": "Connection",
93 | "value": "keep-alive"
94 | },
95 | {
96 | "key": "Vary",
97 | "value": "Accept, Origin"
98 | },
99 | {
100 | "key": "Allow",
101 | "value": "POST, OPTIONS"
102 | },
103 | {
104 | "key": "Strict-Transport-Security",
105 | "value": "max-age=31536000; includeSubdomains"
106 | },
107 | {
108 | "key": "X-Frame-Options",
109 | "value": "DENY"
110 | },
111 | {
112 | "key": "X-XSS-Protection",
113 | "value": "1; mode=block"
114 | },
115 | {
116 | "key": "Referrer-Policy",
117 | "value": "origin-when-cross-origin"
118 | },
119 | {
120 | "key": "X-Content-Type-Options",
121 | "value": "nosniff"
122 | }
123 | ],
124 | "cookie": [],
125 | "body": "{\n \"status\": \"success\",\n \"token\": \"f6838d15fb024b0eb6d83e4c2a2028d3\"\n}"
126 | }
127 | ]
128 | },
129 | {
130 | "name": "verify payment",
131 | "request": {
132 | "method": "POST",
133 | "header": [
134 | {
135 | "key": "Content-Type",
136 | "name": "Content-Type",
137 | "value": "application/json",
138 | "type": "text"
139 | }
140 | ],
141 | "body": {
142 | "mode": "raw",
143 | "raw": "{\n\t\"api\":\"DemoApiKey\",\n\t\"token\":\"f50116d31d4a4d1ab93d1f2759f198bb\"\n}"
144 | },
145 | "url": {
146 | "raw": "https://apiv2.nobitex.ir/pg/verify/",
147 | "protocol": "https",
148 | "host": [
149 | "api",
150 | "nobitex",
151 | "market"
152 | ],
153 | "path": [
154 | "pg",
155 | "verify",
156 | ""
157 | ]
158 | }
159 | },
160 | "response": [
161 | {
162 | "name": "verify payment",
163 | "originalRequest": {
164 | "method": "POST",
165 | "header": [
166 | {
167 | "key": "Content-Type",
168 | "name": "Content-Type",
169 | "value": "application/json",
170 | "type": "text"
171 | }
172 | ],
173 | "body": {
174 | "mode": "raw",
175 | "raw": "{\n\t\"api\":\"DemoApiKey\",\n\t\"token\":\"f50116d31d4a4d1ab93d1f2759f198bb\"\n}"
176 | },
177 | "url": {
178 | "raw": "https://apiv2.nobitex.ir/pg/verify/",
179 | "protocol": "https",
180 | "host": [
181 | "api",
182 | "nobitex",
183 | "market"
184 | ],
185 | "path": [
186 | "pg",
187 | "verify",
188 | ""
189 | ]
190 | }
191 | },
192 | "status": "OK",
193 | "code": 200,
194 | "_postman_previewlanguage": "json",
195 | "header": [
196 | {
197 | "key": "Server",
198 | "value": "nginx/1.14.0 (Ubuntu)"
199 | },
200 | {
201 | "key": "Date",
202 | "value": "Sat, 14 Sep 2019 11:35:51 GMT"
203 | },
204 | {
205 | "key": "Content-Type",
206 | "value": "application/json"
207 | },
208 | {
209 | "key": "Content-Length",
210 | "value": "200"
211 | },
212 | {
213 | "key": "Connection",
214 | "value": "keep-alive"
215 | },
216 | {
217 | "key": "Vary",
218 | "value": "Accept, Origin"
219 | },
220 | {
221 | "key": "Allow",
222 | "value": "POST, OPTIONS"
223 | },
224 | {
225 | "key": "Strict-Transport-Security",
226 | "value": "max-age=31536000; includeSubdomains"
227 | },
228 | {
229 | "key": "X-Frame-Options",
230 | "value": "DENY"
231 | },
232 | {
233 | "key": "X-XSS-Protection",
234 | "value": "1; mode=block"
235 | },
236 | {
237 | "key": "Referrer-Policy",
238 | "value": "origin-when-cross-origin"
239 | },
240 | {
241 | "key": "X-Content-Type-Options",
242 | "value": "nosniff"
243 | }
244 | ],
245 | "cookie": [],
246 | "body": "{\n \"status\": \"success\",\n \"amount\": 1000000,\n \"cryptoAmount\": 85516,\n \"txHash\": \"825d6613a6eef4566abf4ba7bae83618\",\n \"factorNumber\": \"10\",\n \"mobile\": \"09123456789\",\n \"description\": \"Test Payment with Nobitex\"\n}"
247 | }
248 | ]
249 | }
250 | ]
251 | }
252 |
--------------------------------------------------------------------------------
/source/includes/_auth.md:
--------------------------------------------------------------------------------
1 |
احراز هویت
2 |
3 |
روش پیشنهادی دریافت توکن
4 |
5 | روش پیشنهادی نوبیتکس برای دریافت توکن استفاده از API، دریافت آن از پنل کاربری است. برای دریافت توکن میتوانید با مراجعه به پنل کاربری خود در نوبیتکس، از بخش پروفایل وارد صفحه تنظیمات شده و توکن خود را دریافت نمایید. در صورتی که گزینه «مرا به خاطر بسپار» را در هنگام ورود به نوبیتکس انتخاب کرده باشید، این توکن تا ۳۰ روز یا زمان لاگاوت شما از نوبیتکس معتبر خواهد ماند.
6 |
7 | در ادامه روش دریافت خودکار توکن با استفاده از کد توضیح داده میشود. معمولاً دریافت خودکار توکن ضروری نیست و روش پیشنهادی ما برای اغلب کاربران دریافت مستقیم توکن از پنل کاربری است. تنها در صورتی که با مخاطرات ذخیره گذرواژه خود در کد و روشهای امن این کار آشنا هستید، در استفاده از API مهارت دارید، و از طرفی نیاز به دریافت کاملاً خودکار توکن دارید، از API دریافت توکن استفاده نمایید.
8 |
9 | همین طور پیشنهاد میشود که گامهای اولیه توسعه کد خود را با دریافت توکن از پنل انجام دهید تا با فرآیند استفاده از API نوبیتکس بیشتر آشنا شوید و تنها در صورت نیاز و در گام نهاییسازی کد خود اقدام به خودکارسازی دریافت توکن نمایید. لازم به توضیح است که به دلیل مسائل امنیتی مانند شناسایی دوعاملی و کپچا و ... برای دریافت خودکار توکن باید به دقت مستندات این بخش را مطالعه نمایید.
10 |
11 |
ورود - دریافت توکن
12 | > برای دریافت توکن، از این کد استفاده کنید:
13 |
14 | ```shell
15 | curl 'https://apiv2.nobitex.ir/auth/login/' \
16 | -X POST \
17 | --header "Content-Type: application/json" \
18 | --header "X-TOTP: " \
19 | --header "User-Agent: TraderBot/" \
20 | --data $'{"username":"name@example.com","password":"secret-password-1234","captcha":"api"}'
21 | ```
22 |
23 | ```plaintext
24 | http POST https://apiv2.nobitex.ir/auth/login/ \
25 | username=name@example.com password=secret-password-1234 captcha=api
26 | ```
27 |
28 | > در صورت فراخوانی درست، پاسخ به این صورت خواهد بود:
29 |
30 | ```json
31 | {
32 | "status": "success",
33 | "key": "db2055f743c1ac8c30d23278a496283b1e2dd46f",
34 | "device": "AlRyansW"
35 | }
36 | ```
37 |
38 | دریافت توکن به صورت خودکار و با ارسال درخواست به `/auth/login/` صورت میگیرد. این تنها APIی است که نیاز دارید
39 | به آن نام کاربری و رمز عبور خود را ارسال کنید. تمامی دیگر APIها از توکن به جای رمز عبور برای احراز هویت استفاده میکنند.
40 | توکنهای صادر شده بعد از چهار ساعت منقضی میشوند و باید مجددا با ارسال درخواست لاگین، توکن جدیدی دریافت کنید.
41 | در صورتی که نیاز به ایجاد توکنهای بلند مدت دارید، از پارامتر `remember=yes` استفاده کنید تا توکن ایجاد شده به مدت سی
42 | روز معتبر بماند.
43 | توجه داشته باشید، در صورتی که قصد استفاده از وب سرویس بدون ورود کپچای تصویری را دارید، نیاز است مقدار captcha حتما برابر api تنظیم شود و کد دوعاملی بر روی حساب کاربری تنظیم گردد و مقدار لحظه ای آن در هدر ریکویست ارسال شود. همینطور مقدار هدر User-Agent را مطابق الگوی TraderBot/XXXXX ارسال نمایید، که بخش XXXXX هر نام یکتایی است که میتوانید برای بات خود انتخاب کنید. جهت تنظیم کد دوعاملی، توضیحات دقیقتر را از اینجا مطالعه فرمایید.
44 |
45 |
46 | * **درخواست:** `/POST /auth/login `
47 | * **محدودیت فراخوانی:** ۳۰ درخواست در هر ۱۰ دقیقه
48 |
49 |
50 | ### پارامترهای ورودی
51 |
52 | پارامتر | نوع | پیشفرض | توضیحات | نمونه
53 | ------- | ---- | --------- | --------- | -----
54 | username | string | الزامی | ایمیل کاربر | `name@example.com`
55 | password | string | الزامی | گذرواژه کاربر | `secret-password-1234`
56 | remember | string | no | آیا توکن بلند مدت صادر شود؟ | `yes` یا `no`
57 | captcha | string | الزامی | کپچا | `api`
58 |
59 |
60 | ### پارامترهای هدر
61 |
62 | پارامتر | نوع | پیشفرض | توضیحات | نمونه
63 | ------- | ---- | --------- |----------------------| -----
64 | X-TOTP | string | الزامی | کد دوعاملی | `123456`
65 | User-Agent | string | الزامی | ایجنت | `TraderBot/1.0.0`
66 |
67 | ### نکات و ملاحظات
68 |
69 | 1. دقت نمایید که انتهای آدرس url ارسال درخواست، حتماً باید `/` گذاشته شود.
70 | 2. توکنهای دریافت شده از این روش، بعد از اتمام زمان اعتبار یا انجام عملیات لاگاوت منقضی میشوند. زمان پیشفرض اعتبار توکن چهار ساعت است که میتوانید با استفاده از پارامتر `remember` توکنهایی با زمان اعتبار یک ماه دریافت نمایید.
71 | 3. برای لاگین و دریافت توکن، حتماً باید از آیپی ایران درخواست ارسال شود. در غیر این صورت، خطای 429 برگردانده میشود. بدیهی است که استفاده از هر VPN یا VPS خارجی، منجر به این خطا خواهد شد. در حالت استفاده از آیپی ایران میتوانید مقدار کپچا را در درخواست برابر `api` مقداردهی کنید.
72 | 4. در صورت مشکل در دریافت توکن، میتوانید مطابق [روش پیشنهادی](#auth-intro) دریافت توکن از توکنهای موجود در تنظیمات پروفایل خود استفاده کنید.
73 |
74 |
75 |
سوالات متداول دریافت توکن
76 |
77 | ### آیا نوبیتکس توکن بلند مدت هم ارائه میدهد؟
78 | در نوبیتکس میتوانید توکنهایی با تاریخ انقضای حداکثر یک ماه دریافت نمایید. در صورتی که گزینه «مرا به خاطر بسپار» را در زمان لاگین به سایت نوبیتکس انتخاب نمایید، توکنی که در بخش پروفایل دریافت میکنید برای مدت یک ماه معتبر خواهد بود. در صورتی که از API دریافت توکن استفاده میکنید، میتوانید از پارامتر `remember` استفاده کنید. مد نظر داشته باشید که در صورت انجام عملیات لاگاوت از حساب خود در سایت یا API توکن شما دیگر معتبر نخواهد ماند.
79 |
80 | ### من با استفاده از گوگل در نوبیتکس ثبت نام کردهام. چگونه میتوانم با API کار کنم؟
81 | [روش پیشنهادی](#auth-intro) دریافت توکن، دریافت آن از پنل کاربری است و با این روش تمام کاربران مستقل از روش ورود به نوبیتکس میتوانند توکن خود را مشاهده و دریافت نمایند. کاربرانی که با استفاده از حساب گوگل در نوبیتکس ثبتنام کرده باشند و بخواهند از روش خودکار دریافت توکن استفاده کنند، میتوانند از امکان فراموشی رمز عبور استفاده کرده و رمز جدید برای حساب خود تعیین و پس از آن اقدام به استفاده از API نمایند.
82 |
83 | ### در هنگام لاگین با خطای MissingCaptcha روبرو شدهام. مشکل چیست؟
84 | مطابق [روش پیشنهادی](#auth-intro) دریافت توکن، برای دریافت توکن به پنل کاربری خود در سایت، بخش «پروفایل: تنظیمات» مراجعه نمایید. اگر از روش خودکار دریافت توکن استفاده میکنید، مستندات مربوطه را با دقت مطالعه نمایید.
85 |
86 | ### در هنگام لاگین با خطای MissingOTP روبرو شده ام. چگونه این مشکل حل میشود؟
87 | هنگامی که شناسایی دوعاملی حساب شما فعال باشد، در هنگام استفاده از API نیز میبایست این حالت حفظ شده و رمز یکبار مصرف ارسال گردد. این کار از طریق ارسال این رمز با استفاده از پارامتر X-TOTP امکانپذیر خواهد بود. تولید کد دوعاملی با استفاده از فرمول استانداردی در کد ممکن است.
88 |
89 |
90 |
خروج - سوزاندن توکن
91 | > برای خروج یا سوزاندن توکن، از این کد استفاده کنید:
92 |
93 | ```shell
94 | curl -X POST 'https://apiv2.nobitex.ir/auth/logout/' \
95 | --header 'Authorization: Token yourTOKENhereHEX0000000000'
96 | ```
97 |
98 | ```plaintext
99 | POST /auth/logout/ HTTP/1.1
100 | Host: apiv2.nobitex.ir
101 | Authorization: Token yourTOKENhereHEX0000000000
102 | ```
103 |
104 | > در صورت فراخوانی درست، پاسخ به این صورت خواهد بود:
105 |
106 | ```json
107 | {
108 | "detail": "خروج با موفقیت انجام شد.",
109 | "message": "خروج با موفقیت انجام شد."
110 | }
111 | ```
112 |
113 | - **درخواست:** `/POST /auth/logout `
114 |
--------------------------------------------------------------------------------
/source/postman/Nobitex Gateway Testnet.postman_collection.json:
--------------------------------------------------------------------------------
1 | {
2 | "info": {
3 | "_postman_id": "1c466724-e931-459b-b644-39d2e2b0addf",
4 | "name": "Nobitex Gateway Testnet",
5 | "description": "https://apidocs.nobitex.ir/gateway",
6 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
7 | },
8 | "item": [
9 | {
10 | "name": "token (testnet)",
11 | "request": {
12 | "method": "POST",
13 | "header": [
14 | {
15 | "key": "Content-Type",
16 | "name": "Content-Type",
17 | "value": "application/json",
18 | "type": "text"
19 | }
20 | ],
21 | "body": {
22 | "mode": "raw",
23 | "raw": "{\n\t\"api\":\"DemoApiKey\",\n\t\"amount\":1000000,\n\t\"callbackURL\":\"http://localhost\",\n\t\"factorNumber\":\"10\",\n\t\"mobile\":\"09123456789\",\n\t\"description\":\"Test Payment with Nobitex\",\n\t\"currencies\":\"btc\"\n}"
24 | },
25 | "url": {
26 | "raw": "https://testnetapiv2.nobitex.ir/pg/send/",
27 | "protocol": "https",
28 | "host": [
29 | "testnetapi",
30 | "nobitex",
31 | "market"
32 | ],
33 | "path": [
34 | "pg",
35 | "send",
36 | ""
37 | ]
38 | }
39 | },
40 | "response": [
41 | {
42 | "name": "token (testnet)",
43 | "originalRequest": {
44 | "method": "POST",
45 | "header": [
46 | {
47 | "key": "Content-Type",
48 | "name": "Content-Type",
49 | "value": "application/json",
50 | "type": "text"
51 | }
52 | ],
53 | "body": {
54 | "mode": "raw",
55 | "raw": "{\n\t\"api\":\"DemoApiKey\",\n\t\"amount\":1000000,\n\t\"callbackURL\":\"http://localhost\",\n\t\"factorNumber\":\"10\",\n\t\"mobile\":\"09123456789\",\n\t\"description\":\"Test Payment with Nobitex\",\n\t\"currencies\":\"btc\"\n}"
56 | },
57 | "url": {
58 | "raw": "https://testnetapiv2.nobitex.ir/pg/send/",
59 | "protocol": "https",
60 | "host": [
61 | "testnetapi",
62 | "nobitex",
63 | "market"
64 | ],
65 | "path": [
66 | "pg",
67 | "send",
68 | ""
69 | ]
70 | }
71 | },
72 | "status": "OK",
73 | "code": 200,
74 | "_postman_previewlanguage": "json",
75 | "header": [
76 | {
77 | "key": "Server",
78 | "value": "nginx/1.14.0 (Ubuntu)"
79 | },
80 | {
81 | "key": "Date",
82 | "value": "Sat, 14 Sep 2019 11:00:56 GMT"
83 | },
84 | {
85 | "key": "Content-Type",
86 | "value": "application/json"
87 | },
88 | {
89 | "key": "Content-Length",
90 | "value": "66"
91 | },
92 | {
93 | "key": "Connection",
94 | "value": "keep-alive"
95 | },
96 | {
97 | "key": "Vary",
98 | "value": "Accept, Origin"
99 | },
100 | {
101 | "key": "Allow",
102 | "value": "POST, OPTIONS"
103 | },
104 | {
105 | "key": "Strict-Transport-Security",
106 | "value": "max-age=31536000; includeSubdomains"
107 | },
108 | {
109 | "key": "X-Frame-Options",
110 | "value": "DENY"
111 | },
112 | {
113 | "key": "X-XSS-Protection",
114 | "value": "1; mode=block"
115 | },
116 | {
117 | "key": "Referrer-Policy",
118 | "value": "origin-when-cross-origin"
119 | },
120 | {
121 | "key": "X-Content-Type-Options",
122 | "value": "nosniff"
123 | }
124 | ],
125 | "cookie": [],
126 | "body": "{\n \"status\": \"success\",\n \"token\": \"f6838d15fb024b0eb6d83e4c2a2028d3\"\n}"
127 | }
128 | ]
129 | },
130 | {
131 | "name": "verify payment (testnet)",
132 | "request": {
133 | "method": "POST",
134 | "header": [
135 | {
136 | "key": "Content-Type",
137 | "name": "Content-Type",
138 | "value": "application/json",
139 | "type": "text"
140 | }
141 | ],
142 | "body": {
143 | "mode": "raw",
144 | "raw": "{\n\t\"api\":\"DemoApiKey\",\n\t\"token\":\"f50116d31d4a4d1ab93d1f2759f198bb\"\n}"
145 | },
146 | "url": {
147 | "raw": "https://testnetapiv2.nobitex.ir/pg/verify/",
148 | "protocol": "https",
149 | "host": [
150 | "testnetapi",
151 | "nobitex",
152 | "market"
153 | ],
154 | "path": [
155 | "pg",
156 | "verify",
157 | ""
158 | ]
159 | }
160 | },
161 | "response": [
162 | {
163 | "name": "verify payment (testnet)",
164 | "originalRequest": {
165 | "method": "POST",
166 | "header": [
167 | {
168 | "key": "Content-Type",
169 | "name": "Content-Type",
170 | "value": "application/json",
171 | "type": "text"
172 | }
173 | ],
174 | "body": {
175 | "mode": "raw",
176 | "raw": "{\n\t\"api\":\"DemoApiKey\",\n\t\"token\":\"f50116d31d4a4d1ab93d1f2759f198bb\"\n}"
177 | },
178 | "url": {
179 | "raw": "https://testnetapiv2.nobitex.ir/pg/verify/",
180 | "protocol": "https",
181 | "host": [
182 | "testnetapi",
183 | "nobitex",
184 | "market"
185 | ],
186 | "path": [
187 | "pg",
188 | "verify",
189 | ""
190 | ]
191 | }
192 | },
193 | "status": "OK",
194 | "code": 200,
195 | "_postman_previewlanguage": "json",
196 | "header": [
197 | {
198 | "key": "Server",
199 | "value": "nginx/1.14.0 (Ubuntu)"
200 | },
201 | {
202 | "key": "Date",
203 | "value": "Sat, 14 Sep 2019 11:35:51 GMT"
204 | },
205 | {
206 | "key": "Content-Type",
207 | "value": "application/json"
208 | },
209 | {
210 | "key": "Content-Length",
211 | "value": "200"
212 | },
213 | {
214 | "key": "Connection",
215 | "value": "keep-alive"
216 | },
217 | {
218 | "key": "Vary",
219 | "value": "Accept, Origin"
220 | },
221 | {
222 | "key": "Allow",
223 | "value": "POST, OPTIONS"
224 | },
225 | {
226 | "key": "Strict-Transport-Security",
227 | "value": "max-age=31536000; includeSubdomains"
228 | },
229 | {
230 | "key": "X-Frame-Options",
231 | "value": "DENY"
232 | },
233 | {
234 | "key": "X-XSS-Protection",
235 | "value": "1; mode=block"
236 | },
237 | {
238 | "key": "Referrer-Policy",
239 | "value": "origin-when-cross-origin"
240 | },
241 | {
242 | "key": "X-Content-Type-Options",
243 | "value": "nosniff"
244 | }
245 | ],
246 | "cookie": [],
247 | "body": "{\n \"status\": \"success\",\n \"amount\": 1000000,\n \"cryptoAmount\": 85516,\n \"txHash\": \"825d6613a6eef4566abf4ba7bae83618\",\n \"factorNumber\": \"10\",\n \"mobile\": \"09123456789\",\n \"description\": \"Test Payment with Nobitex\"\n}"
248 | }
249 | ]
250 | }
251 | ]
252 | }
253 |
--------------------------------------------------------------------------------
/deploy.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -o errexit #abort if any command fails
3 | me=$(basename "$0")
4 |
5 | help_message="\
6 | Usage: $me [-c FILE] []
7 | Deploy generated files to a git branch.
8 |
9 | Options:
10 |
11 | -h, --help Show this help information.
12 | -v, --verbose Increase verbosity. Useful for debugging.
13 | -e, --allow-empty Allow deployment of an empty directory.
14 | -m, --message MESSAGE Specify the message used when committing on the
15 | deploy branch.
16 | -n, --no-hash Don't append the source commit's hash to the deploy
17 | commit's message.
18 | --source-only Only build but not push
19 | --push-only Only push but not build
20 | "
21 |
22 |
23 | run_build() {
24 | bundle exec middleman build --clean
25 | }
26 |
27 | parse_args() {
28 | # Set args from a local environment file.
29 | if [ -e ".env" ]; then
30 | source .env
31 | fi
32 |
33 | # Parse arg flags
34 | # If something is exposed as an environment variable, set/overwrite it
35 | # here. Otherwise, set/overwrite the internal variable instead.
36 | while : ; do
37 | if [[ $1 = "-h" || $1 = "--help" ]]; then
38 | echo "$help_message"
39 | exit 0
40 | elif [[ $1 = "-v" || $1 = "--verbose" ]]; then
41 | verbose=true
42 | shift
43 | elif [[ $1 = "-e" || $1 = "--allow-empty" ]]; then
44 | allow_empty=true
45 | shift
46 | elif [[ ( $1 = "-m" || $1 = "--message" ) && -n $2 ]]; then
47 | commit_message=$2
48 | shift 2
49 | elif [[ $1 = "-n" || $1 = "--no-hash" ]]; then
50 | GIT_DEPLOY_APPEND_HASH=false
51 | shift
52 | elif [[ $1 = "--source-only" ]]; then
53 | source_only=true
54 | shift
55 | elif [[ $1 = "--push-only" ]]; then
56 | push_only=true
57 | shift
58 | else
59 | break
60 | fi
61 | done
62 |
63 | if [ ${source_only} ] && [ ${push_only} ]; then
64 | >&2 echo "You can only specify one of --source-only or --push-only"
65 | exit 1
66 | fi
67 |
68 | # Set internal option vars from the environment and arg flags. All internal
69 | # vars should be declared here, with sane defaults if applicable.
70 |
71 | # Source directory & target branch.
72 | deploy_directory=build
73 | deploy_branch=gh-pages
74 |
75 | #if no user identity is already set in the current git environment, use this:
76 | default_username=${GIT_DEPLOY_USERNAME:-deploy.sh}
77 | default_email=${GIT_DEPLOY_EMAIL:-}
78 |
79 | #repository to deploy to. must be readable and writable.
80 | repo=origin
81 |
82 | #append commit hash to the end of message by default
83 | append_hash=${GIT_DEPLOY_APPEND_HASH:-true}
84 | }
85 |
86 | main() {
87 | enable_expanded_output
88 |
89 | if ! git diff --exit-code --quiet --cached; then
90 | echo Aborting due to uncommitted changes in the index >&2
91 | return 1
92 | fi
93 |
94 | commit_title=`git log -n 1 --format="%s" HEAD`
95 | commit_hash=` git log -n 1 --format="%H" HEAD`
96 |
97 | #default commit message uses last title if a custom one is not supplied
98 | if [[ -z $commit_message ]]; then
99 | commit_message="publish: $commit_title"
100 | fi
101 |
102 | #append hash to commit message unless no hash flag was found
103 | if [ $append_hash = true ]; then
104 | commit_message="$commit_message"$'\n\n'"generated from commit $commit_hash"
105 | fi
106 |
107 | previous_branch=`git rev-parse --abbrev-ref HEAD`
108 |
109 | if [ ! -d "$deploy_directory" ]; then
110 | echo "Deploy directory '$deploy_directory' does not exist. Aborting." >&2
111 | return 1
112 | fi
113 |
114 | # must use short form of flag in ls for compatibility with macOS and BSD
115 | if [[ -z `ls -A "$deploy_directory" 2> /dev/null` && -z $allow_empty ]]; then
116 | echo "Deploy directory '$deploy_directory' is empty. Aborting. If you're sure you want to deploy an empty tree, use the --allow-empty / -e flag." >&2
117 | return 1
118 | fi
119 |
120 | if git ls-remote --exit-code $repo "refs/heads/$deploy_branch" ; then
121 | # deploy_branch exists in $repo; make sure we have the latest version
122 |
123 | disable_expanded_output
124 | git fetch --force $repo $deploy_branch:$deploy_branch
125 | enable_expanded_output
126 | fi
127 |
128 | # check if deploy_branch exists locally
129 | if git show-ref --verify --quiet "refs/heads/$deploy_branch"
130 | then incremental_deploy
131 | else initial_deploy
132 | fi
133 |
134 | restore_head
135 | }
136 |
137 | initial_deploy() {
138 | git --work-tree "$deploy_directory" checkout --orphan $deploy_branch
139 | git --work-tree "$deploy_directory" add --all
140 | commit+push
141 | }
142 |
143 | incremental_deploy() {
144 | #make deploy_branch the current branch
145 | git symbolic-ref HEAD refs/heads/$deploy_branch
146 | #put the previously committed contents of deploy_branch into the index
147 | git --work-tree "$deploy_directory" reset --mixed --quiet
148 | git --work-tree "$deploy_directory" add --all
149 |
150 | set +o errexit
151 | diff=$(git --work-tree "$deploy_directory" diff --exit-code --quiet HEAD --)$?
152 | set -o errexit
153 | case $diff in
154 | 0) echo No changes to files in $deploy_directory. Skipping commit.;;
155 | 1) commit+push;;
156 | *)
157 | echo git diff exited with code $diff. Aborting. Staying on branch $deploy_branch so you can debug. To switch back to main, use: git symbolic-ref HEAD refs/heads/main && git reset --mixed >&2
158 | return $diff
159 | ;;
160 | esac
161 | }
162 |
163 | commit+push() {
164 | set_user_id
165 | git --work-tree "$deploy_directory" commit -m "$commit_message"
166 |
167 | disable_expanded_output
168 | #--quiet is important here to avoid outputting the repo URL, which may contain a secret token
169 | git push --quiet $repo $deploy_branch
170 | enable_expanded_output
171 | }
172 |
173 | #echo expanded commands as they are executed (for debugging)
174 | enable_expanded_output() {
175 | if [ $verbose ]; then
176 | set -o xtrace
177 | set +o verbose
178 | fi
179 | }
180 |
181 | #this is used to avoid outputting the repo URL, which may contain a secret token
182 | disable_expanded_output() {
183 | if [ $verbose ]; then
184 | set +o xtrace
185 | set -o verbose
186 | fi
187 | }
188 |
189 | set_user_id() {
190 | if [[ -z `git config user.name` ]]; then
191 | git config user.name "$default_username"
192 | fi
193 | if [[ -z `git config user.email` ]]; then
194 | git config user.email "$default_email"
195 | fi
196 | }
197 |
198 | restore_head() {
199 | if [[ $previous_branch = "HEAD" ]]; then
200 | #we weren't on any branch before, so just set HEAD back to the commit it was on
201 | git update-ref --no-deref HEAD $commit_hash $deploy_branch
202 | else
203 | git symbolic-ref HEAD refs/heads/$previous_branch
204 | fi
205 |
206 | git reset --mixed
207 | }
208 |
209 | filter() {
210 | sed -e "s|$repo|\$repo|g"
211 | }
212 |
213 | sanitize() {
214 | "$@" 2> >(filter 1>&2) | filter
215 | }
216 |
217 | parse_args "$@"
218 |
219 | if [[ ${source_only} ]]; then
220 | run_build
221 | elif [[ ${push_only} ]]; then
222 | main "$@"
223 | else
224 | run_build
225 | main "$@"
226 | fi
227 |
--------------------------------------------------------------------------------
/source/includes/_portfolio.md:
--------------------------------------------------------------------------------
1 |
سود و زیان
2 |
3 | «پرتفو» یا «پنل سود و زیان» کاربر، گزارشی است که با توجه به معاملات یا افزایش و کاهش قیمت رمزارزها در مارکت میزان سود یا ضرر بدست آمده و درصدهای آنها را نسبت به قیمت خریداری شده (موجودی) نمایش میدهد.
4 |
5 | در حال حاضر این اطلاعات در پرتفو هر کاربر ارائه میشود:
6 |
7 | * سود و زیان روزانه هفته گذشته
8 | * سود زیان کل به صورت روزانه در هفته گذشته
9 | * سود و زیان کل ماه گذشته
10 |
11 |
12 |
13 |
14 |
سود و زیان روزانه هفته گذشته
15 |
16 | ```shell
17 | curl -X POST 'https://apiv2.nobitex.ir/users/portfolio/last-week-daily-profit' \
18 | -H 'Authorization: Token yourTOKENhereHEX0000000000'
19 | ```
20 |
21 | ```plaintext
22 | http POST https://apiv2.nobitex.ir/users/portfolio/last-week-daily-profit \
23 | Authorization: Token yourTOKENhereHEX0000000000
24 | ```
25 |
26 | > در صورت فراخوانی درست، پاسخ به این صورت خواهد بود:
27 |
28 | ```json
29 | {
30 | "status": "ok",
31 | "data": [
32 | {
33 | "report_date": "2021-06-30",
34 | "total_profit": 0,
35 | "total_profit_percentage": 0,
36 | "total_balance": 0
37 | },
38 | {
39 | "report_date": "2021-07-01",
40 | "total_profit": 0,
41 | "total_profit_percentage": 0,
42 | "total_balance": 0
43 | },
44 | {
45 | "report_date": "2021-07-02",
46 | "total_profit": 0,
47 | "total_profit_percentage": 0,
48 | "total_balance": 0
49 | },
50 | {
51 | "report_date": "2021-07-03",
52 | "total_profit": 0,
53 | "total_profit_percentage": 0,
54 | "total_balance": 0
55 | },
56 | {
57 | "report_date": "2021-07-04",
58 | "total_profit": 0,
59 | "total_profit_percentage": 0,
60 | "total_balance": 0
61 | },
62 | {
63 | "report_date": "2021-07-05",
64 | "total_profit": "0E-10",
65 | "total_profit_percentage": "0E-10",
66 | "total_balance": "4516559.9205900000"
67 | },
68 | {
69 | "report_date": "2021-07-06",
70 | "total_profit": "152570.1426800000",
71 | "total_profit_percentage": "3.3780165737",
72 | "total_balance": "4669130.0632700000"
73 | }
74 | ]
75 | }
76 | ```
77 |
78 | > در صورتی که این ویژگی برای کاربر فعال نباشد با این جواب روبرو خواهند شد
79 |
80 | ```json
81 | {
82 | "status": "failed",
83 | "code": "PortfolioDisabled",
84 | "message": "Portfolio feature is not available for your user."
85 | }
86 | ```
87 |
88 | > در صورتی که اطلاعاتی از سود و زیان کاربر وجود نداشته باشد
89 |
90 | ```json
91 | {
92 | "status": "failed",
93 | "code": "LastWeekDailyProfitFail",
94 | "message": "اطلاعاتی جهت نمایش وجود ندارد"
95 | }
96 | ```
97 |
98 | برای دریافت اطلاعات سود و زیان روزانه هفته گذشته از این درخواست استفاده نمایید:
99 |
100 | * **درخواست:** `POST users/portfolio/last-week-daily-profit`
101 | * **محدودیت فراخوانی:** 10 درخواست در 3 دقیقه
102 |
103 | ### نکات و ملاحظات:
104 | این API به صورت پیش فرض اطلاعات 7 روز گذشته را ارائه می دهد. برای دریافت اطلاعات ماهانه یا ۳۰ روز گذشته کافیست پارامتر monthly با مقدار true را به همراه این درخواست ارسال نمایید.
105 |
106 |
سود زیان کل به صورت روزانه در هفته گذشته
107 |
108 | ```shell
109 | curl -X POST 'https://apiv2.nobitex.ir/users/portfolio/last-week-daily-total-profit' \
110 | -H 'Authorization: Token yourTOKENhereHEX0000000000'
111 | ```
112 |
113 | ```plaintext
114 | http POST https://apiv2.nobitex.ir/users/portfolio/last-week-daily-total-profit \
115 | Authorization: Token yourTOKENhereHEX0000000000
116 | ```
117 |
118 | > در صورت فراخوانی درست، پاسخ به این صورت خواهد بود:
119 |
120 | ```json
121 | {
122 | "status": "ok",
123 | "data": [
124 | {
125 | "report_date": "2021-06-27",
126 | "total_profit": 0,
127 | "total_profit_percentage": 0
128 | },
129 | {
130 | "report_date": "2021-06-28",
131 | "total_profit": 0,
132 | "total_profit_percentage": 0
133 | },
134 | {
135 | "report_date": "2021-06-29",
136 | "total_profit": "4507274.2415300000",
137 | "total_profit_percentage": "197.3669039200"
138 | },
139 | {
140 | "report_date": "2021-06-30",
141 | "total_profit": "9020935.7092505000",
142 | "total_profit_percentage": "-307.6135237294"
143 | },
144 | {
145 | "report_date": "2021-07-01",
146 | "total_profit": "-5373087.9340195000",
147 | "total_profit_percentage": "1302.7642741973"
148 | },
149 | {
150 | "report_date": "2021-07-02",
151 | "total_profit": "313580813.4306171358",
152 | "total_profit_percentage": "-899.0991999052"
153 | },
154 | {
155 | "report_date": "2021-07-03",
156 | "total_profit": "313580813.4306171358",
157 | "total_profit_percentage": "-899.0991999052"
158 | }
159 | ]
160 | }
161 | ```
162 |
163 | > در صورتی که این ویژگی برای کاربر فعال نباشد با این جواب روبرو خواهند شد
164 |
165 | ```json
166 | {
167 | "status": "failed",
168 | "code": "PortfolioDisabled",
169 | "message": "Portfolio feature is not available for your user."
170 | }
171 | ```
172 |
173 | > در صورتی که اطلاعاتی از سود و زیان کاربر وجود نداشته باشد
174 |
175 | ```json
176 | {
177 | "status": "failed",
178 | "code": "LastWeekDailyProfitFail",
179 | "message": "اطلاعاتی جهت نمایش وجود ندارد"
180 | }
181 | ```
182 |
183 | برای دریافت اطلاعات سود و زیان روزانه هفته گذشته از این درخواست استفاده نمایید:
184 |
185 | * **درخواست:** `POST users/portfolio/last-week-daily-total-profit`
186 | * **محدودیت فراخوانی:** 10 درخواست در 3 دقیقه
187 |
188 |
189 |
190 |
سود و زیان کل ماه گذشته
191 |
192 | ```shell
193 | curl -X POST 'https://apiv2.nobitex.ir/users/portfolio/last-month-total-profit' \
194 | -H 'Authorization: Token yourTOKENhereHEX0000000000'
195 | ```
196 |
197 | ```plaintext
198 | http POST https://apiv2.nobitex.ir/users/portfolio/last-month-total-profit \
199 | Authorization: Token yourTOKENhereHEX0000000000
200 | ```
201 |
202 | > در صورت فراخوانی درست، پاسخ به این صورت خواهد بود:
203 |
204 | ```json
205 | {
206 | "status": "ok",
207 | "data": {
208 | "total_profit": "8987787000.0000000000",
209 | "total_profit_percentage": "83.60700983438201160181729556"
210 | }
211 | }
212 | ```
213 |
214 | > در صورتی که این ویژگی برای کاربر فعال نباشد با این جواب روبرو خواهند شد
215 |
216 | ```json
217 | {
218 | "status": "failed",
219 | "code": "PortfolioDisabled",
220 | "message": "Portfolio feature is not available for your user."
221 | }
222 | ```
223 |
224 | > در صورتی که اطلاعاتی از سود و زیان کاربر وجود نداشته باشد
225 |
226 | ```json
227 | {
228 | "status": "failed",
229 | "code": "LastWeekDailyProfitFail",
230 | "message": "اطلاعاتی جهت نمایش وجود ندارد"
231 | }
232 | ```
233 |
234 | برای دریافت اطلاعات سود و زیان روزانه هفته گذشته از این درخواست استفاده نمایید:
235 |
236 | * **درخواست:** `POST users/portfolio/last-month-total-profit`
237 | * **محدودیت فراخوانی:** 10 درخواست در 3 دقیقه
238 |
239 |
240 |
241 |
--------------------------------------------------------------------------------
/slate.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -o errexit #abort if any command fails
3 |
4 | me=$(basename "$0")
5 |
6 | help_message="\
7 | Usage: $me [] []
8 | Run commands related to the slate process.
9 |
10 | Commands:
11 |
12 | serve Run the middleman server process, useful for
13 | development.
14 | build Run the build process.
15 | deploy Will build and deploy files to branch. Use
16 | --no-build to only deploy.
17 |
18 | Global Options:
19 |
20 | -h, --help Show this help information.
21 | -v, --verbose Increase verbosity. Useful for debugging.
22 |
23 | Deploy options:
24 | -e, --allow-empty Allow deployment of an empty directory.
25 | -m, --message MESSAGE Specify the message used when committing on the
26 | deploy branch.
27 | -n, --no-hash Don't append the source commit's hash to the deploy
28 | commit's message.
29 | --no-build Do not build the source files.
30 | "
31 |
32 |
33 | run_serve() {
34 | exec bundle exec middleman serve --watcher-force-polling
35 | }
36 |
37 | run_build() {
38 | bundle exec middleman build --clean
39 | }
40 |
41 | parse_args() {
42 | # Set args from a local environment file.
43 | if [ -e ".env" ]; then
44 | source .env
45 | fi
46 |
47 | command=
48 |
49 | # Parse arg flags
50 | # If something is exposed as an environment variable, set/overwrite it
51 | # here. Otherwise, set/overwrite the internal variable instead.
52 | while : ; do
53 | if [[ $1 = "-h" || $1 = "--help" ]]; then
54 | echo "$help_message"
55 | exit 0
56 | elif [[ $1 = "-v" || $1 = "--verbose" ]]; then
57 | verbose=true
58 | shift
59 | elif [[ $1 = "-e" || $1 = "--allow-empty" ]]; then
60 | allow_empty=true
61 | shift
62 | elif [[ ( $1 = "-m" || $1 = "--message" ) && -n $2 ]]; then
63 | commit_message=$2
64 | shift 2
65 | elif [[ $1 = "-n" || $1 = "--no-hash" ]]; then
66 | GIT_DEPLOY_APPEND_HASH=false
67 | shift
68 | elif [[ $1 = "--no-build" ]]; then
69 | no_build=true
70 | shift
71 | elif [[ $1 = "serve" || $1 = "build" || $1 = "deploy" ]]; then
72 | if [ ! -z "${command}" ]; then
73 | >&2 echo "You can only specify one command."
74 | exit 1
75 | fi
76 | command=$1
77 | shift
78 | elif [ -z $1 ]; then
79 | break
80 | fi
81 | done
82 |
83 | if [ -z "${command}" ]; then
84 | >&2 echo "Command not specified."
85 | exit 1
86 | fi
87 |
88 | # Set internal option vars from the environment and arg flags. All internal
89 | # vars should be declared here, with sane defaults if applicable.
90 |
91 | # Source directory & target branch.
92 | deploy_directory=build
93 | deploy_branch=gh-pages
94 |
95 | #if no user identity is already set in the current git environment, use this:
96 | default_username=${GIT_DEPLOY_USERNAME:-deploy.sh}
97 | default_email=${GIT_DEPLOY_EMAIL:-}
98 |
99 | #repository to deploy to. must be readable and writable.
100 | repo=origin
101 |
102 | #append commit hash to the end of message by default
103 | append_hash=${GIT_DEPLOY_APPEND_HASH:-true}
104 | }
105 |
106 | main() {
107 | enable_expanded_output
108 |
109 | if ! git diff --exit-code --quiet --cached; then
110 | echo Aborting due to uncommitted changes in the index >&2
111 | return 1
112 | fi
113 |
114 | commit_title=`git log -n 1 --format="%s" HEAD`
115 | commit_hash=` git log -n 1 --format="%H" HEAD`
116 |
117 | #default commit message uses last title if a custom one is not supplied
118 | if [[ -z $commit_message ]]; then
119 | commit_message="publish: $commit_title"
120 | fi
121 |
122 | #append hash to commit message unless no hash flag was found
123 | if [ $append_hash = true ]; then
124 | commit_message="$commit_message"$'\n\n'"generated from commit $commit_hash"
125 | fi
126 |
127 | previous_branch=`git rev-parse --abbrev-ref HEAD`
128 |
129 | if [ ! -d "$deploy_directory" ]; then
130 | echo "Deploy directory '$deploy_directory' does not exist. Aborting." >&2
131 | return 1
132 | fi
133 |
134 | # must use short form of flag in ls for compatibility with macOS and BSD
135 | if [[ -z `ls -A "$deploy_directory" 2> /dev/null` && -z $allow_empty ]]; then
136 | echo "Deploy directory '$deploy_directory' is empty. Aborting. If you're sure you want to deploy an empty tree, use the --allow-empty / -e flag." >&2
137 | return 1
138 | fi
139 |
140 | if git ls-remote --exit-code $repo "refs/heads/$deploy_branch" ; then
141 | # deploy_branch exists in $repo; make sure we have the latest version
142 |
143 | disable_expanded_output
144 | git fetch --force $repo $deploy_branch:$deploy_branch
145 | enable_expanded_output
146 | fi
147 |
148 | # check if deploy_branch exists locally
149 | if git show-ref --verify --quiet "refs/heads/$deploy_branch"
150 | then incremental_deploy
151 | else initial_deploy
152 | fi
153 |
154 | restore_head
155 | }
156 |
157 | initial_deploy() {
158 | git --work-tree "$deploy_directory" checkout --orphan $deploy_branch
159 | git --work-tree "$deploy_directory" add --all
160 | commit+push
161 | }
162 |
163 | incremental_deploy() {
164 | #make deploy_branch the current branch
165 | git symbolic-ref HEAD refs/heads/$deploy_branch
166 | #put the previously committed contents of deploy_branch into the index
167 | git --work-tree "$deploy_directory" reset --mixed --quiet
168 | git --work-tree "$deploy_directory" add --all
169 |
170 | set +o errexit
171 | diff=$(git --work-tree "$deploy_directory" diff --exit-code --quiet HEAD --)$?
172 | set -o errexit
173 | case $diff in
174 | 0) echo No changes to files in $deploy_directory. Skipping commit.;;
175 | 1) commit+push;;
176 | *)
177 | echo git diff exited with code $diff. Aborting. Staying on branch $deploy_branch so you can debug. To switch back to main, use: git symbolic-ref HEAD refs/heads/main && git reset --mixed >&2
178 | return $diff
179 | ;;
180 | esac
181 | }
182 |
183 | commit+push() {
184 | set_user_id
185 | git --work-tree "$deploy_directory" commit -m "$commit_message"
186 |
187 | disable_expanded_output
188 | #--quiet is important here to avoid outputting the repo URL, which may contain a secret token
189 | git push --quiet $repo $deploy_branch
190 | enable_expanded_output
191 | }
192 |
193 | #echo expanded commands as they are executed (for debugging)
194 | enable_expanded_output() {
195 | if [ $verbose ]; then
196 | set -o xtrace
197 | set +o verbose
198 | fi
199 | }
200 |
201 | #this is used to avoid outputting the repo URL, which may contain a secret token
202 | disable_expanded_output() {
203 | if [ $verbose ]; then
204 | set +o xtrace
205 | set -o verbose
206 | fi
207 | }
208 |
209 | set_user_id() {
210 | if [[ -z `git config user.name` ]]; then
211 | git config user.name "$default_username"
212 | fi
213 | if [[ -z `git config user.email` ]]; then
214 | git config user.email "$default_email"
215 | fi
216 | }
217 |
218 | restore_head() {
219 | if [[ $previous_branch = "HEAD" ]]; then
220 | #we weren't on any branch before, so just set HEAD back to the commit it was on
221 | git update-ref --no-deref HEAD $commit_hash $deploy_branch
222 | else
223 | git symbolic-ref HEAD refs/heads/$previous_branch
224 | fi
225 |
226 | git reset --mixed
227 | }
228 |
229 | filter() {
230 | sed -e "s|$repo|\$repo|g"
231 | }
232 |
233 | sanitize() {
234 | "$@" 2> >(filter 1>&2) | filter
235 | }
236 |
237 | parse_args "$@"
238 |
239 | if [ "${command}" = "serve" ]; then
240 | run_serve
241 | elif [[ "${command}" = "build" ]]; then
242 | run_build
243 | elif [[ ${command} = "deploy" ]]; then
244 | if [[ ${no_build} != true ]]; then
245 | run_build
246 | fi
247 | main "$@"
248 | fi
249 |
--------------------------------------------------------------------------------
/source/includes/_other.md:
--------------------------------------------------------------------------------
1 |
سایر
2 |
3 |
تنظیمات سیستم
4 |
5 | ```shell
6 | curl 'https://apiv2.nobitex.ir/v2/options'
7 | ```
8 |
9 | ```plaintext
10 | http GET https://apiv2.nobitex.ir/v2/options
11 | ```
12 |
13 | > ساختار کلی پاسخ به صورت زیر خواهد بود. کلیدهای موجود در هر بخش در مستندات توضیح داده شدهاند.
14 |
15 | ```json
16 | {
17 | "status": "ok",
18 | "features": {
19 | "fcmEnabled": true,
20 | "chat": "livechat",
21 | "walletsToNet": false,
22 | "autoKYC": true,
23 | "enabledFeatures": [
24 | "PriceAlert",
25 | "StopLoss",
26 | "GiftCard",
27 | "OCO"
28 | ],
29 | "betaFeatures": []
30 | },
31 | "coins": [
32 | {
33 | "coin": "rls",
34 | "name": "Rial",
35 | "defaultNetwork": "FIAT_MONEY",
36 | "displayPrecision": "10",
37 | "networkList": {
38 | "FIATMONEY": {
39 | "addressRegex": "",
40 | "coin": "rls",
41 | "depositEnable": true,
42 | "isDefault": true,
43 | "minConfirm": 0,
44 | "name": "FIAT",
45 | "network": "FIAT_MONEY",
46 | "withdrawEnable": true,
47 | "withdrawFee": "4_000_0.00000000",
48 | "withdrawIntegerMultiple": "0.10000000",
49 | "withdrawMax": "500_000_000_0.00000000",
50 | "withdrawMin": "15_000_0.00000000"
51 | }
52 | },
53 | "stdName": "﷼"
54 | },
55 | ... Other Coins Options
56 | ],
57 | "nobitex": {
58 | "allCurrencies": [
59 | "rls",
60 | "btc",
61 | ... Other currencies
62 | ],
63 | "activeCurrencies": [
64 | "rls",
65 | "btc",
66 | "eth",
67 | "ltc",
68 | ... Other active currencies
69 | ],
70 | "xchangeCurrencies": [],
71 | "topCurrencies": [
72 | "btc",
73 | "eth",
74 | "usdt",
75 | "doge",
76 | "shib",
77 | "trx",
78 | "ada",
79 | "ltc",
80 | "xrp"
81 | ],
82 | "testingCurrencies": [
83 | "hbar"
84 | ],
85 | "withdrawLimits": {
86 | "normal": {
87 | "dailyCoin": "0",
88 | "dailyRial": "0",
89 | "dailySummation": "0",
90 | "monthlySummation": "0"
91 | },
92 | "level0": {
93 | "dailyCoin": "0",
94 | "dailyRial": "0",
95 | "dailySummation": "0",
96 | "monthlySummation": "0"
97 | },
98 | "44": {
99 | "dailyCoin": "1000000000",
100 | "dailyRial": "200000000",
101 | "dailySummation": "1000000000",
102 | "monthlySummation": "15000000000"
103 | },
104 | ... Other withdraw options
105 | },
106 | "minOrders": {
107 | "rls": "3000000",
108 | "usdt": "11",
109 | "2": "3000000",
110 | "13": "11"
111 | },
112 | "amountPrecisions": {
113 | "BTCIRT": "0.000001",
114 | "BTCUSDT": "0.000001",
115 | "ETHIRT": "0.00001",
116 | ... Other amount precisions
117 | },
118 | "pricePrecisions": {
119 | "BTCIRT": "10",
120 | "BTCUSDT": "0.01",
121 | "ETHIRT": "10",
122 | ... Other market precisions
123 | },
124 | "giftCard": {
125 | "physicalFee": "360000"
126 | }
127 | }
128 | }
129 | ```
130 |
131 | عملکرد سیستم نوبیتکس بر اساس پارامترهای مختلف تنظیم میشود که با استفاده از API «تنظیمات سیستم» میتوانید مقادیر این پارامترها را دریافت نمایید. مواردی مانند رمزارزهای فعال، حداقل معامله در هر بازار، پلههای کارمزد، سقف برداشت و بسیاری اطلاعات مفید دیگر از این طریق در دسترس شما قرار خواهد داشت. پاسخ در دو کلید `nobitex` شامل تنظیمات کلی سیستمی، و کلید `coins` شامل تنظیمات مخصوص هر رمزارز بازگردانده میشود. همچنین هر رمزارز دارای چندین «شبکه» است که برخی تنظیمات ممکن است فقط در سطح شبکه تعریف شوند یا در سطح رمزارز به صورت عمومی وجود داشته باشند ولی در بعضی شبکههای آن رمزارز متفاوت بوده و بازتعریف شوند.
132 |
133 | - **درخواست:** `GET /v2/options`
134 | - **نیاز به ارسال توکن:** ندارد
135 | - **پارامتر ورودی:** ندارد
136 |
137 |
140 |
141 |
142 | ### پارامترهای پاسخ - features
143 |
144 | کلید | نوع | توضیحات
145 | ---- |-------------| ----
146 | fcmEnabled | bool | وضعیت فعال بودن FCM
147 | autoKYC | bool | وضعیت فعال بودن احراز خودکار
148 | enabledFeatures | list of str | لیست Featureهای فعال
149 | betaFeatures | list of str | لیست featureهای بتا
150 |
151 |
152 | ### پارامترهای پاسخ - nobitex
153 |
154 | کلید | نوع | توضیحات
155 | ---- |-------------| ----
156 | allCurrencies | list of str | نماد تمام رمزارزهای موجود در بازارها
157 | activeCurrencies | list of str | نماد رمزارزهای اصلی و سطح یک
158 | xchangeCurrencies | list of str | نماد رمزارزهای صرافی
159 | topCurrencies | list of str | رمزارزهای برتر بازار
160 | testingCurrencies | list of str | رمزارزهای در حال توسعه و آزمایش
161 | withdrawLimits | dict | محدودیت های روزانه و ماهانه در سطوح مختلف
162 | minOrders | dict | حداقل مبلغ سفارش ریالی و تتری
163 | amountPrecisions | dict | دقت اعشار مقدار در بازارهای مختلف
164 | pricePrecisions | dict | دقت اعشار قیمت در بازارهای مختلف
165 | giftCard | dict | هزینه چاپ گیفت کارتهای فیزیکی
166 |
167 |
168 | ### پارامترهای پاسخ - Coins
169 |
170 | فیلد | نوع | توضیحات | نمونه
171 | ---- |--------------------------------------------------------------------------------------------------------| ---- | ----
172 | coin | str | نماد یکتای رمزارز، معمولاً با حروف کوچک | `rls` یا `btc` یا `eth` یا …
173 | name | str | نام انگلیسی رمزارز | `Bitcoin` یا `TRON` یا `Dogecoin` یا …
174 | default_network | str | شبکه پیشفرض رمزارز، یکی از کلیدهای NetworkOptions آن رمزارز | `FIAT_MONEY` یا `BTC` یا `BSC` یا …
175 | network_list | dict | یک دیکشنری از شبکههای مختلف این رمزارز، با کلیدهای نام انگلیسی هر شبکه و مقادیر از نوع NetworkOptions |
176 | displayPrecision | str | دقت اعشار پیشفرض نمایش مقادیر این رمزارز | `0.0001` یا `0.1` یا `1`
177 | stdName | str | عنوان رمز ارز | `ریال`
178 |
179 |
180 | ### پارامترهای پاسخ - Network
181 |
182 | فیلد | نوع | توضیحات | نمونه
183 | ---- | ---- | ---- | ----
184 | network | str | نماد یکتای شبکه، معمولاً با حروف بزرگ | `FIAT_MONEY` یا `BTC` یا `BSC` یا …
185 | name | str | نام انگلیسی خوانای شبکه | `BTC` یا `ERC20` یا …
186 | isDefault | boolean | آیا این شبکه پیشفرض برای این رمزارز در نوبیتکس است؟ | `false`
187 | beta | boolean | آیا این شبکه هنوز در حالت آزمایشی است؟ | `false`
188 | addressRegex | str | الگوی آدرسها در این شبکه | `^0x[0-9A-Fa-f]{40}$`
189 | memoRequired | boolean | آیا تراکنش روی این شبکه نیازمند ممو است؟ | `false`
190 | memoRegex | str | در صورت وجود، ممو باید چه الگویی داشته باشد؟ | `^[0-9A-Za-z]{1,28}$`
191 | depositEnable | boolean | آیا واریز رمزارز روی این شبکه فعال است؟ | `true`
192 | minConfirm | int | حداقل تعداد کانفیرم شبکه برای تایید اولیه واریز | `1`
193 | depositInfo | dict | فهرست پارامترهای واریز | `{"standard": {"depositMin": "0.01"}}`
194 | depositInfo.standard.depositMin | monetary | حداقل مقدار واریز این رمزارز روی شبکه | `0`
195 | depositInfo.standard.depositMax | monetary | حداکثر مقدار واریز این رمزارز روی شبکه | `1000`
196 | withdrawEnable | boolean | آیا برداشت رمزارز روی این شبکه فعال است؟ | `false`
197 | withdrawIntegerMultiple | monetary | حداقل مقدار تغییر مقدار قابل برداشت | `0.000001`
198 | withdrawFee | monetary | کارمزد برداشت | `0.1`
199 | withdrawMin | monetary | حداقل مقدار قابل برداشت | `0.1`
200 | withdrawMax | monetary | حداکثر مقدار قابل برداشت | `1000`
201 |
--------------------------------------------------------------------------------
/source/includes/_general_notes.md:
--------------------------------------------------------------------------------
1 |
ملاحظات عمومی
2 |
3 | ## راهنمای اشکالیابی
4 | * به نوع درخواست دقت کنید، احتمال دارد درخواست از نوع `HTTP POST` باشد و شما از `GET` استفاده کرده باشید.
5 | * آدرس API را مجددا بررسی نمایید. همچنین به وجود یا عدم وجود `/` در انتهای آدرس دقت کنید.
6 |
7 | ## پاسخهای موفق
8 | > نمونه پاسخ موفق:
9 |
10 | ``` json
11 | {
12 | "status": "ok",
13 | "otherFields": "..."
14 | }
15 | ```
16 |
17 | در تمامی API ها در صورتی که عملیات مد نظر به درستی انجام شده باشد، پاسخ به صورت یک شی در قالب JSON
18 | بازگردانده میشود و با وضعیت `HTTP 200` است. این پاسخ در حالت موفق یک کلید `status` با مقدار `ok` دارد.
19 | بنا به API مورد استفاده ممکن است یک یا چند کلید دیگر نیز در این پاسخ بازگردانده شود.
20 |
21 | ## پاسخهای ناموفق
22 | > نمونه پاسخ ناموفق:
23 |
24 | ``` json
25 | {
26 | "status": "failed",
27 | "code": "ErrorCode",
28 | "message": "Human-readable error message"
29 | }
30 | ```
31 |
32 | در تمامی APIها در صورتی که به هر دلیل امکان پردازش و انجام آن درخواست وجود نداشته باشد، یک پاسخ ناموفق
33 | بازگردانده میشود. پاسخهای ناموفق به دو صورت هستند، یا با کد خطای HTTP مشخص میشوند که مطابق با معانی
34 | وضعیت در پروتکل HTTP قابل تفسیر هستند.
35 |
36 | در صورتی که پارامترهای ورودی قابل تفسیر باشند، ولی عملیات مد نظر قابل انجام نباشد، پاسخ با وضعیت `HTTP 200` بازگردانده
37 | میشود، و توضیحات تکمیلی به صورت یک شی در قالب JSON خواهد بود که مقدار کلید `status` آن برابر `failed` است.
38 | کلید `code` در این شرایط، خطای دقیق رخ داده شده را مشخص میکند که در بخش «حالتهای خطا» در توضیحات هر API
39 | فهرستی از کدهای خطای ممکن و توضیحات آن ارائه شده است. معمولاً در یک کلید `message` توضیح بیشتری در مورد آن
40 | خطا نیز ارائه میشود که جهت رفع عیب یا نمایش مستقیم به کاربر نهایی میتواند مفید باشد.
41 |
42 |
46 |
47 | ### برخی وضعیتهای پرکاربرد
48 | کد HTTP | عنوان | توضیحات |
49 | ---- |-----------------------|---------------------------------------------------------------------------------------------------| ----
50 | 200 | OK | درخواست دریافت و پاسخ داده شده، وضعیت اصلی درخواست در فیلد status پاسخ مشخص میشود | 🐱
51 | 400 | Bad Request | پارامترهای درخواست نادرست یا ناکافی است به طوری که امکان بررسی بیشتر و پاسخ بهتر به آن وجود ندارد | 🐱
52 | 401 | Unauthorized | کاربر [احراز هویت](#intro-auth) نشده است | 🐱
53 | 403 | Forbidden | انجام این عملیات مجاز نمیباشد | 🐱
54 | 404 | Not Found | آدرس یا شی مد نظر وجود ندارد | 🐱
55 | 422 | Unprocessable Content | پارامترهای درخواست درست است، اما از نظر معنایی درخواست قابل انجام نیست | 🐱
56 | 429 | Too Many Requests | تعداد درخواست بیشتر از اندازه مجاز است | 🐱
57 | 500 | Internal Server Error | مشکلی به صورت موقت در سرور نوبیتکس رخ داده است | 🐱
58 |
59 |
صفحهبندی
60 | پارامترهای زیر در API های دریافت لیست دارای صفحهبندی قابل استفاده است:
61 |
62 | | پارامتر | نوع | پیشفرض | توضیحات | نمونه |
63 | |----------|-----|---------|-------------|-------|
64 | | page | int | اختیاری | شماره صفحه | 2 |
65 | | pageSize | int | اختیاری | اندازه صفحه | 10 |
66 |
67 |
70 |
71 |
74 |
75 |
76 |
فیلتر زمانی
77 | پارامترهای زیر در API های دریافت لیست قابل فیلتر زمانی قابل استفاده است:
78 |
79 | | پارامتر | نوع | پیشفرض | توضیحات | نمونه |
80 | |---------|------|---------|----------|--------------|
81 | | from | date | اختیاری | از تاریخ | `2022-05-12` |
82 | | to | date | اختیاری | تا تاریخ | `2022-07-22` |
83 |
84 |
85 | ## مقادیر پولی (monetary)
86 | در موارد متعددی پارامترهای ورودی درخواستها از نوع مقدار پولی یا monetary مشخص شده است. برای داشتن بالاترین دقت، پیشنهاد میشود که این مقادیر را به صورت رشتهای ارسال نمایید، چرا که استفاده از انواع دادهای مانند `float` در کاربردهای دقیق مالی توصیه نمیشود.
87 |
88 | ## اعتبارسنجی دو عاملی
89 | در صورتی که اعتبارسنجی دو عاملی (2 Factor Authentication) را برای حساب خود فعال کرده باشید، باید در هنگام استفاده از برخی APIها،
90 | به خصوص در هنگام دریافت توکن از API لاگین، علاوه بر سایر پارامترها، رمز یکبار مصرف خود را نیز در هدرهای درخواست به این صورت ارسال نمایید:
91 | `X-TOTP: 123456`.
92 |
93 |
محدودیت فراخوانی
94 | > نمونه پاسخ ناموفق:
95 |
96 | ``` json
97 | {
98 | "status": "failed",
99 | "code": "TooManyRequests",
100 | "message": "تعداد درخواست شما بیش از حد معمول تشخیص داده شده. لطفا 12 ثانیه صبر نمایید.",
101 | "backOff": 12,
102 | "limit": 60
103 | }
104 | ```
105 |
106 | برخی از APIهای نوبیتکس دارای محدودیت تعداد فراخوانی در هر بازهی زمانی هستند. با این حال اگر شما به صورت معمولی و مشابه
107 | استفادهی متداول کاربران از API استفاده کنید، با این محدودیتها مواجه نخواهید شد. محدودیتها به ازای هر API مستقلا محاسبه
108 | و اعمال میشوند. محدودیتها معمولا بر اساس آدرس IP درخواست دهنده و در برخی موارد هم بر اساس کاربر (توکن) درخواست دهنده میباشند.
109 |
110 | در صورتی که تعداد درخواستها از این محدودیت فراتر رود، خطای `TooManyRequests` با کد 429 در پاسخ بازگردانده میشود که
111 | همراه با توضیحات مشخص در خصوص آن محدودیت است.
112 |
113 | برای ارسال مجدد درخواست به همان آدرس، لازم است به اندازه مقدار مشخصشده در پارامتر `backOff` (به واحد ثانیه) صبر کنید.
114 | پارامتر `limit` سقف مجاز تعداد درخواست را در بازه مشخصشده نشان میدهد.
115 |
116 |
120 |
121 | محدودیتهای استفاده از APIها بر اساس ظرفیت پردازشی نوبیتکس یا به منظور حفظ امنیت برای هر کاربر تعیین میشود
122 | تا کیفیت خدمات برای همه کاربران بهطور یکنواخت حفظ گردد. در زمانهای ازدحام شدید بازار، بهمنظور ایجاد فرصت برابر برای
123 | همه کاربران، ممکن است محدودیت فراخوانی یک API به ازای یک کاربر کاهش یابد.
124 |
125 | اگر به صورت مداوم با محدودیتی در استفاده از یک API مواجه میشوید و بر این باور هستید که افزایش تعداد فراخوانی مجاز
126 | آن API مفید خواهد بود، لطفا از طریق ایجاد یک [مسئله در گیتهاب](https://github.com/nobitex/docs-api/issues/new)
127 | درخواست خود را با ما در میان بگذارید.
128 |
129 |
محدودیت مشترک APIهای سفارشگذاری
130 | توجه داشته باشید که تمامی APIهای مربوط به ثبت سفارش دارای محدودیت مشترک روی تعداد سفارشهایی که ثبت میشوند هستند. برای مثال، اگر همزمان هم در بازار اسپات و هم در بازار تعهدی سفارش ثبت میکنید، محدودیت فراخوانی شامل مجموع سفارشهای ثبت شده در این دو بازار میشود.
131 |
132 | مقدار محدودیت مشترک: ۳۰۰ درخواست در ۱۰ دقیقه
133 |
134 |
محدودیت احراز ناموفق
135 | به منظور حفاظت از امنیت حسابهای کاربران، در صورتی که بیش از ۱۰۰ درخواست با توکن اشتباه (یا منقضی) از یک آدرس IP
136 | در مدت زمان کمتر از ۳۰ دقیقه ارسال شود، آن IP تا پایان این بازه زمانی مسدود خواهد شد. برای پیشگیری از بروز این مسئله،
137 | توصیه میشود فرایند تولید و تجدید توکن خود را مطابق با توضیحات [احراز هویت](/#auth) مدیریت نمایید.
138 |
139 |
140 | ## حالت متداول و Pro
141 | در برخی از درخواستها جهت حفاظت بهتر از کاربران، برخی محدودیتها اعمال میشود. در چنین مواردی در بخش ملاحظات این محدودیتها توضیح داده شده و در انتهای آن عبارت «غیرفعال در حالت Pro» ذکر شده است. با ارائه پارامتر `pro` به مقدار `yes` به عنوان ورودی، این محدودیت برای آن درخواست غیرفعال میشود. با این حال دقت کنید که محدودیتهای حالت متداول برای جلوگیری از حالتهای خاص و اشتباهات رایج تعبیه شده است و تنها در صورت نیاز و آگاهی از تبعات احتمالی آن، اقدام به فعالسازی حالت Pro نمایید.
142 |
--------------------------------------------------------------------------------
/source/includes/internal/_2fa.md:
--------------------------------------------------------------------------------
1 | # شناسایی دوعاملی
2 | شناسایی دوعاملی جهت افزایش امنیت حساب و دارایی کاربر در زمان ورود، علاوه بر گذرواژه، یک کد شش رقمی تقاضا خواهد نمود که از [احرازگر گوگل](https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2 "Google Authenticator") دریافت میشود.
3 |
4 | ### نکات و ملاحظات
5 |
6 | 1. فعالسازی شناسایی دو عاملی برای کاربران سطح دو نوبیتکس اجباری است.
7 | 2. احراز هویت در API های این مجموعه الزامی است.
8 |
9 | ##فعالسازی شناسایی دوعاملی
10 |
11 | >نمونه درخواست:
12 |
13 | ```shell
14 | curl 'https://apiv2.nobitex.ir/users/tfa/request' \
15 | -H 'Authorization: Token yourTOKENhereHEX0000000000'
16 | ```
17 |
18 | ```javascript
19 | api.get('/users/tfa/request', {
20 | headers: {Authorization: "Token yourTOKENhereHEX0000000000"},
21 | }).then((response) => {
22 | console.log(response);
23 | });
24 | ```
25 |
26 | ```java
27 | public interface APIService {
28 | @Headers({"Authorization: Token yourTOKENhereHEX0000000000"})
29 | @GET("/users/tfa/request")
30 | Call request2FA();
31 | }
32 |
33 | APIService api = retrofit.create(APIService.class);
34 |
35 | Call call = api.request2FA();
36 | ```
37 |
38 | ```plaintext
39 | GET /users/tfa/request HTTP/1.1
40 | Host: apiv2.nobitex.ir
41 | Authorization: Token yourTOKENhereHEX0000000000
42 | ```
43 |
44 | > در صورت فراخوانی درست، پاسخ به این صورت خواهد بود:
45 |
46 | ```json
47 | {
48 | "status": "ok",
49 | "device": {
50 | "id": 1,
51 | "name": "App",
52 | "confirmed": false,
53 | "configUrl": "otpauth://totp/Nobitex%3Atest%40nobitex.net?secret=FXZJ28P2V3U0F4W3U7707EYIKNBJAKR6&algorithm=SHA1&digits=6&period=30&issuer=Nobitex"
54 | }
55 | }
56 | ```
57 |
58 | برای فعالسازی شناسایی دوعاملی از این نوع درخواست استفاده نمایید:
59 |
60 | پس از ثبت درخواست، پیامکی حاوی کد شش رقمی جهت تایید دستگاه به شماره همراه کاربر ارسال میشود که ظرف مدت 30 دقیقه منقضی خواهد شد.
61 |
62 | - **درخواست:** `GET /users/tfa/request`
63 | - **محدودیت فراخوانی:** 3 درخواست در 10 دقیقه / 10 درخواست در ساعت
64 |
65 |
66 |
69 |
70 | ### پارامترهای پاسخ
71 |
72 | پارامتر | نوع | توضیحات | نمونه
73 | ------- | ---- | --------- | ---------
74 | status | string | وضعیت پاسخ | ok
75 | device | TOTPDevice | اطلاعات تنظیم دستگاه | {"id": 1, ...}
76 |
77 | ### شی TOTPDevice
78 |
79 | پارامتر | نوع | توضیحات | نمونه
80 | ------- | ---- | --------- | ---------
81 | id | integer | شناسه دستگاه | 1
82 | name | string | نام دستگاه | "App"
83 | confirmed | boolean | تایید شده با پیامک | false
84 | configUrl | string | آدرس تنظیم شناسایی دوعاملی در احرازگر گوگل | "otpauth://totp/Nobitex%3Atest%40nobitex.net?secret=FXZJ28P2V3U0F4W3U7707EYIKNBJAKR6&algorithm=SHA1&digits=6&period=30&issuer=Nobitex"
85 |
86 |
87 |
88 | ### حالتهای خطا
89 |
90 | کد خطا | توضیحات
91 | ---- | ----
92 | UnverifiedMobile | کاربر شماره تماس یا ایمیل تایید شده ندارد.
93 | IPRestricted | فراخوانی فقط از داخل ایران امکانپذیر است.
94 |
95 |
96 | ### نکات و ملاحظات
97 | توجه فرمایید که فراخوانی این درخواست فقط از داخل ایران امکانپذیر است
98 |
99 | کاربر با خروجی این API میتواند برنامه احرازگر گوگل را فعال نماید. این برنامه هر 30 ثانیه یک بار کد جدیدی تولید میکند که تا دو دقیقه قابل استفاده است.
100 | در صورت تنظیم درست احرازگر گوگل میتوانید برای تایید دستگاه (device) و تکمیل درخواست خود اقدام کنید.
101 |
102 |
103 | ##تایید شناسایی دوعاملی
104 |
105 | >نمونه درخواست:
106 |
107 | ```shell
108 | curl -X POST 'https://apiv2.nobitex.ir/users/tfa/confirm' \
109 | -H 'Authorization: Token yourTOKENhereHEX0000000000' \
110 | -H 'Content-Type: application/json' \
111 | --data '{"device": 1, "otp": 123456, "sms_otp": 987654}'
112 | ```
113 |
114 | ```javascript
115 | api.post('/users/tfa/confirm', {device: 1, otp: 123456, sms_otp: 987654}, {
116 | headers: {Authorization: "Token yourTOKENhereHEX0000000000"},
117 | }).then((response) => {
118 | console.log(response);
119 | });
120 | ```
121 |
122 | ```java
123 | public interface APIService {
124 | @Headers({"Authorization: Token yourTOKENhereHEX0000000000"})
125 | @FormUrlEncoded
126 | @POST("/users/tfa/confirm")
127 | Call confirm2FA(@Field("device") int deviceId, @Field("otp") int otp, @Field("sms_otp") int smsOtp);
128 | }
129 |
130 | APIService api = retrofit.create(APIService.class);
131 |
132 | Call call = api.confirm2FA(1, 123456, 987654);
133 | ```
134 |
135 |
136 |
137 | ```plaintext
138 | POST /users/tfa/confirm HTTP/1.1
139 | Host: apiv2.nobitex.ir
140 | Authorization: Token yourTOKENhereHEX0000000000
141 | {"device": 1, "otp": 123456, "sms_otp": 987654}
142 | ```
143 |
144 | > در صورت فراخوانی درست، پاسخ به این صورت خواهد بود:
145 |
146 | ```json
147 | {
148 | "status": "ok"
149 | }
150 | ```
151 |
152 | پس از تنظیم شناسایی دوعاملی در احرازگر گوگل و دریافت پیامک کد تایید، برای تکمیل درخواست خود از این نوع درخواست استفاده نمایید:
153 |
154 | - **درخواست:** `POST /users/tfa/confirm`
155 | - **محدودیت فراخوانی:** 10 درخواست در 10 دقیقه / 20 درخواست در ساعت
156 |
157 | ### پارامترهای ورودی
158 |
159 | پارامتر | نوع | پیشفرض | توضیحات | نمونه
160 | ------- | ---- | ---- | --------- | ---------
161 | device | integer | الزامی | شناسه دستگاهی که فعالسازی شناسایی دوعاملی را درخواست کرده | 1
162 | otp | integer | الزامی | رمز یکبارمصرف شش رقمی دریافت شده از احرازگر گوگل | 123456
163 | sms_otp | integer | الزامی | کد تایید شش رقمی پیامک شده به شماره همراه کاربر | 987654
164 |
165 | ### پارامترهای پاسخ
166 |
167 | پارامتر | نوع | توضیحات | نمونه
168 | ------- | ---- | --------- | ---------
169 | status | string | وضعیت پاسخ | ok
170 |
171 |
172 | ### حالتهای خطا
173 |
174 | کد خطا | توضیحات
175 | ---- | ----
176 | InvalidOTP | رمز یکبارمصرف نامعتبر است یا زمان لازم برای انتظار پس از ورود اشتباه رمز سپری نشده است.
177 | MissingSmsOTP | کد تایید پیامک شده ارسال نشده است.
178 | InvalidSmsOTP | کد تایید پیامک شده منقضی یا نامعتبر است.
179 |
180 |
181 | ### نکات و ملاحظات
182 | 1. در صورت اشتباه وارد کردن رمز یکبارمصرف احرازگر گوگل، برای درخواست بعدی با توجه به دفعات اشتباه بایستی به ترتیب 1، 2، 4، 8 و ... ثانیه پیش از درخواست مجدد صبر کنید.
183 | 2. حداکثر یک دستگاه دارای شناسایی دوعاملی فعال در هر لحظه برای کاربر مجاز است و در صورت فعالسازی دستگاه دیگر، دستگاه قبلی غیر فعال خواهد شد.
184 |
185 |
186 | ##غیرفعالسازی شناسایی دوعاملی
187 |
188 | >نمونه درخواست:
189 |
190 | ```shell
191 | curl -X POST 'https://apiv2.nobitex.ir/users/tfa/disable' \
192 | -H 'Authorization: Token yourTOKENhereHEX0000000000' \
193 | -H 'Content-Type: application/json' \
194 | --data '{"otp": 123456}'
195 | ```
196 |
197 | ```javascript
198 | api.post('/users/tfa/disable', {otp: 123456}, {
199 | headers: {Authorization: "Token yourTOKENhereHEX0000000000"},
200 | }).then((response) => {
201 | console.log(response);
202 | });
203 | ```
204 |
205 | ```java
206 | public interface APIService {
207 | @Headers({"Authorization: Token yourTOKENhereHEX0000000000"})
208 | @FormUrlEncoded
209 | @POST("/users/tfa/disable")
210 | Call disable2FA(@Field("otp") int otp);
211 | }
212 |
213 | APIService api = retrofit.create(APIService.class);
214 |
215 | Call call = api.disable2FA(123456);
216 | ```
217 |
218 |
219 |
220 | ```plaintext
221 | POST /users/tfa/disable HTTP/1.1
222 | Host: apiv2.nobitex.ir
223 | Authorization: Token yourTOKENhereHEX0000000000
224 | {"otp": 123456}
225 | ```
226 |
227 | > در صورت فراخوانی درست، پاسخ به این صورت خواهد بود:
228 |
229 | ```json
230 | {
231 | "status": "ok"
232 | }
233 | ```
234 |
235 | برای غیرفعالسازی شناسایی دوعاملی از این نوع درخواست استفاده نمایید:
236 |
237 | * **درخواست:** `POST /users/tfa/disable`
238 |
239 | * پارامترهای ورودی:
240 |
241 | پارامتر | نوع | پیشفرض | توضیحات | نمونه
242 | ------- | ---- | ---- | --------- | ---------
243 | otp | integer | الزامی | رمز یکبارمصرف شش رقمی دریافت شده از احرازگر گوگل | 123456
244 |
245 | ### پارامترهای پاسخ
246 |
247 | پارامتر | نوع | توضیحات | نمونه
248 | ------- | ---- | --------- | ---------
249 | status | string | وضعیت پاسخ | ok
250 |
251 |
252 | ### حالتهای خطا
253 |
254 | کد خطا | توضیحات
255 | ---- | ----
256 | InvalidOTP | رمز یکبارمصرف نامعتبر است یا زمان لازم برای انتظار پس از ورود اشتباه رمز سپری نشده است.
257 | IPRestricted | فراخوانی فقط از داخل ایران امکانپذیر است.
258 |
259 | ### نکات و ملاحظات
260 | 1. در صورت اشتباه وارد کردن رمز یکبارمصرف احرازگر گوگل، برای درخواست بعدی با توجه به دفعات اشتباه بایستی به ترتیب 1، 2، 4، 8 و ... ثانیه پیش از درخواست مجدد صبر کنید.
261 | 2. توجه فرمایید که فراخوانی این درخواست فقط از داخل ایران امکانپذیر است.
262 |
--------------------------------------------------------------------------------
/source/includes/_address_book.md:
--------------------------------------------------------------------------------
1 | # دفتر آدرس و حالت برداشت امن
2 |
3 | دفتر آدرس (address book) و حالت برداشت امن (whitelist mode)
4 | به منظور ارتقاء امنیت و سرعت برداشت رمزارز کاربران پیاده سازی می شود و امکان تعریف آدرسهای برداشت از پیش تعیین
5 | و تأیید شده را در دفتر آدرس برای کاربر فراهم می آورد. برداشت به آدرسهای امن دفتر آدرس به رمز دوعاملی یا کد تایید
6 | یکبار مصرف نیازی ندارد.
7 |
8 | ## مشاهده لیست آدرسهای دفتر آدرس
9 |
10 | ```shell
11 | curl 'https://apiv2.nobitex.ir/address_book' \
12 | -H "Authorization: Token yourTOKENhereHEX0000000000"
13 | ```
14 |
15 | ```plaintext
16 | https GET https://apiv2.nobitex.ir/address_book
17 | ```
18 |
19 | > در صورت فراخوانی درست، پاسخ به این صورت خواهد بود:
20 |
21 | ```json
22 | {
23 | "status": "ok",
24 | "data": [
25 | {
26 | "id": 3,
27 | "title": "TetherBinance",
28 | "network": "BSC",
29 | "address": "000000xxxxxxx111111111zzzzzzz",
30 | "createdAt": "2023-08-09T10:12:37+00:00"
31 | },
32 | {
33 | "id": 4,
34 | "title": "BinanceCoinOKX",
35 | "network": "BNB",
36 | "address": "000000xxxxxxx222222222zzzzzzz",
37 | "tag": "test17280992",
38 | "createdAt": "2023-08-09T10:26:12+00:00"
39 | }
40 | ]
41 | }
42 | ```
43 |
44 | برای دریافت دفتر آدرس از این درخواست استفاده نمایید.
45 |
46 | - **درخواست:**: `GET /address_book`
47 | - **محدودیت فراخوانی:** 20 درخواست در هر دقیقه
48 |
49 | ### پارامترهای ورودی
50 |
51 | | پارامتر | نوع | پیشفرض | توضیحات | نمونه |
52 | |---------|--------|-------------|------------|-------|
53 | | network | string | همه شبکهها | فیلتر شبکه | `BSC` |
54 |
55 | ## اضافه کردن آدرس جدید به دفتر آدرس
56 |
57 | ```shell
58 | curl -X POST 'https://apiv2.nobitex.ir/address_book' \
59 | -H "Authorization: Token yourTOKENhereHEX0000000000" \
60 | -H "content-type: application/json" \
61 | --data '{"title": "test", "network": "BSC", "address": "000000xxxxxxx111111111zzzzzzz",
62 | "otpCode": "123456", "tfaCode": "654321"}'
63 |
64 | ```
65 |
66 | ```plaintext
67 | http POST https://apiv2.nobitex.ir/address_book
68 | ```
69 |
70 | > در صورت فراخوانی درست، پاسخ به این صورت خواهد بود:
71 |
72 | ```json
73 | {
74 | "status": "ok",
75 | "data": {
76 | "id": 5,
77 | "title": "test",
78 | "network": "BSC",
79 | "address": "000000xxxxxxx111111111zzzzzzz",
80 | "createdAt": "2023-08-09T10:22:37+00:00"
81 | }
82 | }
83 | ```
84 |
85 |
86 | > برای دریافت رمزیکبارمصرف otpCode از درخواست زیر استفاده نمایید:
87 |
88 | ```shell
89 | curl -X POST 'https://apiv2.nobitex.ir/v2/otp/request' \
90 | -H 'Authorization: Token yourTOKENhereHEX0000000000' \
91 | --data '{"type": "email", "usage": "address_book"}'
92 | ```
93 |
94 |
95 | - **درخواست:**: `POST /address_book`
96 | - **محدودیت فراخوانی:** 6 درخواست در هر دقیقه
97 |
98 | ### پارامترهای ورودی
99 |
100 | | پارامتر | نوع | پیشفرض | توضیحات | نمونه |
101 | |---------|--------|------------------------------|------------------------|---------------------------------|
102 | | title | string | الزامی | عنوان آدرس | `test` |
103 | | network | string | الزامی | شبکه | `BSC` |
104 | | address | string | الزامی | آدرس | `000000xxxxxxx111111111zzzzzzz` |
105 | | tag | string | الزامی در شبکههای تگاجباری | تگ | `test17280992` |
106 | | otpCode | string | الزامی | کد تأیید ایمیل و پیامک | `123456` |
107 | | tfaCode | string | الزامی | کد تأیید دوعاملی | `654321` |
108 |
109 | ### نکات و ملاحظات
110 |
111 | 1. مقدار آدرس در شبکههای بدون تگ نمیتواند تکراری باشد.
112 | 2. در شبکههای تگ اجباری است.
113 | 3. مقدار تگهای یک آدرس در شبکههای تگاجباری نمیتواند تکراری باشد. (زوج آدرس و تگ باید یکتا باشد.)
114 | 4. برای دریافت کد تایید از طریق ایمیل (otpCode) از درخواست روبرو استفاده نمایید.
115 |
116 | ### حالتهای خطا
117 |
118 | > در صورت عدم پذیرش درخواست، پاسخ به این صورت خواهد بود:
119 |
120 | ```json
121 | {
122 | "status": "failed",
123 | "code": "ErrorCode",
124 | "message": "Human readable error message"
125 | }
126 | ```
127 |
128 | | کد خطا | توضیحات |
129 | |-------------------|----------------------------------------------------------------|
130 | | ParseError | نوع یا شرط الزامی بودن یکی از پارامترهای ورودی رعایت نشده است. |
131 | | InvalidOTP | مقدار tfa وارد شده نادرست است. |
132 | | Invalid2FA | مقدار otp وارد شده نادرست است. |
133 | | Inactive2FA | tfa فعال نیست |
134 | | InvalidAddress | آدرس مربوط به شبکه مشخص شده نمیباشد. |
135 | | DuplicatedAddress | آدرس قبلا ثبت شده و تکراری می باشد. |
136 | | InvalidTag | فرمت تگ مطابق شبکه مشخص شده نمیباشد. |
137 |
138 |
139 | ## حذف یک دفتر آدرس
140 |
141 | ```shell
142 | curl 'https://apiv2.nobitex.ir/address_book//delete
143 | -H "Authorization: Token yourTOKENhereHEX000000ook'"
144 |
145 | ```
146 |
147 | ```plaintext
148 | https DELETE /address_book//delete
149 | ```
150 |
151 | > در صورت فراخوانی درست، پاسخ به این صورت خواهد بود:
152 |
153 | ```json
154 | {
155 | "status": "ok"
156 | }
157 | ```
158 |
159 | - **درخواست:**: `DELETE /address_book//delete`
160 | - **محدودیت فراخوانی:** 6 درخواست در هر دقیقه
161 |
162 | ### حالتهای خطا
163 |
164 | > در صورت عدم پذیرش درخواست، پاسخ به این صورت خواهد بود:
165 |
166 | ```json
167 | {
168 | "status": "failed",
169 | "code": "ErrorCode",
170 | "message": "Human readable error message"
171 | }
172 | ```
173 |
174 | | کد خطا | توضیحات |
175 | |----------|--------------------------------|
176 | | NotFound | آدرسی با این شناسه وجود ندارد. |
177 |
178 | ## فعال کردن برداشت امن
179 | در صورتی که حالت برداشت امن فعال باشد مقصدهای برداشت رمزارزی به آدرسهای موجود در دفتر آدرس محدود خواهد شد
180 | و به استثنای برداشت در شبکه لایتنینگ، امکان برداشت رمزارزی به آدرسهای غیر وجود نخواهد داشت.
181 |
182 | ```shell
183 | curl -X POST 'https://apiv2.nobitex.ir/address_book/whitelist/activate' \
184 | -H "Authorization: Token yourTOKENhereHEX0000000000"
185 | ```
186 |
187 | ```plaintext
188 | https POST https://apiv2.nobitex.ir/address_book/whitelist/activate
189 | ```
190 |
191 | > در صورت فراخوانی درست، پاسخ به این صورت خواهد بود:
192 |
193 | ```json
194 | {
195 | "status": "ok"
196 | }
197 | ```
198 |
199 | - **درخواست:**: `POST /address_book/whitelist/activate`
200 | - **محدودیت فراخوانی:** 6 درخواست در هر دقیقه
201 |
202 | ## غیرفعال کردن برداشت امن
203 | با غیر فعال کردن برداشت امن، به جهت حفظ امنیت حساب امکان برداشت به مدت ۲۴ ساعت روی حساب کاربر محدود خواهد شد.
204 |
205 | ```shell
206 | curl 'https://apiv2.nobitex.ir/address_book/whitelist/deactivate' \
207 | -H "Authorization: Token yourTOKENhereHEX0000000000"
208 | -H "content-type: application/json" \
209 | --data '{"otpCode": "1234", "tfaCode": "12345"}'
210 | ```
211 |
212 | ```plaintext
213 | https POST https://apiv2.nobitex.ir/address_book/whitelist/deactivate
214 | ```
215 |
216 | > در صورت فراخوانی درست، پاسخ به این صورت خواهد بود:
217 |
218 | ```json
219 | {
220 | "status": "ok"
221 | }
222 | ```
223 |
224 | - **درخواست:**: `POST /address_book/whitelist/deactivate`
225 | - **محدودیت فراخوانی:** 6 درخواست در هر دقیقه
226 |
227 | ### پارامترهای ورودی
228 |
229 | | پارامتر | نوع | پیشفرض | توضیحات | نمونه |
230 | |---------|--------|---------|------------------------|---------|
231 | | otpCode | string | الزامی | کد تأیید ایمیل و پیامک | `1234` |
232 | | tfaCode | string | الزامی | کد تأیید دوعاملی | `12345` |
233 |
234 | ### حالتهای خطا
235 |
236 | > در صورت عدم پذیرش درخواست، پاسخ به این صورت خواهد بود:
237 |
238 | ```json
239 | {
240 | "status": "failed",
241 | "code": "ErrorCode",
242 | "message": "Human readable error message"
243 | }
244 | ```
245 |
246 | | کد خطا | توضیحات |
247 | |-------------|----------------------------------------------------------------|
248 | | ParseError | نوع یا شرط الزامی بودن یکی از پارامترهای ورودی رعایت نشده است. |
249 | | InvalidOTP | مقدار tfa وارد شده نادرست است. |
250 | | Invalid2FA | مقدار otp وارد شده نادرست است. |
251 | | Inactive2FA | tfa فعال نیست |
252 |
--------------------------------------------------------------------------------