Initial commit
This commit is contained in:
51
docs/zagros/deposit/blockchain.md
Normal file
51
docs/zagros/deposit/blockchain.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Blockchain Deposit
|
||||
[please read first](daemon.md)
|
||||
|
||||
### file:
|
||||
- {$Dena_path}/app/workers/daemons/blockchain.rb
|
||||
|
||||
### implementation
|
||||
daemon dockerize by below code and file:
|
||||
- bash -c "bundle exec ruby lib/daemons/daemons.rb blockchain" (called in Alvand Service up rake)
|
||||
- {$Dena_path}/lib/daemons/daemons.rb
|
||||
|
||||
Blockchain daemon as one **thread** for each active blockchain, process blocks and filter platform deposits.<br />
|
||||
this daemon use BlockchainService class in per one thread.<br/>
|
||||
that class recognizes its `adapter` (coin-connectors or coin-middleman) with help of the parameter that is passed to it when initialized,
|
||||
this parameter is **the blockchain DB record.**<br/>
|
||||
also, this class has standard functions that any coin-connectors must obey, so this class has two hands, with one hand connect to local DB and with another hand talk to the relevant Blockchain with help of `the adapter`.<br/>
|
||||
each coin has itself adapter that can be the Gem.<br />
|
||||
responsibility of these Adapters that connect to the related blockchain and doing my needed methods.<br/>
|
||||
this daemon is kept alive by an infinite loop that in every 30 seconds check the active blockchains.<br />
|
||||
also, in this 30-second time, check updated time of the blockchain or currencies record, if they have been newly updated time,
|
||||
the blockchain thread will be reset.<br />
|
||||
when the blockchain thread is reset, the last_seen_block will become **nil**.</br>
|
||||
BlockchainService class fetches relative blocks with help the Adapter,<br />
|
||||
and find transactions that included our users addresses (users addresses were saved in local DB).<br />
|
||||
after each loop of the Blockchain investigation, we update the Variable that has kept the last seen block number.<br />
|
||||
and also update the Height column of the blockchain record.<br />
|
||||
We are waiting for the N number of confirmations.<br />
|
||||
if height column of the blockchain record plus(+) the min confirmation, was bigger than the Adapters last seen block variable, synchronization will be skipped, and try again after 10 seconds<br />
|
||||
from the blockchain height to Adapters last_seen_block, the `process_block` function of **BlockchainService** class will be executed for each block.<br/>
|
||||
at last the height column will be updated.
|
||||
|
||||
#### process_block function
|
||||
1. fetch block by Adapter
|
||||
2. find relative deposits (destination address of blocks in our user address).
|
||||
3. find relative withdraws (hash transaction of blocks in our user confirming withdraws `txid`).
|
||||
4. Per deposit Blockchain, we update or create Db record and changing users balances.
|
||||
5. Per withdraw in Blockchain, we find Db records by `confirming` state, then update record state by the blockchain transaction,
|
||||
that was fetched before again by its the Adapter. so, at last, we will unlock and update user balances
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A(Peatio) -->|Blockchain stuffs| B[BlockchainService using adapter]
|
||||
|
||||
B --> |Blockchain stuffs| D((Btc Blockchain))
|
||||
B --> |Blockchain stuffs| E((Eth Blockchain))
|
||||
B --> |Blockchain stuffs| F((...))
|
||||
B --> A
|
||||
D --> B
|
||||
E --> B
|
||||
F --> B
|
||||
```
|
||||
29
docs/zagros/deposit/collection-fee.md
Normal file
29
docs/zagros/deposit/collection-fee.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Blockchain Collection fee
|
||||
[please read first](daemon.md)
|
||||
|
||||
### files:
|
||||
- {$Dena_path}/app/workers/daemons/deposit.rb
|
||||
- {$Dena_path}/app/services/wallet_service.rb
|
||||
|
||||
### implementation
|
||||
during blockchain deposit daemon, WalletService asks its Adapter (by passing The relevant deposit wallet) that the `prepare_deposit_collection!` method was implemented or not.<br />
|
||||
if not, the daemon kept continues its process, but if that method existed in the coin Adapter, the deposit daemon call the `collect_fee` method on the deposit DB record.<br />
|
||||
|
||||
#### collect_fee function
|
||||
1. Check the spread column of the deposit to find was filled or not. if not call `spread_between_wallets!` from the Deposit model.
|
||||
2. Active relevant fee wallet will be found from DB. if not found, we will back to the deposit daemon process.
|
||||
3. Create WalletService object by passing active fee wallet and run `deposit_collection_fees!` method on the deposit record.
|
||||
4. `deposit_collection_fees` method, run `prepare_deposit_collection`
|
||||
5. `prepare_deposit_collection` method will have a unique implementation for each coin (blockchain),but eventually, the output must be a transaction that in addition to sending into the relevant blockchain, also will be saved in the local DB.
|
||||
6. Change the state column of the deposit record from `processing` to `fee_processing`
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A((Depoist Daemon)) -->|deposit record| B[WalletService ]
|
||||
B --> |the Depoist Wallet Record| C{Adapter}
|
||||
C --> |`prepare_deposit_collection` is not impelemented |A
|
||||
C --> |`prepare_deposit_collection` is impelemented| E(WalletService)
|
||||
E --> |the Fee Wallet Record| C
|
||||
C --> D(`deposit_collection_fees!`)
|
||||
D --> |change state to fee_processing|A
|
||||
```
|
||||
65
docs/zagros/deposit/daemon.md
Normal file
65
docs/zagros/deposit/daemon.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Blockchain Deposit Watcher
|
||||
Peatio daemons are controlled by this gem: [God](http://godrb.com/).
|
||||
##### note: just we use the God if want using The Peatio in local without docker, in collection service, daemons handle by docker container.
|
||||
|
||||
## Daemon
|
||||
##### start daemon with the god:
|
||||
`god -c lib/daemons/daemons.god` <br/>
|
||||
**When the Peatio is being initialized, the God starts all daemons**<br />
|
||||
|
||||
##### stop daemon with the god:
|
||||
`god stop`. *God will still be up.*<br />
|
||||
|
||||
##### stop God and all daemons:
|
||||
`god terminate`
|
||||
|
||||
##### restart God: <br />
|
||||
`god restart`
|
||||
|
||||
##### status God: <br />
|
||||
`god status`
|
||||
|
||||
#### [please read it](../../../README.md)
|
||||
|
||||
|
||||
## Deposit Daemon
|
||||
###### this Daemon, become a docker service by daemons.yaml that call in service.rake
|
||||
[first read deposits_flow](../../../docs/peatio/deposits_flow.md)
|
||||
|
||||
**so we use new version of deposit**
|
||||
#### files:
|
||||
- {$Dena_path}/app/workers/daemons/deposit.rb
|
||||
- {$Dena_path}/app/workers/daemons/blockchain.rb
|
||||
|
||||
#### implementation
|
||||
daemon dockerize by below code and file:
|
||||
- bash -c "bundle exec ruby lib/daemons/daemons.rb deposit" (called in Alvand Service up rake)
|
||||
- {$Dena_path}/lib/daemons/daemons.rb
|
||||
|
||||
We decided to remove to AMQP base deposit daemons and create a new deposit daemon that will work on deposit states changes
|
||||
and will prevent immediate proceeding of erc20 deposits.
|
||||
|
||||
New deposit process diagram:
|
||||
|
||||

|
||||
|
||||
1. Blockchain daemon process blocks and filter platform deposits and save them in our DB. [document](blockchain.md) <br />
|
||||
3. In the deposit daemons we select each 60s deposits with state `processing` and `fee_processing`.
|
||||
4. For `processing` deposits we are checking if plugin implement method `prepare_deposit_collection!` if it doesn't we immediately process the deposit and collect deposit to the `hot`, `warm`, `cold` wallets.<br />
|
||||
this collection is done with help of WalletService class, that one of its responsibility is **spreading** between wallets.
|
||||
[read more about WalletService](../withdraw/withdraw-coin.md)<br/>
|
||||
every deposit record has column named `spread` that getting array value like this:<br />
|
||||
`[{"to_address"=>"xyxzx", "amount"=>"0.00083", "currency_id"=>"btc", "status"=>"pending", "hash"=>"dcffd5b7fabaa"}]`,<br />
|
||||
valued by (`spread_between_wallets!` *function* in deposit model) that was called in this daemon<br/>
|
||||
each row of the Spread array, will become transaction record and will be send to the Blockchain by WalletService and its the Adapter (`collect_deposit!` function).<br />
|
||||
If plugin implement method `prepare_deposit_collection!` daemon processing of collection fees and change deposit state to `fee_processing`.<br />
|
||||
For deposits with `fee_processing` state, we select each minute deposits that have `updated_at` older than 5 minutes and process them. With time condition we are sure that fee transaction has already been executed.<br />
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A((Blockchain)) -->|Deposit| B[Blockchain Daemon]
|
||||
B --> |waiting for numbers of confirmations| C[Deposit Daemon]
|
||||
D(BlockchainService) --> B
|
||||
E(WalletService) --> C
|
||||
```
|
||||
|
||||
57
docs/zagros/deposit/fiat.md
Normal file
57
docs/zagros/deposit/fiat.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Deposit: Fiat
|
||||
###### Sprint: 5
|
||||
|
||||
### Outcome:
|
||||
Users can do fiat deposits with the Help of the Vandar service.
|
||||
|
||||
### Implementation description:
|
||||
|
||||
#### Endpoints:
|
||||
POST {$domain}/api/v2/peatio/account/deposits/fiat <br/>
|
||||
POST {$domain}/api/v2/peatio/account/deposits/confirm<br/>
|
||||
#### File destination:
|
||||
{$Dena_Path}/app/api/v2/account/deposits.rb
|
||||
|
||||
#### Commits:
|
||||
3b189b07<br/>
|
||||
d436176b<br/>
|
||||
1cc9fb29<br/>
|
||||
9a6d7864<br/>
|
||||
5994b163<br/>
|
||||
7769e86a<br/>
|
||||
7dea7777<br/>
|
||||
#### What did we implement:
|
||||
we implemented a new client route for user, to they can deposit their money and charge their accounts
|
||||
|
||||
### TODO
|
||||
now we dont show any information of the deposit result to user, so in the result of the Vandar the amount perhaps remains as Rial
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
|
||||
Title: Depost Fiat
|
||||
|
||||
note over User,Ranj:The description and factorNumber are optionals
|
||||
note over User,Ranj:callback_url parameter use for Vandar Service\n to redirect Bank Gateway into my system after deposit
|
||||
User->>Ranj:amount, callback_url, currency, card, **factorNumber**, **description**
|
||||
Ranj->>Dalan:POST: after client side checking
|
||||
Dalan->>Ranj:4xx if lose any required parameters
|
||||
note over Dalan,Vandar:The Vandar service has own documentation
|
||||
Dalan->>Ranj:4xx if entered Card number not exist in current user valid Card number list
|
||||
Dalan->>Ranj:new deoposit recored created
|
||||
Dalan->>Ranj:4xx if any model validation become false
|
||||
Dalan->>Vandar:POST valid_card_number, amount, callback_url, description
|
||||
Vandar->>Dalan:A new deposit token will be generated for Bank Gateway
|
||||
Dalan->>Ranj: pass generated Token
|
||||
Ranj->>User:if token present redirect user's page to Bank Gateway \n otherwise, show errors in the Vandar response and process finished
|
||||
User-->>Vandar: entering bank information for doing deposit
|
||||
Vandar->>Ranj:GET pass generated token to callback_url
|
||||
Ranj->>Dalan: POST generated token for confirming step
|
||||
Dalan->>Ranj:at first, we check the database to check the status of the deposit that was unique by the generated token.\n show record result if txid present in DB,\n otherwise ask The Vandar for result of this deposit.
|
||||
Dalan->>Vandar: POST generated token to find transaction
|
||||
Vandar->>Dalan: pass result of transaction
|
||||
Dalan->>Vandar: POST generated token to verify transaction
|
||||
Dalan->>Ranj: update deposit record in DB (txid) and charge user balane
|
||||
Ranj->>User: notify the user that the deposit is done.
|
||||
|
||||
```
|
||||
49
docs/zagros/deposit/spread-between-wallets.md
Normal file
49
docs/zagros/deposit/spread-between-wallets.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Spread between wallets method
|
||||
[Please read first](daemon.md)
|
||||
|
||||
### files:
|
||||
- {$Dena_path}/app/workers/daemons/deposit.rb
|
||||
- {$Dena_path}/app/models/deposit.rb
|
||||
|
||||
|
||||
### implementation
|
||||
If you have read the deposit doc, you know this function where is called.
|
||||
|
||||
#### spread_between_wallets! function
|
||||
1. Will Return to ex-process if the Spread column had value.
|
||||
2. Finding the Deposit wallet form currency and pass it as input param to the WalletService class to create the object.
|
||||
3. Calling `spread_deposit` function from **WalletService** class for the deposit record
|
||||
4. Update the spread column for DB record with return value from step **3**.
|
||||
|
||||
#### spread_deposit function
|
||||
1. The Adapter will be configured with the wallet record data and the relevant blockchain and currency setting
|
||||
2. Array list by data of the withdraw wallet form DB (HOT WARM COLD)
|
||||
3. Map them to new data by name **destination_wallets**:
|
||||
- `address` : the wallet address
|
||||
- `balance` : the current coin balance of wallet
|
||||
- `max_balance` : how many coins the wallet can host
|
||||
- `min_collection_amount` : the minimum of accepted deposit (set in the Admin panel)
|
||||
- `skip_deposit_collection` : boolean type to skip deposit or not (set in the Admin panel)
|
||||
4. Set the zero the balance for the last wallet. Since last wallet is considered to be the most secure we need always. All money which doesn't fit to other wallets will be collected to last wallet.
|
||||
5. Call `spread_between_wallets` from *WalletService* with the deposit record and the **destination_wallets**
|
||||
|
||||
|
||||
#### spread_between_wallets function
|
||||
1. Returning empty array if deposit amount smaller than the minimum of `min_collection amount` of wallets.
|
||||
2. left_amount variable is initialized with amount of the deposit (*original_amount*)
|
||||
3. starting a loop on `destination_wallets`.
|
||||
4. `amount_for_wallet` = choose the minimum value between available wallet balance and left_amount
|
||||
5. Setting zero for `amount_for_wallet` if this variable smaller than `min_collection_amount`
|
||||
6. `left_amount` will equal to (`left_amount` minus `amount_for_wallet`)
|
||||
7. If amount left is too small we will not able to collect it.So we collect everything to current wallet.<br/ >
|
||||
`amount_for_wallet` = `amount_for_wallet` + `left_amount` and `left_amount` = 0
|
||||
8. Creating `Peatio::Transaction` object:
|
||||
- to_address : `to_address` from **destination_wallets**
|
||||
- amount : `amount_for_wallet`
|
||||
- currency_id: currency_id of the deposit record
|
||||
- status : :skipped if `skip_deposit_collection` is true
|
||||
9. Ending the loop on `destination_wallets` and now we have `spread` variable that includes **transactions**.
|
||||
|
||||
10. If deposit amount doesn't fit to any wallet, collect it to the last one. (`left_amount` doesnt become zero).
|
||||
11. Remove zero and skipped transactions from spread.
|
||||
12. Return `spread` variable.
|
||||
Reference in New Issue
Block a user