stellar_base-rails 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +19 -29
- data/app/concepts/stellar_base/bridge_callbacks/bridge_callback_policy.rb +14 -0
- data/app/concepts/stellar_base/bridge_callbacks/contracts/{process.rb → create.rb} +5 -5
- data/app/concepts/stellar_base/bridge_callbacks/operations/create.rb +31 -0
- data/app/concepts/stellar_base/withdrawal_requests/contracts/create.rb +38 -0
- data/app/concepts/stellar_base/withdrawal_requests/operations/create.rb +53 -0
- data/app/concepts/stellar_base/withdrawal_requests/withdrawal_request_policy.rb +14 -0
- data/app/controllers/stellar_base/bridge_callbacks_controller.rb +1 -1
- data/app/controllers/stellar_base/withdraw_controller.rb +35 -0
- data/app/models/stellar_base/bridge_callback.rb +1 -14
- data/app/models/stellar_base/withdrawal_request.rb +4 -0
- data/app/representers/application_representer.rb +3 -0
- data/app/representers/withdrawal_request_representer.rb +13 -0
- data/app/services/stellar_base/bridge_callbacks/process.rb +9 -7
- data/app/services/stellar_base/gen_random_string.rb +10 -0
- data/app/services/stellar_base/withdrawal_requests/call_on_withdraw.rb +30 -0
- data/app/services/stellar_base/withdrawal_requests/determine_fee.rb +21 -0
- data/app/services/stellar_base/withdrawal_requests/find_withdrawal_request.rb +40 -0
- data/app/services/stellar_base/withdrawal_requests/gen_memo.rb +19 -0
- data/app/services/stellar_base/withdrawal_requests/process.rb +27 -0
- data/app/twins/application_twin.rb +3 -0
- data/app/twins/withdrawal_request_twin.rb +13 -0
- data/config/routes.rb +2 -3
- data/db/migrate/20180816014433_create_stellar_base_bridge_callbacks.rb +21 -0
- data/db/migrate/20180816110314_create_stellar_base_withdrawal_requests.rb +25 -0
- data/db/migrate/20180816135847_unique_stellar_base_bridge_callbacks_operation_id.rb +11 -0
- data/lib/stellar_base.rb +33 -0
- data/lib/stellar_base/factories.rb +3 -0
- data/lib/stellar_base/factories/bridge_callbacks.rb +9 -0
- data/lib/stellar_base/factories/withdrawal_requests.rb +14 -0
- data/lib/stellar_base/version.rb +1 -1
- metadata +97 -5
- data/app/concepts/stellar_base/bridge_callbacks/operations/process.rb +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 15b69658233c066ee56074dd0bcf6ceed2abb687d873322e7d732f36bfb9d96c
|
4
|
+
data.tar.gz: 29e95f9804ccd034b6a9d210792ad19800936fbfddc9ae7c0588dd62bce0231d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9340c436c18b047df93e5a6ca27321c4fe586ed0c60f449e3d55a2042cfd8ac9f19411d7fdb2e6954c4767d64dbd8c22f2c436f0475daa0d1513bcaf27018f57
|
7
|
+
data.tar.gz: 123e430f1e9f8fc2a938bcd928e09a34174f3325c7df4a9649d48de58e255bed5a4e3b2961118485ed220c08a6368761c3bddbcaab35cd3b612769080f991a0c
|
data/README.md
CHANGED
@@ -11,6 +11,11 @@ Adding modules to your routes:
|
|
11
11
|
mount StellarBase::Engine => "/stellar_base"
|
12
12
|
```
|
13
13
|
|
14
|
+
```sh
|
15
|
+
rails stellar_base:install:migrations
|
16
|
+
rails db:migrate
|
17
|
+
```
|
18
|
+
|
14
19
|
### Configuration
|
15
20
|
Create an initializer in your rails application:
|
16
21
|
|
@@ -30,41 +35,21 @@ end
|
|
30
35
|
|
31
36
|
|
32
37
|
#### c.modules
|
33
|
-
|
34
|
-
|
38
|
+
You can supply what endpoints you want to activate with the gem
|
39
|
+
|
40
|
+
- Value(s): array of symbols. See the [modules documentation](docs/modules.md) for more details.
|
35
41
|
- Default: `%i(bridge_callbacks)`
|
36
|
-
|
37
|
-
|
42
|
+
|
43
|
+
#### c.distribution_account
|
44
|
+
This is the same distribution account that is setup in bridge. Currently, it is used in the `/withdraw` endpoint -- to tell the user to send the assets there.
|
45
|
+
|
46
|
+
- Value: Stellar account address
|
38
47
|
|
39
48
|
#### c.horizon_url
|
40
49
|
- Value(s): String, url to horizon
|
41
50
|
- Default: https://horizon.stellar.org
|
42
51
|
- This is where the engine will check bridge callbacks if `c.check_bridge_callbacks_authenticity` is turned on
|
43
52
|
|
44
|
-
#### c.on_bridge_callback
|
45
|
-
- Value(s): Class
|
46
|
-
- Default: None
|
47
|
-
- Once the bridge_receive endpoint receives a callback, the class will be called with .call
|
48
|
-
- The class will be passed with the bridge server callback payload contained in a `StellarBase::BridgeCallback` object.
|
49
|
-
- The class will be expected to return a boolean, return true if the callback was processed properly
|
50
|
-
- Warning: The bridge server will may post multiple callbacks with the same ID, make sure you handle these correctly. https://github.com/stellar/bridge-server/blob/master/readme_bridge.md#callbacksreceive
|
51
|
-
|
52
|
-
|
53
|
-
#### c.check_bridge_callbacks_authenticity
|
54
|
-
- Value(s): `true` or `false`
|
55
|
-
- Default: `false`
|
56
|
-
- This secures the `/bridge_callbacks` endpoint from fake transactions by checking the transaction ID and it's contents against the Stellar Blockchain. If it doesn't add up, `/bridge_callbacks` endpoint will respond with a 422
|
57
|
-
|
58
|
-
#### c.check_bridge_callbacks_mac_payload
|
59
|
-
- Value(s): `true` or `false`
|
60
|
-
- Default: `false`
|
61
|
-
- This secures the `/bridge_callbacks` endpoint from fake transactions by checking the `X_PAYLOAD_MAC` header for 1.) existence and 2.) if it matches the HMAC-SH256 encoded raw request body
|
62
|
-
|
63
|
-
#### c.bridge_callbacks_mac_key
|
64
|
-
- Value(s): Any Stellar Private Key, it should be the same as the mac_key configured in your bridge server
|
65
|
-
- Default: None
|
66
|
-
- This is used to verify the contents of `X_PAYLOAD_MAC` by encoding the raw request body with the decoded `bridge_callback_mac_key` as the key
|
67
|
-
|
68
53
|
## Installation
|
69
54
|
Add this line to your application's Gemfile:
|
70
55
|
|
@@ -78,7 +63,12 @@ $ bundle
|
|
78
63
|
```
|
79
64
|
|
80
65
|
## Contributing
|
81
|
-
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
cp spec/config.yml{.sample,}
|
69
|
+
```
|
70
|
+
|
71
|
+
Edit the `spec/config.yml` file.
|
82
72
|
|
83
73
|
## License
|
84
74
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module StellarBase
|
2
2
|
module BridgeCallbacks
|
3
3
|
module Contracts
|
4
|
-
class
|
4
|
+
class Create < ApplicationContract
|
5
5
|
|
6
|
-
property :
|
6
|
+
property :operation_id
|
7
7
|
property :from
|
8
8
|
property :route
|
9
9
|
property :amount
|
@@ -14,7 +14,7 @@ module StellarBase
|
|
14
14
|
property :data
|
15
15
|
property :transaction_id
|
16
16
|
|
17
|
-
validates :
|
17
|
+
validates :operation_id, presence: true
|
18
18
|
validates :transaction_id, presence: true
|
19
19
|
validates :from, presence: true
|
20
20
|
validates :amount, presence: true
|
@@ -27,10 +27,10 @@ module StellarBase
|
|
27
27
|
end
|
28
28
|
|
29
29
|
result = BridgeCallbacks::Check.({
|
30
|
-
operation_id:
|
30
|
+
operation_id: operation_id,
|
31
31
|
transaction_id: transaction_id,
|
32
32
|
params: {
|
33
|
-
id:
|
33
|
+
id: operation_id,
|
34
34
|
from: from,
|
35
35
|
route: route,
|
36
36
|
amount: amount,
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module StellarBase
|
2
|
+
module BridgeCallbacks
|
3
|
+
module Operations
|
4
|
+
class Create < ApplicationOperation
|
5
|
+
step Policy::Pundit(BridgeCallbackPolicy, :create?)
|
6
|
+
step :assign_operation_id!
|
7
|
+
step :find_model!
|
8
|
+
step Model(BridgeCallback, :new)
|
9
|
+
step Contract::Build(constant: Contracts::Create)
|
10
|
+
step Contract::Validate(key: :bridge_callback)
|
11
|
+
step Contract::Persist()
|
12
|
+
step :process!
|
13
|
+
|
14
|
+
def find_model!(options, params:, **)
|
15
|
+
operation_id = params[:bridge_callback][:operation_id]
|
16
|
+
bridge_callback = BridgeCallback.find_by(operation_id: operation_id)
|
17
|
+
options["model"] = bridge_callback
|
18
|
+
bridge_callback.present? ? Railway.pass_fast! : true
|
19
|
+
end
|
20
|
+
|
21
|
+
def assign_operation_id!(options, params:, **)
|
22
|
+
params[:bridge_callback][:operation_id] = params[:bridge_callback][:id]
|
23
|
+
end
|
24
|
+
|
25
|
+
def process!(options, **)
|
26
|
+
BridgeCallbacks::Process.(options["model"])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module StellarBase
|
2
|
+
module WithdrawalRequests
|
3
|
+
module Contracts
|
4
|
+
class Create < ApplicationContract
|
5
|
+
|
6
|
+
property :asset_type
|
7
|
+
property :asset_code
|
8
|
+
property :dest
|
9
|
+
property :dest_extra
|
10
|
+
property :issuer
|
11
|
+
property :account_id
|
12
|
+
property :memo_type
|
13
|
+
property :memo
|
14
|
+
property :eta
|
15
|
+
property :min_amount
|
16
|
+
property :max_amount
|
17
|
+
property :fee_fixed
|
18
|
+
property :fee_percent
|
19
|
+
property :fee_network
|
20
|
+
|
21
|
+
validates(
|
22
|
+
*%i[
|
23
|
+
asset_type
|
24
|
+
asset_code
|
25
|
+
dest
|
26
|
+
issuer
|
27
|
+
account_id
|
28
|
+
fee_network
|
29
|
+
fee_fixed
|
30
|
+
fee_percent
|
31
|
+
],
|
32
|
+
presence: true
|
33
|
+
)
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module StellarBase
|
2
|
+
module WithdrawalRequests
|
3
|
+
module Operations
|
4
|
+
class Create < ApplicationOperation
|
5
|
+
|
6
|
+
DEFAULT_ETA = (10 * 60).freeze
|
7
|
+
|
8
|
+
step self::Policy::Pundit(WithdrawalRequestPolicy, :create?)
|
9
|
+
step Model(WithdrawalRequest, :new)
|
10
|
+
step :find_withdrawal_asset_details!
|
11
|
+
success :set_defaults!
|
12
|
+
step Contract::Build(constant: Contracts::Create)
|
13
|
+
step Contract::Validate(key: :withdrawal_request)
|
14
|
+
step Contract::Persist()
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def find_withdrawal_asset_details!(options, params:, **)
|
19
|
+
withdrawable_assets = StellarBase.configuration.withdrawable_assets
|
20
|
+
details = withdrawable_assets.find do |e|
|
21
|
+
e[:asset_code] == params[:withdrawal_request][:asset_code]
|
22
|
+
end
|
23
|
+
|
24
|
+
return Railway.fail_fast! if details.nil?
|
25
|
+
|
26
|
+
options["withdrawal_asset_details"] = details
|
27
|
+
return true
|
28
|
+
end
|
29
|
+
|
30
|
+
def set_defaults!(options, withdrawal_asset_details:, params:, **)
|
31
|
+
fee_network = DetermineFee.network(
|
32
|
+
withdrawal_asset_details[:network],
|
33
|
+
params[:withdrawal_request][:fee_network],
|
34
|
+
)
|
35
|
+
params[:withdrawal_request].merge!({
|
36
|
+
asset_type: params[:withdrawal_request][:type],
|
37
|
+
issuer: withdrawal_asset_details[:issuer],
|
38
|
+
account_id: StellarBase.configuration.distribution_account,
|
39
|
+
memo_type: "text",
|
40
|
+
memo: GenMemo.(),
|
41
|
+
eta: DEFAULT_ETA,
|
42
|
+
min_amount: 0.0,
|
43
|
+
max_amount: nil,
|
44
|
+
fee_fixed: DetermineFee.(withdrawal_asset_details[:fee_fixed]),
|
45
|
+
fee_percent: DetermineFee.(withdrawal_asset_details[:fee_percent]),
|
46
|
+
fee_network: fee_network,
|
47
|
+
})
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -4,7 +4,7 @@ module StellarBase
|
|
4
4
|
before_action :verify_mac_payload, if: :check_mac_payload?
|
5
5
|
|
6
6
|
def create
|
7
|
-
op = BridgeCallbacks::Operations::
|
7
|
+
op = BridgeCallbacks::Operations::Create.(bridge_callback: callback_params)
|
8
8
|
|
9
9
|
respond_to do |f|
|
10
10
|
f.json do
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module StellarBase
|
2
|
+
class WithdrawController < ApplicationController
|
3
|
+
|
4
|
+
WITHDRAWAL_REQUEST_PARAMS = %i[
|
5
|
+
type
|
6
|
+
asset_code
|
7
|
+
dest
|
8
|
+
dest_extra
|
9
|
+
fee_network
|
10
|
+
]
|
11
|
+
|
12
|
+
def create
|
13
|
+
op = WithdrawalRequests::Operations::Create.(withdrawal_request: withdrawal_request_params)
|
14
|
+
|
15
|
+
respond_to do |f|
|
16
|
+
f.json do
|
17
|
+
if op.success?
|
18
|
+
twin = WithdrawalRequestTwin.new(op["model"])
|
19
|
+
representer = WithdrawalRequestRepresenter.new(twin)
|
20
|
+
render json: representer
|
21
|
+
else
|
22
|
+
head :unprocessable_entity
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def withdrawal_request_params
|
31
|
+
params.permit(*WITHDRAWAL_REQUEST_PARAMS)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -1,17 +1,4 @@
|
|
1
1
|
module StellarBase
|
2
|
-
class BridgeCallback
|
3
|
-
include Virtus.model
|
4
|
-
# Attributes and params from
|
5
|
-
# https://github.com/stellar/bridge-server/blob/master/readme_bridge.md#callbacksreceive
|
6
|
-
attribute :id, String
|
7
|
-
attribute :from, String
|
8
|
-
attribute :route, String
|
9
|
-
attribute :amount, Float
|
10
|
-
attribute :asset_code, String
|
11
|
-
attribute :asset_issuer, String
|
12
|
-
attribute :memo_type, String
|
13
|
-
attribute :memo, String
|
14
|
-
attribute :data, String
|
15
|
-
attribute :transaction_id, String
|
2
|
+
class BridgeCallback < ApplicationRecord
|
16
3
|
end
|
17
4
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class WithdrawalRequestRepresenter < ApplicationRepresenter
|
2
|
+
|
3
|
+
property :account_id
|
4
|
+
property :memo_type
|
5
|
+
property :memo
|
6
|
+
property :min_amount
|
7
|
+
property :max_amount
|
8
|
+
property :fee_fixed
|
9
|
+
property :fee_percent
|
10
|
+
property :fee_network
|
11
|
+
property :extra_info
|
12
|
+
|
13
|
+
end
|
@@ -3,7 +3,15 @@ module StellarBase
|
|
3
3
|
class Process
|
4
4
|
def self.call(callback)
|
5
5
|
callback_class.(callback)
|
6
|
-
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def self.callback_class
|
11
|
+
on_bridge_callback = StellarBase.configuration.on_bridge_callback
|
12
|
+
return on_bridge_callback if on_bridge_callback.respond_to?(:call)
|
13
|
+
on_bridge_callback.constantize
|
14
|
+
rescue NameError
|
7
15
|
error_message = [
|
8
16
|
"StellarBase.on_bridge_callback isn't configured or the",
|
9
17
|
"configured callback class doesn't exist:",
|
@@ -12,12 +20,6 @@ module StellarBase
|
|
12
20
|
|
13
21
|
raise NameError, error_message
|
14
22
|
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def self.callback_class
|
19
|
-
StellarBase.configuration.on_bridge_callback.constantize
|
20
|
-
end
|
21
23
|
end
|
22
24
|
end
|
23
25
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module StellarBase
|
2
|
+
module WithdrawalRequests
|
3
|
+
class CallOnWithdraw
|
4
|
+
|
5
|
+
extend LightService::Action
|
6
|
+
expects :withdrawal_request, :bridge_callback, :on_withdraw
|
7
|
+
|
8
|
+
ON_WITHDRAW_ERROR = "`on_withdraw` must be a string of an object " \
|
9
|
+
"that responds to `.call` or the object itself"
|
10
|
+
|
11
|
+
executed do |c|
|
12
|
+
callback = callback_from(c.on_withdraw)
|
13
|
+
callback.(c.withdrawal_request, c.bridge_callback)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.callback_from(on_withdraw)
|
17
|
+
if on_withdraw.respond_to?(:constantize)
|
18
|
+
on_withdraw = on_withdraw.constantize
|
19
|
+
end
|
20
|
+
|
21
|
+
if !on_withdraw.respond_to?(:call)
|
22
|
+
fail ArgumentError, ON_WITHDRAW_ERROR
|
23
|
+
end
|
24
|
+
|
25
|
+
on_withdraw
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module StellarBase
|
2
|
+
module WithdrawalRequests
|
3
|
+
class DetermineFee
|
4
|
+
|
5
|
+
DEFAULT = 0.0
|
6
|
+
# NOTE: Hard-code default network fees for now.
|
7
|
+
DEFAULT_NETWORK = {
|
8
|
+
bitcoin: 0.0001,
|
9
|
+
}.with_indifferent_access.freeze
|
10
|
+
|
11
|
+
def self.call(v)
|
12
|
+
v || DEFAULT
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.network(network, v)
|
16
|
+
v || DEFAULT_NETWORK.fetch(network)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module StellarBase
|
2
|
+
module WithdrawalRequests
|
3
|
+
class FindWithdrawalRequest
|
4
|
+
|
5
|
+
extend LightService::Action
|
6
|
+
expects :bridge_callback
|
7
|
+
promises :withdrawal_request
|
8
|
+
|
9
|
+
MATCH_WITHDRAWAL_REQUEST_TO_BRIDGE_CALLBACK_MAP = {
|
10
|
+
asset_code: :asset_code,
|
11
|
+
issuer: :asset_issuer,
|
12
|
+
memo_type: :memo_type,
|
13
|
+
memo: :memo,
|
14
|
+
}.freeze
|
15
|
+
|
16
|
+
executed do |c|
|
17
|
+
bridge_callback = c.bridge_callback
|
18
|
+
c.withdrawal_request = withdrawal_request = WithdrawalRequest.
|
19
|
+
find_by(memo: bridge_callback.memo)
|
20
|
+
|
21
|
+
if withdrawal_request.nil?
|
22
|
+
c.skip_remaining!
|
23
|
+
next c
|
24
|
+
end
|
25
|
+
|
26
|
+
map = MATCH_WITHDRAWAL_REQUEST_TO_BRIDGE_CALLBACK_MAP
|
27
|
+
mismatch = map.any? do |withdrawal_request_attr, bridge_callback_attr|
|
28
|
+
withdrawal_request.send(withdrawal_request_attr) !=
|
29
|
+
bridge_callback.send(bridge_callback_attr)
|
30
|
+
end
|
31
|
+
|
32
|
+
if mismatch
|
33
|
+
c.skip_remaining!
|
34
|
+
next c
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module StellarBase
|
2
|
+
module WithdrawalRequests
|
3
|
+
class GenMemo
|
4
|
+
|
5
|
+
LENGTH = 8
|
6
|
+
|
7
|
+
def self.call
|
8
|
+
loop do
|
9
|
+
memo = GenRandomString.(length: LENGTH)
|
10
|
+
if !WithdrawalRequest.exists?(memo: memo)
|
11
|
+
return memo
|
12
|
+
break
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module StellarBase
|
2
|
+
module WithdrawalRequests
|
3
|
+
class Process
|
4
|
+
|
5
|
+
extend LightService::Organizer
|
6
|
+
|
7
|
+
def self.call(
|
8
|
+
bridge_callback,
|
9
|
+
on_withdraw: StellarBase.configuration.on_withdraw
|
10
|
+
)
|
11
|
+
with(
|
12
|
+
bridge_callback: bridge_callback,
|
13
|
+
on_withdraw: on_withdraw,
|
14
|
+
).reduce(actions)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.actions
|
18
|
+
[
|
19
|
+
FindWithdrawalRequest,
|
20
|
+
CallOnWithdraw,
|
21
|
+
]
|
22
|
+
end
|
23
|
+
private_class_method :actions
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class WithdrawalRequestTwin < ApplicationTwin
|
2
|
+
|
3
|
+
property :account_id
|
4
|
+
property :memo_type
|
5
|
+
property :memo
|
6
|
+
property :min_amount
|
7
|
+
property :max_amount
|
8
|
+
property :fee_fixed
|
9
|
+
property :fee_percent
|
10
|
+
property :fee_network
|
11
|
+
property :extra_info
|
12
|
+
|
13
|
+
end
|
data/config/routes.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
StellarBase::Engine.routes.draw do
|
2
|
-
|
3
|
-
|
4
|
-
end
|
2
|
+
resources :bridge_callbacks, only: [:create], defaults: { format: "json" }
|
3
|
+
get "/withdraw" => "withdraw#create", as: :withdraw
|
5
4
|
end
|
6
5
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class CreateStellarBaseBridgeCallbacks < ActiveRecord::Migration[5.1]
|
2
|
+
def change
|
3
|
+
create_table :stellar_base_bridge_callbacks do |t|
|
4
|
+
t.string :operation_id, null: false
|
5
|
+
t.string :from, null: false
|
6
|
+
t.string :route
|
7
|
+
t.decimal :amount, null: false
|
8
|
+
t.string :asset_code
|
9
|
+
t.string :asset_issuer
|
10
|
+
t.string :memo_type
|
11
|
+
t.string :memo
|
12
|
+
t.string :data
|
13
|
+
t.string :transaction_id
|
14
|
+
t.index %i[asset_code asset_issuer], name: :index_stellar_base_bridge_callbacks_on_asset
|
15
|
+
t.index :memo
|
16
|
+
t.index :operation_id
|
17
|
+
t.index :transaction_id
|
18
|
+
t.timestamps
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class CreateStellarBaseWithdrawalRequests < ActiveRecord::Migration[5.1]
|
2
|
+
def change
|
3
|
+
create_table :stellar_base_withdrawal_requests do |t|
|
4
|
+
t.string :asset_type, null: false
|
5
|
+
t.string :asset_code, null: false
|
6
|
+
t.string :dest, null: false
|
7
|
+
t.string :issuer, null: false
|
8
|
+
t.string :dest_extra
|
9
|
+
t.string :account_id
|
10
|
+
t.string :memo_type
|
11
|
+
t.string :memo
|
12
|
+
t.integer :eta
|
13
|
+
t.decimal :min_amount, null: false, default: 0.0
|
14
|
+
t.decimal :max_amount
|
15
|
+
t.decimal :fee_fixed, null: false, default: 0.0
|
16
|
+
t.decimal :fee_percent, null: false, default: 0.0
|
17
|
+
t.decimal :fee_network, null: false, default: 0.0
|
18
|
+
t.string :extra_info
|
19
|
+
t.index([:asset_type, :asset_code], {
|
20
|
+
name: :index_stellar_base_withdrawal_requests_on_asset,
|
21
|
+
})
|
22
|
+
t.timestamps
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class UniqueStellarBaseBridgeCallbacksOperationId < ActiveRecord::Migration[5.1]
|
2
|
+
def up
|
3
|
+
remove_index :stellar_base_bridge_callbacks, :operation_id
|
4
|
+
add_index :stellar_base_bridge_callbacks, :operation_id, unique: true
|
5
|
+
end
|
6
|
+
|
7
|
+
def down
|
8
|
+
remove_index :stellar_base_bridge_callbacks, :operation_id
|
9
|
+
add_index :stellar_base_bridge_callbacks, :operation_id
|
10
|
+
end
|
11
|
+
end
|
data/lib/stellar_base.rb
CHANGED
@@ -5,8 +5,10 @@ require "virtus"
|
|
5
5
|
require "httparty"
|
6
6
|
require "trailblazer-rails"
|
7
7
|
require "disposable"
|
8
|
+
require "multi_json"
|
8
9
|
require "reform"
|
9
10
|
require "reform/form/coercion"
|
11
|
+
require "representable"
|
10
12
|
|
11
13
|
require "stellar_base/engine"
|
12
14
|
|
@@ -17,15 +19,46 @@ module StellarBase
|
|
17
19
|
has :horizon_url, default: "https://horizon.stellar.org"
|
18
20
|
has :modules, default: [:bridge_callbacks]
|
19
21
|
|
22
|
+
has :distribution_account, classes: [NilClass, String]
|
23
|
+
|
20
24
|
has :on_bridge_callback
|
21
25
|
has :check_bridge_callbacks_authenticity, default: false
|
22
26
|
has :check_bridge_callbacks_mac_payload, default: false
|
23
27
|
has :bridge_callbacks_mac_key, default: false
|
28
|
+
|
29
|
+
has :withdrawable_assets, classes: [NilClass, Array, String, Pathname]
|
30
|
+
has :on_withdraw
|
31
|
+
end
|
32
|
+
|
33
|
+
after_configuration_change do
|
34
|
+
self.convert_config_withdraw!
|
24
35
|
end
|
25
36
|
|
26
37
|
def self.included_module?(module_name)
|
27
38
|
self.configuration.modules&.include?(module_name)
|
28
39
|
end
|
40
|
+
|
41
|
+
def self.convert_config_withdraw!
|
42
|
+
withdrawable_assets = self.configuration.withdrawable_assets
|
43
|
+
return if withdrawable_assets.is_a?(Array) || withdrawable_assets.nil?
|
44
|
+
|
45
|
+
array_of_hashes = try_from_yaml_file_path(withdrawable_assets) ||
|
46
|
+
try_from_json(withdrawable_assets)
|
47
|
+
|
48
|
+
self.configuration.withdrawable_assets =
|
49
|
+
array_of_hashes.map(&:with_indifferent_access)
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.try_from_json(str)
|
53
|
+
JSON.parse(str)
|
54
|
+
rescue JSON::ParserError
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.try_from_yaml_file_path(str)
|
58
|
+
YAML.load_file(str.to_s)
|
59
|
+
rescue Errno::ENOENT
|
60
|
+
end
|
61
|
+
|
29
62
|
end
|
30
63
|
|
31
64
|
require "stellar_base/horizon_client"
|
@@ -0,0 +1,14 @@
|
|
1
|
+
FactoryBot.define do
|
2
|
+
|
3
|
+
factory(:stellar_base_withdrawal_request, {
|
4
|
+
class: "StellarBase::WithdrawalRequest",
|
5
|
+
}) do
|
6
|
+
asset_type "crypto"
|
7
|
+
asset_code "BTC"
|
8
|
+
issuer "issuer"
|
9
|
+
memo_type "text"
|
10
|
+
dest "destination"
|
11
|
+
sequence(:memo) {|n| "XYZ#{n}" }
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
data/lib/stellar_base/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stellar_base-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ace Subido
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-08-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: virtus
|
@@ -136,6 +136,48 @@ dependencies:
|
|
136
136
|
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: disposable
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: representable
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :runtime
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: multi_json
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :runtime
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
139
181
|
- !ruby/object:Gem::Dependency
|
140
182
|
name: sqlite3
|
141
183
|
requirement: !ruby/object:Gem::Requirement
|
@@ -192,6 +234,34 @@ dependencies:
|
|
192
234
|
- - ">="
|
193
235
|
- !ruby/object:Gem::Version
|
194
236
|
version: '0'
|
237
|
+
- !ruby/object:Gem::Dependency
|
238
|
+
name: factory_bot_rails
|
239
|
+
requirement: !ruby/object:Gem::Requirement
|
240
|
+
requirements:
|
241
|
+
- - ">="
|
242
|
+
- !ruby/object:Gem::Version
|
243
|
+
version: '0'
|
244
|
+
type: :development
|
245
|
+
prerelease: false
|
246
|
+
version_requirements: !ruby/object:Gem::Requirement
|
247
|
+
requirements:
|
248
|
+
- - ">="
|
249
|
+
- !ruby/object:Gem::Version
|
250
|
+
version: '0'
|
251
|
+
- !ruby/object:Gem::Dependency
|
252
|
+
name: stellar-sdk
|
253
|
+
requirement: !ruby/object:Gem::Requirement
|
254
|
+
requirements:
|
255
|
+
- - ">="
|
256
|
+
- !ruby/object:Gem::Version
|
257
|
+
version: '0'
|
258
|
+
type: :development
|
259
|
+
prerelease: false
|
260
|
+
version_requirements: !ruby/object:Gem::Requirement
|
261
|
+
requirements:
|
262
|
+
- - ">="
|
263
|
+
- !ruby/object:Gem::Version
|
264
|
+
version: '0'
|
195
265
|
description: API Endpoints for the Stellar Protocol
|
196
266
|
email:
|
197
267
|
- ace.subido@gmail.com
|
@@ -207,15 +277,23 @@ files:
|
|
207
277
|
- app/assets/stylesheets/stellar_base/application.css
|
208
278
|
- app/concepts/stellar_base/application_contract.rb
|
209
279
|
- app/concepts/stellar_base/application_operation.rb
|
210
|
-
- app/concepts/stellar_base/bridge_callbacks/
|
211
|
-
- app/concepts/stellar_base/bridge_callbacks/
|
280
|
+
- app/concepts/stellar_base/bridge_callbacks/bridge_callback_policy.rb
|
281
|
+
- app/concepts/stellar_base/bridge_callbacks/contracts/create.rb
|
282
|
+
- app/concepts/stellar_base/bridge_callbacks/operations/create.rb
|
283
|
+
- app/concepts/stellar_base/withdrawal_requests/contracts/create.rb
|
284
|
+
- app/concepts/stellar_base/withdrawal_requests/operations/create.rb
|
285
|
+
- app/concepts/stellar_base/withdrawal_requests/withdrawal_request_policy.rb
|
212
286
|
- app/controllers/stellar_base/application_controller.rb
|
213
287
|
- app/controllers/stellar_base/bridge_callbacks_controller.rb
|
288
|
+
- app/controllers/stellar_base/withdraw_controller.rb
|
214
289
|
- app/helpers/stellar_base/application_helper.rb
|
215
290
|
- app/jobs/stellar_base/application_job.rb
|
216
291
|
- app/mailers/stellar_base/application_mailer.rb
|
217
292
|
- app/models/stellar_base/application_record.rb
|
218
293
|
- app/models/stellar_base/bridge_callback.rb
|
294
|
+
- app/models/stellar_base/withdrawal_request.rb
|
295
|
+
- app/representers/application_representer.rb
|
296
|
+
- app/representers/withdrawal_request_representer.rb
|
219
297
|
- app/services/stellar_base/bridge_callbacks/check.rb
|
220
298
|
- app/services/stellar_base/bridge_callbacks/compare.rb
|
221
299
|
- app/services/stellar_base/bridge_callbacks/get_operation.rb
|
@@ -228,11 +306,25 @@ files:
|
|
228
306
|
- app/services/stellar_base/bridge_callbacks/mac_payloads/encode_params.rb
|
229
307
|
- app/services/stellar_base/bridge_callbacks/process.rb
|
230
308
|
- app/services/stellar_base/bridge_callbacks/verify_mac_payload.rb
|
309
|
+
- app/services/stellar_base/gen_random_string.rb
|
310
|
+
- app/services/stellar_base/withdrawal_requests/call_on_withdraw.rb
|
311
|
+
- app/services/stellar_base/withdrawal_requests/determine_fee.rb
|
312
|
+
- app/services/stellar_base/withdrawal_requests/find_withdrawal_request.rb
|
313
|
+
- app/services/stellar_base/withdrawal_requests/gen_memo.rb
|
314
|
+
- app/services/stellar_base/withdrawal_requests/process.rb
|
315
|
+
- app/twins/application_twin.rb
|
316
|
+
- app/twins/withdrawal_request_twin.rb
|
231
317
|
- app/views/layouts/stellar_base/application.html.erb
|
232
318
|
- config/routes.rb
|
319
|
+
- db/migrate/20180816014433_create_stellar_base_bridge_callbacks.rb
|
320
|
+
- db/migrate/20180816110314_create_stellar_base_withdrawal_requests.rb
|
321
|
+
- db/migrate/20180816135847_unique_stellar_base_bridge_callbacks_operation_id.rb
|
233
322
|
- lib/stellar_base-rails.rb
|
234
323
|
- lib/stellar_base.rb
|
235
324
|
- lib/stellar_base/engine.rb
|
325
|
+
- lib/stellar_base/factories.rb
|
326
|
+
- lib/stellar_base/factories/bridge_callbacks.rb
|
327
|
+
- lib/stellar_base/factories/withdrawal_requests.rb
|
236
328
|
- lib/stellar_base/horizon_client.rb
|
237
329
|
- lib/stellar_base/version.rb
|
238
330
|
- lib/tasks/stellar_base_tasks.rake
|
@@ -256,7 +348,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
256
348
|
version: '0'
|
257
349
|
requirements: []
|
258
350
|
rubyforge_project:
|
259
|
-
rubygems_version: 2.7.
|
351
|
+
rubygems_version: 2.7.7
|
260
352
|
signing_key:
|
261
353
|
specification_version: 4
|
262
354
|
summary: Mountable Stellar API Endpoints for Rails
|
@@ -1,21 +0,0 @@
|
|
1
|
-
module StellarBase
|
2
|
-
module BridgeCallbacks
|
3
|
-
module Operations
|
4
|
-
class Process < ApplicationOperation
|
5
|
-
step :model!
|
6
|
-
step Contract::Build(constant: Contracts::Process)
|
7
|
-
step Contract::Validate(key: :bridge_callback)
|
8
|
-
step Contract::Persist(method: :sync)
|
9
|
-
step :process!
|
10
|
-
|
11
|
-
def model!(options, **)
|
12
|
-
options["model"] = BridgeCallback.new
|
13
|
-
end
|
14
|
-
|
15
|
-
def process!(options, **)
|
16
|
-
BridgeCallbacks::Process.(options["model"])
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|