"+a),this.timeline.info({state:a,params:b}),this.emit("state_change",{previous:c,current:a}),this.emit(a,b))};c.shouldRetry=function(){return"connecting"===
104 | this.state||"connected"===this.state};Pusher.ConnectionManager=b}).call(this);
105 | (function(){function b(){Pusher.EventsDispatcher.call(this);var b=this;void 0!==window.addEventListener&&(window.addEventListener("online",function(){b.emit("online")},!1),window.addEventListener("offline",function(){b.emit("offline")},!1))}Pusher.Util.extend(b.prototype,Pusher.EventsDispatcher.prototype);b.prototype.isOnline=function(){return void 0===window.navigator.onLine?!0:window.navigator.onLine};Pusher.NetInfo=b;Pusher.Network=new b}).call(this);
106 | (function(){function b(){this.reset()}var c=b.prototype;c.get=function(a){return Object.prototype.hasOwnProperty.call(this.members,a)?{id:a,info:this.members[a]}:null};c.each=function(a){var b=this;Pusher.Util.objectApply(b.members,function(c,f){a(b.get(f))})};c.setMyID=function(a){this.myID=a};c.onSubscription=function(a){this.members=a.presence.hash;this.count=a.presence.count;this.me=this.get(this.myID)};c.addMember=function(a){null===this.get(a.user_id)&&this.count++;this.members[a.user_id]=a.user_info;
107 | return this.get(a.user_id)};c.removeMember=function(a){var b=this.get(a.user_id);b&&(delete this.members[a.user_id],this.count--);return b};c.reset=function(){this.members={};this.count=0;this.me=this.myID=null};Pusher.Members=b}).call(this);
108 | (function(){function b(a,b){Pusher.EventsDispatcher.call(this,function(b,c){Pusher.debug("No callbacks on "+a+" for "+b)});this.name=a;this.pusher=b;this.subscribed=!1}var c=b.prototype;Pusher.Util.extend(c,Pusher.EventsDispatcher.prototype);c.authorize=function(a,b){return b(!1,{})};c.trigger=function(a,b){if(0!==a.indexOf("client-"))throw new Pusher.Errors.BadEventName("Event '"+a+"' does not start with 'client-'");return this.pusher.send_event(a,b,this.name)};c.disconnect=function(){this.subscribed=
109 | !1};c.handleEvent=function(a,b){0===a.indexOf("pusher_internal:")?"pusher_internal:subscription_succeeded"===a&&(this.subscribed=!0,this.emit("pusher:subscription_succeeded",b)):this.emit(a,b)};c.subscribe=function(){var a=this;a.authorize(a.pusher.connection.socket_id,function(b,c){b?a.handleEvent("pusher:subscription_error",c):a.pusher.send_event("pusher:subscribe",{auth:c.auth,channel_data:c.channel_data,channel:a.name})})};c.unsubscribe=function(){this.pusher.send_event("pusher:unsubscribe",{channel:this.name})};
110 | Pusher.Channel=b}).call(this);(function(){function b(a,b){Pusher.Channel.call(this,a,b)}var c=b.prototype;Pusher.Util.extend(c,Pusher.Channel.prototype);c.authorize=function(a,b){return(new Pusher.Channel.Authorizer(this,this.pusher.config)).authorize(a,b)};Pusher.PrivateChannel=b}).call(this);
111 | (function(){function b(a,b){Pusher.PrivateChannel.call(this,a,b);this.members=new Pusher.Members}var c=b.prototype;Pusher.Util.extend(c,Pusher.PrivateChannel.prototype);c.authorize=function(a,b){var c=this;Pusher.PrivateChannel.prototype.authorize.call(c,a,function(a,e){if(!a){if(void 0===e.channel_data){Pusher.warn("Invalid auth response for channel '"+c.name+"', expected 'channel_data' field");b("Invalid auth response");return}var g=JSON.parse(e.channel_data);c.members.setMyID(g.user_id)}b(a,e)})};
112 | c.handleEvent=function(a,b){switch(a){case "pusher_internal:subscription_succeeded":this.members.onSubscription(b);this.subscribed=!0;this.emit("pusher:subscription_succeeded",this.members);break;case "pusher_internal:member_added":var c=this.members.addMember(b);this.emit("pusher:member_added",c);break;case "pusher_internal:member_removed":(c=this.members.removeMember(b))&&this.emit("pusher:member_removed",c);break;default:Pusher.PrivateChannel.prototype.handleEvent.call(this,a,b)}};c.disconnect=
113 | function(){this.members.reset();Pusher.PrivateChannel.prototype.disconnect.call(this)};Pusher.PresenceChannel=b}).call(this);
114 | (function(){function b(){this.channels={}}var c=b.prototype;c.add=function(a,b){if(!this.channels[a]){var c=this.channels,f;f=0===a.indexOf("private-")?new Pusher.PrivateChannel(a,b):0===a.indexOf("presence-")?new Pusher.PresenceChannel(a,b):new Pusher.Channel(a,b);c[a]=f}return this.channels[a]};c.all=function(a){return Pusher.Util.values(this.channels)};c.find=function(a){return this.channels[a]};c.remove=function(a){var b=this.channels[a];delete this.channels[a];return b};c.disconnect=function(){Pusher.Util.objectApply(this.channels,
115 | function(a){a.disconnect()})};Pusher.Channels=b}).call(this);
116 | (function(){Pusher.Channel.Authorizer=function(b,a){this.channel=b;this.type=a.authTransport;this.options=a;this.authOptions=(a||{}).auth||{}};Pusher.Channel.Authorizer.prototype={composeQuery:function(b){b="socket_id="+encodeURIComponent(b)+"&channel_name="+encodeURIComponent(this.channel.name);for(var a in this.authOptions.params)b+="&"+encodeURIComponent(a)+"="+encodeURIComponent(this.authOptions.params[a]);return b},authorize:function(b,a){return Pusher.authorizers[this.type].call(this,b,a)}};
117 | var b=1;Pusher.auth_callbacks={};Pusher.authorizers={ajax:function(b,a){var d;d=Pusher.XHR?new Pusher.XHR:window.XMLHttpRequest?new window.XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP");d.open("POST",this.options.authEndpoint,!0);d.setRequestHeader("Content-Type","application/x-www-form-urlencoded");for(var h in this.authOptions.headers)d.setRequestHeader(h,this.authOptions.headers[h]);d.onreadystatechange=function(){if(4===d.readyState)if(200===d.status){var b,c=!1;try{b=JSON.parse(d.responseText),
118 | c=!0}catch(g){a(!0,"JSON returned from webapp was invalid, yet status code was 200. Data was: "+d.responseText)}c&&a(!1,b)}else Pusher.warn("Couldn't get auth info from your webapp",d.status),a(!0,d.status)};d.send(this.composeQuery(b));return d},jsonp:function(c,a){void 0!==this.authOptions.headers&&Pusher.warn("Warn","To send headers with the auth request, you must use AJAX, rather than JSONP.");var d=b.toString();b++;var h=Pusher.Util.getDocument(),f=h.createElement("script");Pusher.auth_callbacks[d]=
119 | function(b){a(!1,b)};f.src=this.options.authEndpoint+"?callback="+encodeURIComponent("Pusher.auth_callbacks['"+d+"']")+"&"+this.composeQuery(c);d=h.getElementsByTagName("head")[0]||h.documentElement;d.insertBefore(f,d.firstChild)}}}).call(this);
--------------------------------------------------------------------------------
/app/assets/stylesheets/application.css.scss:
--------------------------------------------------------------------------------
1 | /*
2 | * This is a manifest file that'll be compiled into application.css, which will include all the files
3 | * listed below.
4 | *
5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6 | * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7 | *
8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9 | * compiled file so the styles you add here take precedence over styles defined in any styles
10 | * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11 | * file per style scope.
12 | *
13 | *= require ./framework_and_overrides.css.scss
14 | *= require bootstrap-material-design
15 | *= require_self
16 | */
17 |
18 | a.qr-code {
19 |
20 | font-size: 11px;
21 | }
22 |
23 | table.qr-code {
24 | border-width: 0;
25 | border-style: none;
26 | border-color: #0000ff;
27 | border-collapse: collapse;
28 | margin: 20px;
29 | width: auto;
30 | border: none;
31 | border-radius: none;
32 | -webkit-border-radius: none;
33 | }
34 |
35 | table.qr-code td {
36 | border-width: 0;
37 | border-style: none;
38 | border-color: #0000ff;
39 | border-collapse: collapse;
40 | padding: 0;
41 | margin: 0;
42 | width: 10px;
43 | height: 10px;
44 | border-radius: none;
45 | -webkit-border-radius: none;
46 | }
47 |
48 | table.qr-code td.black {
49 | background-color: #000;
50 | }
51 |
52 | table.qr-code td.white {
53 | background-color: #fff;
54 | }
55 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/framework_and_overrides.css.scss:
--------------------------------------------------------------------------------
1 | // import the CSS framework
2 | @import "bootstrap-sprockets";
3 | @import "bootstrap";
4 |
5 | // apply styles to HTML elements
6 | // to make views framework-neutral
7 | main {
8 | @extend .container;
9 | padding-bottom: 80px;
10 | width: 100%;
11 | margin-top: 75px; // accommodate the navbar
12 | }
13 | section {
14 | @extend .row;
15 | margin-top: 20px;
16 | }
17 |
18 | // Styles for form views
19 | // using Bootstrap
20 | // generated by the rails_layout gem
21 | .authform {
22 | padding-top: 30px;
23 | max-width: 320px;
24 | margin: 0 auto;
25 | }
26 | .authform form {
27 | padding-bottom: 40px;
28 | }
29 | .authform .right {
30 | float: right !important;
31 | }
32 | .authform .button {
33 | @extend .btn;
34 | @extend .btn-primary;
35 | }
36 | #error_explanation h2 {
37 | font-size: 16px;
38 | }
39 | .button-xs {
40 | @extend .btn;
41 | @extend .btn-primary;
42 | @extend .btn-xs;
43 | }
44 |
--------------------------------------------------------------------------------
/app/controllers/application_controller.rb:
--------------------------------------------------------------------------------
1 | class ApplicationController < ActionController::Base
2 | # Prevent CSRF attacks by raising an exception.
3 | # For APIs, you may want to use :null_session instead.
4 | protect_from_forgery with: :exception
5 | before_action :are_we_configured, :except => [:configure]
6 |
7 | protected
8 |
9 | def are_we_configured
10 | if Figaro.env.master_public_keys == nil
11 | redirect_to configuration_path
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/app/controllers/bets_controller.rb:
--------------------------------------------------------------------------------
1 | class BetsController < ApplicationController
2 |
3 | skip_before_action :authenticate_user_from_token!, only: :show
4 |
5 | def show
6 | @bet = Bet.find(params[:id])
7 |
8 | render layout: false
9 | end
10 |
11 | def create
12 | bet = current_user.bets.build(bet_attributes)
13 | bet.secret = Secret.last || Secret.create
14 | bet.server_seed = session[:server_seed]
15 |
16 | if bet.amount < 0
17 | bet.amount = 0
18 | end
19 |
20 | # Set limit to 1 BTC (100,000,000 satoshis).
21 | # Set limit to 0.2 BTC
22 | limit = 20000000
23 | if ENV['limit'] != nil
24 | limit = ENV['limit'].to_i
25 | end
26 |
27 | # We need to put a thread lock around this to stop timing attacks.
28 | if bet.amount <= current_user.balance and bet.amount < limit
29 |
30 | bet.save
31 |
32 | if ENV['PUSHER_URL'] != nil or ENV['pusher_url'] != nil
33 | Pusher['test_channel'].trigger('my_event', bet.as_json)
34 | end
35 | end
36 |
37 | respond_to do |format|
38 | format.html { redirect_to root_url }
39 | format.json { render json: bet.to_json }
40 | end
41 | end
42 |
43 | protected
44 |
45 | def bet_attributes
46 | params.require(:bet).permit(:client_seed, :amount, :game, :rolltype)
47 | end
48 |
49 | end
--------------------------------------------------------------------------------
/app/controllers/cashouts_controller.rb:
--------------------------------------------------------------------------------
1 | class CashoutsController < ApplicationController
2 |
3 | before_action :authenticate_user_from_token!, only: :show
4 |
5 | def create
6 |
7 |
8 | cashout = current_user.cashouts.build(cashout_attributes)
9 |
10 | # We deal in statoshis.
11 | cashout.amount = current_user.balance - ((cashout.amount * 100000000).to_i)
12 | # Take off miners fee.
13 | cashout.amount = cashout.amount - 10000
14 |
15 | if cashout.amount > 0 and Bitcoin::valid_address?(cashout.address)
16 |
17 | cashout.save
18 |
19 | bal = Balance.new
20 | bal.user_id = current_user.id
21 | bal.transaction_hash = "Cashout to " + cashout.address
22 | bal.amount = 0 - cashout.amount
23 | bal.save
24 |
25 | end
26 |
27 | respond_to do |format|
28 | format.html { redirect_to root_url }
29 | format.json { render json: co.to_json }
30 | end
31 | end
32 |
33 | protected
34 |
35 | def cashout_attributes
36 | params.require(:cashout).permit(:address, :amount)
37 | end
38 | end
--------------------------------------------------------------------------------
/app/controllers/concerns/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bitsino/BitsinoDice/ab7040438fac437b6b146e208f0813dd97c09690/app/controllers/concerns/.keep
--------------------------------------------------------------------------------
/app/controllers/visitors_controller.rb:
--------------------------------------------------------------------------------
1 | class VisitorsController < ApplicationController
2 |
3 | def index
4 | session[:server_seed] = SecureRandom.hex(12)
5 |
6 | respond_to do |format|
7 | format.html do
8 | @bet = Bet.new.tap do |b|
9 | b.server_seed = session[:server_seed]
10 | b.amount = 0
11 | b.game = 49.5
12 | end
13 |
14 | @cashout = Cashout.new
15 |
16 | @transactions = []
17 |
18 | @bets = Bet.latest_bets
19 | @data_slider_range = "0,0"
20 |
21 | if current_user
22 |
23 | setup_transactions
24 |
25 | make_sure_user_address_is_set
26 |
27 | last_bet = current_user.bets.last
28 | if last_bet != nil and last_bet.amount < current_user.balance
29 | @bet.amount = last_bet.amount
30 | @bet.game = last_bet.game
31 | end
32 |
33 | @data_slider_range = "0," + current_user.balance.to_s
34 |
35 | @qr = RQRCode::QRCode.new(current_user.bitcoin_address)
36 | end
37 | end
38 | format.json do
39 | attrs = { server_seed: session[:server_seed] }
40 | attrs.merge!(auth_token: current_user.auth_token) if current_user
41 |
42 | render json: attrs
43 | end
44 | end
45 | end
46 |
47 | def bet_table
48 |
49 | respond_to do |format|
50 | format.html do
51 | @bets = Bet.latest_bets
52 | render :layout => false
53 | end
54 | end
55 | end
56 |
57 | def make_sure_user_address_is_set
58 | if current_user.bitcoin_address == nil
59 | keys = ColdStorage.get_extended_keys
60 | current_user.bitcoin_address = OnChain::Sweeper.multi_sig_address_from_mpks(
61 | keys.length, keys, "m/#{current_user.id}")
62 | current_user.save
63 | end
64 | end
65 |
66 | def setup_transactions
67 |
68 | balances = current_user.balances.all
69 |
70 | @transactions = []
71 |
72 | balances.each do |balance|
73 | if ! balance.transaction_hash.start_with? "Bet"
74 | if ! balance.transaction_hash.start_with? "Cashout"
75 | tx = {}
76 | tx[:amount] = balance.amount / 100000000.0
77 | tx[:address] = "Deposit"
78 | tx[:status] = "Processed"
79 | tx[:date] = balance.created_at
80 | @transactions << tx
81 | else
82 | tx = {}
83 | tx[:amount] = balance.amount / 100000000.0
84 | tx[:address] = balance.transaction_hash
85 | tx[:status] = "Awaiting Signoff"
86 | tx[:date] = balance.created_at
87 | @transactions << tx
88 | end
89 | end
90 | end
91 | end
92 |
93 | # We get here if our ENV vars are not set.
94 | def configure
95 | end
96 |
97 | end
98 |
--------------------------------------------------------------------------------
/app/helpers/application_helper.rb:
--------------------------------------------------------------------------------
1 | module ApplicationHelper
2 | end
3 |
--------------------------------------------------------------------------------
/app/mailers/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bitsino/BitsinoDice/ab7040438fac437b6b146e208f0813dd97c09690/app/mailers/.keep
--------------------------------------------------------------------------------
/app/models/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bitsino/BitsinoDice/ab7040438fac437b6b146e208f0813dd97c09690/app/models/.keep
--------------------------------------------------------------------------------
/app/models/balance.rb:
--------------------------------------------------------------------------------
1 | class Balance < ActiveRecord::Base
2 | end
3 |
--------------------------------------------------------------------------------
/app/models/bet.rb:
--------------------------------------------------------------------------------
1 | class Bet < ActiveRecord::Base
2 | include ActionView::Helpers::DateHelper
3 |
4 | belongs_to :user
5 | belongs_to :secret
6 |
7 | before_create :calculate_roll
8 | after_create :update_balance
9 |
10 | def as_json(options = {})
11 | {
12 | id: id,
13 | username: user.try(:name) || 'Guest',
14 | amount: amount_formatted,
15 | multiplier: multiplier.round(2),
16 | game: game,
17 | rolltype: rolltype == 'under' ? '<' : '>',
18 | roll: roll.round(2),
19 | profit: profit_formatted,
20 | win_or_lose: win? ? 'win' : 'lose',
21 | created_at: time_ago_in_words(created_at) + ' ago',
22 | }
23 | end
24 |
25 | def multiplier
26 | return (99 / game)
27 | end
28 |
29 | def profit
30 | if win?
31 | return ((amount.to_d * (multiplier).to_d) - amount.to_d).to_i
32 | else
33 | return -amount
34 | end
35 | end
36 |
37 | def win?
38 | if rolltype == 'under'
39 | roll < game
40 | else
41 | roll > game
42 | end
43 | end
44 |
45 | def self.latest_bets
46 | bets = Bet.order('created_at DESC').limit(25)
47 | end
48 |
49 | def profit_formatted
50 | return format_btc(profit)
51 | end
52 |
53 | def amount_formatted
54 | return format_btc(amount)
55 | end
56 |
57 | def format_btc(amount)
58 | if amount < 10000
59 | return "%.8f" % (amount / 100000000.0)
60 | end
61 | return amount / 100000000.0
62 | end
63 |
64 | protected
65 |
66 | def calculate_roll
67 |
68 | # Combine all the secrets.
69 | str = [secret.secret, server_seed, client_seed].join
70 |
71 | # Generate a hexadecimal hash.
72 | hash = Digest::SHA512.hexdigest(str)
73 |
74 | # Generate a number between 0 and 9999 inclusive.
75 | one_and_ten_thousand = hash.hex % 10000
76 |
77 | # Conver it to a 2 decimal point number between 0 and 99.99
78 | self.roll = one_and_ten_thousand / 100.0
79 | end
80 |
81 | def update_balance
82 | return if user.nil?
83 |
84 | b = user.balances.new
85 | b.transaction_hash = "Bet #{id}"
86 |
87 | if win?
88 | b.amount = profit
89 | else
90 | b.amount = (- amount)
91 | end
92 |
93 | if b.amount != 0
94 | b.save
95 | end
96 | end
97 |
98 | def make_payment
99 | return if user.nil?
100 |
101 | if win?
102 | Cashout.perform(ENV['PKEY'], user.address, profit.in_satoshi)
103 | else
104 | Cashout.perform(user.pkey ENV['FEE_ADDRESS'], amount.in_satoshi)
105 | end
106 | end
107 |
108 | end
109 |
--------------------------------------------------------------------------------
/app/models/cashout.rb:
--------------------------------------------------------------------------------
1 | class Cashout < ActiveRecord::Base
2 |
3 | def self.create_onchain_payment_request
4 |
5 | # Collect all the payouts inyo an array of address,amount
6 | cashouts = Cashout.where('status is null')
7 | payees = cashouts.map { |c| [c.address, c.amount] }
8 |
9 |
10 | # No one to pay out to ?
11 | if payees.count == 0
12 | return
13 | end
14 |
15 | total = Cashout.all.inject(0){|sum,c| sum += c.amount }
16 |
17 | puts "Paying out " + total.to_s
18 |
19 | # Get the redmption script for our fund
20 | rs = ColdStorage.redemption_script
21 |
22 | # Create a transaction for the lucky winners :)
23 | # or unlucky for us. :(
24 | tx = OnChain::Payments.create_payment_tx(rs, payees)
25 |
26 | # Did we get an error back ?
27 | if tx.is_a? String
28 | puts tx
29 | else
30 | # Update the cashout status
31 | cashouts.each do |cashout|
32 | cashout.status = true
33 | cashout.save
34 | end
35 |
36 | # Forward the TX to onchain for signing.
37 | tx_hex = OnChain.bin_to_hex(tx.to_payload)
38 | OnChain::Sweeper.post_tx_for_signing(tx_hex, [], ColdStorage.get_fund_address)
39 | end
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/app/models/cold_storage.rb:
--------------------------------------------------------------------------------
1 | class ColdStorage < ActiveRecord::Base
2 |
3 | self.table_name = 'cold_storage'
4 | def self.get_addresses
5 | mpks = Figaro.env.master_public_keys.split(",")
6 |
7 | addresses = []
8 | mpks.each do |mpk|
9 | master = MoneyTree::Node.from_serialized_address(mpk)
10 | addresses << master.public_key.to_hex
11 | end
12 | return addresses
13 | end
14 |
15 | def self.get_fund_address
16 | return OnChain::Sweeper.generate_address_of_redemption_script(redemption_script)
17 | end
18 |
19 | def self.get_extended_keys
20 | return Figaro.env.master_public_keys.split(",")
21 | end
22 |
23 | def self.redemption_script
24 | addresses = get_addresses
25 | return OnChain::Sweeper.generate_redemption_script(addresses.length, addresses)
26 | end
27 | end
--------------------------------------------------------------------------------
/app/models/concerns/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bitsino/BitsinoDice/ab7040438fac437b6b146e208f0813dd97c09690/app/models/concerns/.keep
--------------------------------------------------------------------------------
/app/models/secret.rb:
--------------------------------------------------------------------------------
1 | class Secret < ActiveRecord::Base
2 |
3 | belongs_to :bet
4 |
5 | before_create :generate_secret
6 |
7 | def to_s
8 | created_at < 24.hours.ago ? secret : '************************************'
9 | end
10 |
11 | protected
12 |
13 | def generate_secret
14 | self.secret = SecureRandom.hex(64)
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/app/models/transaction.rb:
--------------------------------------------------------------------------------
1 | class Transaction < ActiveRecord::Base
2 | end
3 |
--------------------------------------------------------------------------------
/app/models/user.rb:
--------------------------------------------------------------------------------
1 | class User < ActiveRecord::Base
2 |
3 | # Include default devise modules. Others available are:
4 | # :confirmable, :lockable, :timeoutable and :omniauthable
5 | devise :database_authenticatable, :registerable,
6 | :recoverable, :rememberable, :trackable, :validatable
7 |
8 | has_many :bets
9 | has_many :transactions
10 | has_many :cashouts
11 | has_many :balances
12 |
13 | def balance
14 | bal = 0
15 | balances.each{ |balance| bal = bal + balance.amount }
16 | return bal
17 | end
18 |
19 | def balance_as_btc
20 | (balance / 100000000.0)
21 | end
22 |
23 | def self.get_cold_storage
24 | cs = ColdStorage.first
25 | if cs == nil
26 | cs = ColdStorage.create
27 | cs.save
28 | end
29 | return cs
30 | end
31 |
32 | def self.sweep_for_incoming_coins
33 |
34 | block = get_cold_storage.block
35 | if block == nil
36 | block = 0
37 | end
38 | count = User.count
39 | keys = ColdStorage.get_extended_keys
40 |
41 | puts "Sweeping #{count} users starting from block #{block}"
42 | incoming, block_end = OnChain::Sweeper.sweep(keys.count, keys, 'm/#{index}', count, block)
43 |
44 | ActiveRecord::Base.transaction do
45 | incoming.each do |coins|
46 | u = User.find_by_bitcoin_address(coins[0])
47 |
48 | bal = u.balances.new
49 | bal.transaction_hash = coins[3]
50 | bal.amount = coins[2].to_i
51 | bal.save
52 | end
53 | cs = ColdStorage.first
54 | cs.block = block_end
55 | cs.save
56 | end
57 | end
58 |
59 | def self.sweep_bitcoins_to_onchain_fund
60 |
61 | block = get_cold_storage.sweep_block
62 | if block == nil
63 | block = 0
64 | end
65 | count = User.count
66 | keys = ColdStorage.get_extended_keys
67 |
68 | puts "Sweeping #{count} users starting from block #{block}"
69 | incoming, block_end = OnChain::Sweeper.sweep(keys.length, keys, 'm/#{index}', count, block)
70 |
71 | cs = ColdStorage.first
72 | cs.sweep_block = block_end
73 | cs.save
74 |
75 | tx, paths = OnChain::Sweeper.create_payment_tx_from_sweep(keys.length, incoming, ColdStorage.get_fund_address, keys)
76 |
77 | puts ENV['ONCHAIN_EMAIL']
78 |
79 | if tx != 'Not enough coins to create a transaction.'
80 |
81 | OnChain::Sweeper.post_tx_for_signing(tx, paths, ColdStorage.get_fund_address)
82 |
83 | return true
84 | end
85 | return false
86 | end
87 | end
88 |
--------------------------------------------------------------------------------
/app/services/create_admin_service.rb:
--------------------------------------------------------------------------------
1 | class CreateAdminService
2 | def call
3 | user = User.find_or_create_by!(email: Rails.application.secrets.admin_email) do |user|
4 | user.password = Rails.application.secrets.admin_password
5 | user.password_confirmation = Rails.application.secrets.admin_password
6 | end
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/app/views/bets/show.html.haml:
--------------------------------------------------------------------------------
1 |
2 | %dl
3 | %dt Bet Id
4 | %dd
5 | %input.form-control{:type => "text", :value => @bet.id.to_s, :readonly => "true"}
6 | %dt Server Seed
7 | %dd
8 | %input.form-control{:type => "text", :value => @bet.server_seed, :readonly => "true"}
9 | %dt Client Seed
10 | %dd
11 | %input.form-control{:type => "text", :value => @bet.client_seed, :readonly => "true"}
12 | %dt Secret Seed (Revealed after 24 hours.)
13 | %dd
14 | %textarea.form-control{:type => "text", :readonly => "true"}
15 | = @bet.secret.to_s
16 |
--------------------------------------------------------------------------------
/app/views/devise/passwords/edit.html.erb:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/app/views/devise/passwords/new.html.erb:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/app/views/devise/registrations/edit.html.erb:
--------------------------------------------------------------------------------
1 |
37 |
42 |
--------------------------------------------------------------------------------
/app/views/devise/registrations/new.html.erb:
--------------------------------------------------------------------------------
1 |
24 |
--------------------------------------------------------------------------------
/app/views/devise/sessions/new.html.erb:
--------------------------------------------------------------------------------
1 |
29 |
--------------------------------------------------------------------------------
/app/views/layouts/_messages.html.haml:
--------------------------------------------------------------------------------
1 | -# Rails flash messages styled for Bootstrap 3.0
2 | - flash.each do |name, msg|
3 | - if msg.is_a?(String)
4 | %input.snackbar{ type: 'hidden', value: msg }
5 |
6 | :javascript
7 | $( document ).ready(function() {
8 | $('.snackbar').each(function(i, obj) {
9 | $.snackbar({content: $(this).val(), timeout: 3000});
10 | });
11 | });
--------------------------------------------------------------------------------
/app/views/layouts/_navigation.html.haml:
--------------------------------------------------------------------------------
1 | -# navigation styled for Bootstrap 3.0
2 | %nav.navbar.navbar-default.navbar-fixed-top
3 | .container
4 | .navbar-header
5 | %button.navbar-toggle{"data-target" => ".navbar-collapse", "data-toggle" => "collapse", :type => "button"}
6 | %span.sr-only Toggle navigation
7 | %span.icon-bar
8 | %span.icon-bar
9 | %span.icon-bar
10 | %a{ href: root_path, class: 'navbar-brand' }
11 | %i.mdi-action-swap-vert-circle
12 | Bitsino Dice
13 | .collapse.navbar-collapse
14 | %ul.nav.navbar-nav
15 | = render 'layouts/navigation_links'
16 |
--------------------------------------------------------------------------------
/app/views/layouts/_navigation_links.html.erb:
--------------------------------------------------------------------------------
1 | <%# add navigation links to this file %>
2 | <% if user_signed_in? %>
3 | <%= link_to 'Edit account', edit_user_registration_path %>
4 | <%= link_to 'Sign out', destroy_user_session_path, :method=>'delete' %>
5 | <% else %>
6 | <%= link_to 'Sign in', new_user_session_path %>
7 | <%= link_to 'Sign up', new_user_registration_path %>
8 | <% end %>
9 |
--------------------------------------------------------------------------------
/app/views/layouts/application.html.haml:
--------------------------------------------------------------------------------
1 | !!!
2 | %html
3 | %head
4 | %meta{:name => "viewport", :content => "width=device-width, initial-scale=1.0"}
5 | %title= content_for?(:title) ? yield(:title) : 'Bitsino Dice - Provably fair Bitcoin dice game.'
6 | %meta{:name => "description", :content => "#{content_for?(:description) ? yield(:description) : 'Bitcoinary'}"}
7 | = stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true
8 | = javascript_include_tag 'application', 'data-turbolinks-track' => true
9 | = csrf_meta_tags
10 | = favicon_link_tag 'favicon.ico'
11 | %body
12 | %header
13 | = render 'layouts/navigation'
14 | %main{:role => "main"}
15 | = render 'layouts/messages'
16 | = yield
17 |
18 | -if Figaro.env.ga != nil
19 | %script
20 | = raw 'var GA = "' + Figaro.env.ga + '"'
21 | :javascript
22 | (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
23 | (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
24 | m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
25 | })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
26 |
27 | ga('create', GA, 'auto');
28 | ga('send', 'pageview');
29 |
--------------------------------------------------------------------------------
/app/views/visitors/_bets_table_rows.html.haml:
--------------------------------------------------------------------------------
1 | - @bets.each do |bet|
2 | - begin
3 | %tr
4 | %td.text-primary
5 | = link_to bet.id.to_s, bet_url(bet), { onclick: 'showVerification("' + bet.id.to_s + '"); return false' }
6 | %td
7 | = bet.user.name
8 | %td
9 | = time_ago_in_words(bet.created_at)
10 | ago.
11 | %td
12 | = bet.amount_formatted
13 | %td
14 | = bet.multiplier.round(2)
15 | %td
16 | - if bet.rolltype == 'under'
17 | <
18 | - else
19 | >
20 | = bet.game
21 | %td
22 | = bet.roll
23 | %td
24 | - if bet.win? or bet.amount == 0
25 | %span.label.label-success
26 | = bet.profit_formatted
27 | - else
28 | %span.label.label-default
29 | = bet.profit_formatted
30 | - rescue => e
31 | - puts e
--------------------------------------------------------------------------------
/app/views/visitors/_cashout_modal.html.haml:
--------------------------------------------------------------------------------
1 | #cashoutModal.modal.fade
2 | .modal-dialog
3 | .modal-content
4 | .modal-header
5 | %button.close{"data-dismiss" => "modal", :type => "button"}
6 | %span.aria-hidden
7 | ×
8 | %span.sr-only
9 | Close
10 | %h4.modal-title Cashout
11 | %p Please note a fee of 0.0005 BTC will be taken from your balance.
12 | .modal-body
13 | = form_for(@cashout, html: { role: 'form', class: 'inline-form', id: 'cashoutForm' }) do |f|
14 | .row
15 | .col-md-12
16 | %label Address
17 |
18 | = f.text_field :address, class: 'form-control', id: 'address'
19 | .col-md-12
20 | %label Amount
21 | = f.text_field :amount, class: 'form-control', id: 'amount'
22 | .col-md-12
23 | %input.btn.btn-primary#cashout-button{:style => "margin-top: 10px", :type => "submit", :value => "Cashout"}/
--------------------------------------------------------------------------------
/app/views/visitors/_deposit_modal.html.haml:
--------------------------------------------------------------------------------
1 | #depositModal.modal.fade
2 | .modal-dialog
3 | .modal-content
4 | .modal-header
5 | %button.close{"data-dismiss" => "modal", :type => "button"}
6 | %span.aria-hidden
7 | ×
8 | %span.sr-only
9 | Close
10 | %h4.modal-title Deposit
11 | .modal-body
12 | %p.center-block Please send funds to:
13 | %h3.center-block
14 | - if current_user != nil
15 | = current_user.bitcoin_address
16 | %table.qr-code
17 | - @qr.modules.each_index do |x|
18 | %tr
19 | - @qr.modules.each_index do |y|
20 | %td{:class => (@qr.dark?(x,y) ? 'black' : 'white')}
--------------------------------------------------------------------------------
/app/views/visitors/_transaction_history_modal.html.haml:
--------------------------------------------------------------------------------
1 | #transactionModal.modal.fade
2 | .modal-dialog
3 | .modal-content
4 | .modal-header
5 | %button.close{"data-dismiss" => "modal", :type => "button"}
6 | %span.aria-hidden
7 | ×
8 | %span.sr-only
9 | Close
10 | %h4.modal-title Transaction History
11 | .modal-body
12 | %table.table.table-striped
13 | %thead
14 | %tr
15 | %th Amount
16 | %th Type
17 | %th Status
18 | %th Date
19 | %tbody#transaction-history
20 | - @transactions.each do |tx|
21 | %tr
22 | %td
23 | = tx[:amount]
24 | %td
25 | = tx[:address]
26 | %td
27 | = tx[:status]
28 | %td
29 | = time_ago_in_words(tx[:date]) + ' ago.'
--------------------------------------------------------------------------------
/app/views/visitors/_verification_modal.html.haml:
--------------------------------------------------------------------------------
1 | #verificationModal.modal.fade{"aria-hidden" => "true", "aria-labelledby" => "myModalLabel", :role => "dialog", :tabindex => "-1"}
2 | .modal-dialog
3 | .modal-content
4 | .modal-header
5 | %button.close{"aria-hidden" => "true", "data-dismiss" => "modal", :type => "button"} ×
6 | %h4.modal-title Provably Fair
7 | .modal-body
8 | #verCont
9 | .modal-footer
10 | %button.btn.btn-default{"data-dismiss" => "modal", :type => "button"} Close
11 |
12 | :javascript
13 | function showVerification(id) {
14 | var url = '/bets/' + id;
15 |
16 | $( "#verCont" ).load( url );
17 | $('#verificationModal').modal();
18 | }
--------------------------------------------------------------------------------
/app/views/visitors/bet_table.html.haml:
--------------------------------------------------------------------------------
1 | = render :partial => "bets_table_rows"
--------------------------------------------------------------------------------
/app/views/visitors/configure.html.haml:
--------------------------------------------------------------------------------
1 | .container
2 | .row
3 | %h3
4 | Secure Cold Storage Installation
5 | %p
6 | To configure
7 | we need to connect to the ONCHAIN.IO cold storage service. ONCHAIN.IO provides multi signature
8 | funds to secure yours and your users money.
9 | %p
10 | Create or log into your account on ONCHAIN.IO and complete the following steps.
11 | %ol
12 | %li
13 | Go to the funds menu and create a new fund.
14 | %li
15 | Add up to 10 people to the fund. People in the fund will have the ability to sign transactions.
16 | %li
17 | Click the send invites button.
18 | %li
19 | Wait until all your invitees have accepted the invitations and added their public keys to the
20 | fund.
21 | %li
22 | You need to create an environment variable called 'master_public_keys' and set this to the value of each public key. Comma separated.
23 |
24 | %textarea.form-control
25 | master_public_keys=xpub69GZWTQPtwQRriHyYuYJpDgAUrHHRD8ksBbQ61QpY1CbSUrcW7udYcZ1YLuLVtSQx9xW5QApiGidDfmFVLEz4Lep3AoCGD2HQmfvXwH1GMt,xpub69GZWTQPtwQRriHyYuYJpDgAUrHHRD8ksBbQ61QpY1CbSUrcW7udYcZ1YLuLVtSQx9xW5QApiGidDfmFVLEz4Lep3AoCGD2HQmfvXwH1GMt
26 |
27 |
--------------------------------------------------------------------------------
/app/views/visitors/index.html.haml:
--------------------------------------------------------------------------------
1 | .container
2 | .row{ :style => 'margin-bottom: 40px' }
3 | .col-md-12.text-center
4 | - if current_user == nil
5 | %h1
6 | Provably Fair Bitcoin Gambling
7 | %h2
8 | Register to try BitsinoDice out for free
9 | .row
10 | .col-md-3
11 | #userDetails
12 | %dl
13 | %dt Name
14 | %dd
15 | %input#username.form-control{:type => "text", :value => current_user.try(:name), :readonly => "true"}
16 | %dt User Id
17 | %dd
18 | %input#userid.form-control{:type => "text", :value => current_user.try(:id), :readonly => "true" }
19 |
20 | #seeds
21 | %dl
22 | %dt Server Seed
23 | %dd
24 | %input#server-seed.form-control{:readonly => "true", :type => "text", :value => session[:server_seed]}
25 | %dt Client Seed
26 | %dd
27 | %input#client-seed.form-control{:type => "text"}/
28 | .col-md-6.well
29 | = form_for(@bet, html: { role: 'form', class: 'inline-form submit-once', id: 'betForm' }) do |f|
30 | .row
31 | .col-md-12
32 | %label Probability of winning
33 | %div#probability-slider.slider{ style: 'width: 100%' }
34 | %input#start-prob{ type: 'hidden', value: @bet.game }
35 | .row{ style: 'margin-top:20px' }
36 | .col-md-12
37 | %label Amount of Bet.
38 | %div#amount-slider.slider{ style: 'width: 100%' }
39 | %input#range{ type: 'hidden', value: @data_slider_range}
40 | = f.hidden_field :amount, id: 'amount-hidden'
41 | .row{ style: 'margin-top:20px' }
42 | .col-md-3
43 | .form-group
44 | %label Roll Under
45 | = f.text_field :game, class: 'form-control', readonly: true, value: '49.50', id: 'roll-prob'
46 | = f.hidden_field :rolltype
47 | = f.hidden_field :client_seed, id: 'client-seed-form'
48 | .col-md-3
49 | %label For a profit of
50 | %input#bet_profit.form-control{:readonly => "true", :type => "text", :value => "0"}/
51 | .col-md-3
52 | %label With probability
53 | %input#bet_chance.form-control{:readonly => "true", :type => "text", :value => "49.50%"}/
54 | .col-md-3
55 | %label Amount of Bet
56 | %input{ type: 'text', class: 'form-control input-small', readonly: "true", id: 'amount-view', placeholder: 'Amount', value: '0' }
57 | .form-group{:style => "margin-top: 10px"}
58 | - if current_user == nil
59 | = f.submit 'Roll Dice', class: 'btn btn-block btn-info disabled', id: 'roll-button'
60 | - else
61 | = f.submit 'Roll Dice', class: 'btn btn-block btn-info btn-raised', id: 'roll-button'
62 | .col-md-3.btc-options
63 | .row
64 | .col-md-12
65 | %label BTC Balance
66 | - if current_user != nil
67 | %input#balance.form-control{:type => "text",
68 | :value => number_to_human(current_user.balance_as_btc, precision: 8, strip_insignificant_zeros: true),
69 | :readonly => "true", "data-address" => "#{current_user.try(:address)}"}
70 | - else
71 | %input#balance.form-control{:type => "text", :value => '0', :readonly => "true"}
72 | .row{ style: 'margin-top:10px' }
73 | .col-md-12
74 | - if current_user == nil
75 | %button.btn.btn-primary.disabled.btn-block
76 | %i.mdi-action-account-balance-wallet
77 | Deposit
78 | - else
79 | %button.btn.btn-primary.btn-block{"data-target" => "#depositModal", "data-toggle" => "modal"}
80 | %i.mdi-action-account-balance-wallet
81 | Deposit
82 | .row{ style: 'margin-top:10px' }
83 | .col-md-12
84 | - if current_user == nil
85 | %button.btn.btn-primary.disabled.btn-block
86 | %i.mdi-action-account-balance
87 | Cashout
88 | - else
89 | %button.btn.btn-primary.btn-block{"data-target" => "#cashoutModal", "data-toggle" => "modal"}
90 | %i.mdi-action-account-balance
91 | Cashout
92 |
93 | .row{ style: 'margin-top:10px' }
94 | .col-md-12
95 | - if current_user == nil
96 | %button.btn.btn-primary.disabled.btn-block
97 | %i.mdi-action-receipt
98 | Transaction History
99 | - else
100 | %button.btn.btn-primary.btn-block#transButton{"data-target" => "#transactionModal", "data-toggle" => "modal"}
101 | %i.mdi-action-receipt
102 | Transaction History
103 | .container
104 | .row
105 | .col-md-12
106 | %table.table.table-striped
107 | %thead
108 | %tr
109 | %th Bet ID
110 | %th User
111 | %th Time
112 | %th Bet
113 | %th Payout
114 | %th Game
115 | %th Roll
116 | %th Profit
117 | %tbody#bets
118 | = render :partial => "bets_table_rows"
119 |
120 | = render :partial => "deposit_modal"
121 |
122 | = render :partial => "cashout_modal"
123 |
124 | = render :partial => "transaction_history_modal"
125 |
126 | = render :partial => "verification_modal"
--------------------------------------------------------------------------------
/bin/bundle:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
3 | load Gem.bin_path('bundler', 'bundle')
4 |
--------------------------------------------------------------------------------
/bin/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | begin
3 | load File.expand_path("../spring", __FILE__)
4 | rescue LoadError
5 | end
6 | APP_PATH = File.expand_path('../../config/application', __FILE__)
7 | require_relative '../config/boot'
8 | require 'rails/commands'
9 |
--------------------------------------------------------------------------------
/bin/rake:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | begin
3 | load File.expand_path("../spring", __FILE__)
4 | rescue LoadError
5 | end
6 | require_relative '../config/boot'
7 | require 'rake'
8 | Rake.application.run
9 |
--------------------------------------------------------------------------------
/bin/spring:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | # This file loads spring without using Bundler, in order to be fast
4 | # It gets overwritten when you run the `spring binstub` command
5 |
6 | unless defined?(Spring)
7 | require "rubygems"
8 | require "bundler"
9 |
10 | if match = Bundler.default_lockfile.read.match(/^GEM$.*?^ spring \((.*?)\)$.*?^$/m)
11 | ENV["GEM_PATH"] = ([Bundler.bundle_path.to_s] + Gem.path).join(File::PATH_SEPARATOR)
12 | ENV["GEM_HOME"] = ""
13 | Gem.paths = ENV
14 |
15 | gem "spring", match[1]
16 | require "spring/binstub"
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/config.ru:
--------------------------------------------------------------------------------
1 | # This file is used by Rack-based servers to start the application.
2 |
3 | require ::File.expand_path('../config/environment', __FILE__)
4 | run Rails.application
5 |
--------------------------------------------------------------------------------
/config/application.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path('../boot', __FILE__)
2 |
3 | require 'rails/all'
4 |
5 | # Require the gems listed in Gemfile, including any gems
6 | # you've limited to :test, :development, or :production.
7 | Bundler.require(*Rails.groups)
8 |
9 | module Bitcoinary
10 | class Application < Rails::Application
11 |
12 | config.generators do |g|
13 | g.test_framework :rspec,
14 | fixtures: true,
15 | view_specs: false,
16 | helper_specs: false,
17 | routing_specs: false,
18 | controller_specs: false,
19 | request_specs: false
20 | g.fixture_replacement :factory_girl, dir: "spec/factories"
21 | end
22 |
23 | # Settings in config/environments/* take precedence over those specified here.
24 | # Application configuration should go into files in config/initializers
25 | # -- all .rb files in that directory are automatically loaded.
26 |
27 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
28 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
29 | # config.time_zone = 'Central Time (US & Canada)'
30 |
31 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
32 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
33 | # config.i18n.default_locale = :de
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/config/boot.rb:
--------------------------------------------------------------------------------
1 | # Set up gems listed in the Gemfile.
2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
3 |
4 | require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
5 |
--------------------------------------------------------------------------------
/config/database.yml:
--------------------------------------------------------------------------------
1 | # SQLite version 3.x
2 | # gem install sqlite3
3 | #
4 | # Ensure the SQLite 3 gem is defined in your Gemfile
5 | # gem 'sqlite3'
6 | #
7 | default: &default
8 | adapter: sqlite3
9 | pool: 5
10 | timeout: 5000
11 |
12 | development:
13 | <<: *default
14 | database: db/development.sqlite3
15 |
16 | # Warning: The database defined as "test" will be erased and
17 | # re-generated from your development database when you run "rake".
18 | # Do not set this db to the same as development or production.
19 | test:
20 | <<: *default
21 | database: db/test.sqlite3
22 |
23 | production:
24 | <<: *default
25 | database: db/production.sqlite3
26 |
--------------------------------------------------------------------------------
/config/environment.rb:
--------------------------------------------------------------------------------
1 | # Load the Rails application.
2 | require File.expand_path('../application', __FILE__)
3 |
4 | # Initialize the Rails application.
5 | Rails.application.initialize!
6 |
--------------------------------------------------------------------------------
/config/environments/development.rb:
--------------------------------------------------------------------------------
1 | Rails.application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb.
3 |
4 | # In the development environment your application's code is reloaded on
5 | # every request. This slows down response time but is perfect for development
6 | # since you don't have to restart the web server when you make code changes.
7 | config.cache_classes = false
8 |
9 | # Do not eager load code on boot.
10 | config.eager_load = false
11 |
12 | # Show full error reports and disable caching.
13 | config.consider_all_requests_local = true
14 | config.action_controller.perform_caching = false
15 |
16 | # Don't care if the mailer can't send.
17 | config.action_mailer.raise_delivery_errors = false
18 |
19 | # Print deprecation notices to the Rails logger.
20 | config.active_support.deprecation = :log
21 |
22 | # Raise an error on page load if there are pending migrations.
23 | config.active_record.migration_error = :page_load
24 |
25 | # Debug mode disables concatenation and preprocessing of assets.
26 | # This option may cause significant delays in view rendering with a large
27 | # number of complex assets.
28 | config.assets.debug = true
29 |
30 | config.action_mailer.smtp_settings = {
31 | address: "smtp.sendgrid.net",
32 | port: 587,
33 | domain: Rails.application.secrets.domain_name,
34 | authentication: "plain",
35 | enable_starttls_auto: true,
36 | user_name: Rails.application.secrets.email_provider_username,
37 | password: Rails.application.secrets.email_provider_password
38 | }
39 | # ActionMailer Config
40 | config.action_mailer.default_url_options = { :host => 'localhost:3000' }
41 | config.action_mailer.delivery_method = :smtp
42 | config.action_mailer.raise_delivery_errors = true
43 | # Send email in development mode?
44 | config.action_mailer.perform_deliveries = true
45 |
46 |
47 | # Adds additional error checking when serving assets at runtime.
48 | # Checks for improperly declared sprockets dependencies.
49 | # Raises helpful error messages.
50 | config.assets.raise_runtime_errors = true
51 |
52 | # Raises error for missing translations
53 | # config.action_view.raise_on_missing_translations = true
54 | end
55 |
--------------------------------------------------------------------------------
/config/environments/production.rb:
--------------------------------------------------------------------------------
1 | Rails.application.configure do
2 |
3 | # Settings specified here will take precedence over those in config/application.rb.
4 |
5 | # Code is not reloaded between requests.
6 | config.cache_classes = true
7 |
8 | # Eager load code on boot. This eager loads most of Rails and
9 | # your application in memory, allowing both threaded web servers
10 | # and those relying on copy on write to perform better.
11 | # Rake tasks automatically ignore this option for performance.
12 | config.eager_load = true
13 |
14 | # Full error reports are disabled and caching is turned on.
15 | config.consider_all_requests_local = false
16 | config.action_controller.perform_caching = true
17 |
18 | # Enable Rack::Cache to put a simple HTTP cache in front of your application
19 | # Add `rack-cache` to your Gemfile before enabling this.
20 | # For large-scale production use, consider using a caching reverse proxy like nginx, varnish or squid.
21 | # config.action_dispatch.rack_cache = true
22 |
23 | # Disable Rails's static asset server (Apache or nginx will already do this).
24 | config.serve_static_assets = false
25 |
26 | # Compress JavaScripts and CSS.
27 | config.assets.js_compressor = :uglifier
28 | # config.assets.css_compressor = :sass
29 |
30 | # Do not fallback to assets pipeline if a precompiled asset is missed.
31 | config.assets.compile = false
32 |
33 | # Generate digests for assets URLs.
34 | config.assets.digest = true
35 |
36 | # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
37 |
38 | # Specifies the header that your server uses for sending files.
39 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
40 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
41 |
42 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
43 | # config.force_ssl = true
44 |
45 | # Set to :debug to see everything in the log.
46 | config.log_level = :info
47 |
48 | # Prepend all log lines with the following tags.
49 | # config.log_tags = [ :subdomain, :uuid ]
50 |
51 | # Use a different logger for distributed setups.
52 | # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
53 |
54 | # Use a different cache store in production.
55 | # config.cache_store = :mem_cache_store
56 |
57 | # Enable serving of images, stylesheets, and JavaScripts from an asset server.
58 | # config.action_controller.asset_host = "http://assets.example.com"
59 |
60 | # Ignore bad email addresses and do not raise email delivery errors.
61 | # Set this to true and configure the email server for immediate delivery to raise delivery errors.
62 | # config.action_mailer.raise_delivery_errors = false
63 |
64 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
65 | # the I18n.default_locale when a translation cannot be found).
66 | config.i18n.fallbacks = true
67 |
68 | # Send deprecation notices to registered listeners.
69 | config.active_support.deprecation = :notify
70 |
71 | config.action_mailer.smtp_settings = {
72 | address: "smtp.sendgrid.net",
73 | port: 587,
74 | domain: Rails.application.secrets.domain_name,
75 | authentication: "plain",
76 | enable_starttls_auto: true,
77 | user_name: Rails.application.secrets.email_provider_username,
78 | password: Rails.application.secrets.email_provider_password
79 | }
80 | # ActionMailer Config
81 | config.action_mailer.default_url_options = { :host => Rails.application.secrets.domain_name }
82 | config.action_mailer.delivery_method = :smtp
83 | config.action_mailer.perform_deliveries = true
84 | config.action_mailer.raise_delivery_errors = false
85 |
86 |
87 | # Disable automatic flushing of the log to improve performance.
88 | # config.autoflush_log = false
89 |
90 | # Use default logging formatter so that PID and timestamp are not suppressed.
91 | config.log_formatter = ::Logger::Formatter.new
92 |
93 | # Do not dump schema after migrations.
94 | config.active_record.dump_schema_after_migration = false
95 | end
96 |
--------------------------------------------------------------------------------
/config/environments/test.rb:
--------------------------------------------------------------------------------
1 | Rails.application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb.
3 |
4 | # The test environment is used exclusively to run your application's
5 | # test suite. You never need to work with it otherwise. Remember that
6 | # your test database is "scratch space" for the test suite and is wiped
7 | # and recreated between test runs. Don't rely on the data there!
8 | config.cache_classes = true
9 |
10 | # Do not eager load code on boot. This avoids loading your whole application
11 | # just for the purpose of running a single test. If you are using a tool that
12 | # preloads Rails for running tests, you may have to set it to true.
13 | config.eager_load = false
14 |
15 | # Configure static asset server for tests with Cache-Control for performance.
16 | config.serve_static_assets = true
17 | config.static_cache_control = 'public, max-age=3600'
18 |
19 | # Show full error reports and disable caching.
20 | config.consider_all_requests_local = true
21 | config.action_controller.perform_caching = false
22 |
23 | # Raise exceptions instead of rendering exception templates.
24 | config.action_dispatch.show_exceptions = false
25 |
26 | # Disable request forgery protection in test environment.
27 | config.action_controller.allow_forgery_protection = false
28 |
29 | # Tell Action Mailer not to deliver emails to the real world.
30 | # The :test delivery method accumulates sent emails in the
31 | # ActionMailer::Base.deliveries array.
32 | config.action_mailer.delivery_method = :test
33 |
34 | # Print deprecation notices to the stderr.
35 | config.active_support.deprecation = :stderr
36 |
37 | # Raises error for missing translations
38 | # config.action_view.raise_on_missing_translations = true
39 | end
40 |
--------------------------------------------------------------------------------
/config/initializers/assets.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Version of your assets, change this if you want to expire all your assets.
4 | Rails.application.config.assets.version = '1.0'
5 |
6 | # Precompile additional assets.
7 | # application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
8 | # Rails.application.config.assets.precompile += %w( search.js )
9 |
--------------------------------------------------------------------------------
/config/initializers/backtrace_silencers.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
5 |
6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
7 | # Rails.backtrace_cleaner.remove_silencers!
8 |
--------------------------------------------------------------------------------
/config/initializers/cookies_serializer.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | Rails.application.config.action_dispatch.cookies_serializer = :json
--------------------------------------------------------------------------------
/config/initializers/devise.rb:
--------------------------------------------------------------------------------
1 | # Use this hook to configure devise mailer, warden hooks and so forth.
2 | # Many of these configuration options can be set straight in your model.
3 | Devise.setup do |config|
4 | # The secret key used by Devise. Devise uses this key to generate
5 | # random tokens. Changing this key will render invalid all existing
6 | # confirmation, reset password and unlock tokens in the database.
7 | # config.secret_key = '2d43db95793eec39ee116b33dd9f6e0931046ca56dbb9a32554e7ef7783f65d2732b05ccd442afdaf40e3b6aad89dfaae26d3ebbb557ba4fcdb49e4a7a5eb10b'
8 |
9 | # ==> Mailer Configuration
10 | # Configure the e-mail address which will be shown in Devise::Mailer,
11 | # note that it will be overwritten if you use your own mailer class
12 | # with default "from" parameter.
13 | config.mailer_sender = 'no-reply@' + Rails.application.secrets.domain_name
14 |
15 | # Configure the class responsible to send e-mails.
16 | # config.mailer = 'Devise::Mailer'
17 |
18 | # ==> ORM configuration
19 | # Load and configure the ORM. Supports :active_record (default) and
20 | # :mongoid (bson_ext recommended) by default. Other ORMs may be
21 | # available as additional gems.
22 | require 'devise/orm/active_record'
23 |
24 | # ==> Configuration for any authentication mechanism
25 | # Configure which keys are used when authenticating a user. The default is
26 | # just :email. You can configure it to use [:username, :subdomain], so for
27 | # authenticating a user, both parameters are required. Remember that those
28 | # parameters are used only when authenticating and not when retrieving from
29 | # session. If you need permissions, you should implement that in a before filter.
30 | # You can also supply a hash where the value is a boolean determining whether
31 | # or not authentication should be aborted when the value is not present.
32 | # config.authentication_keys = [ :email ]
33 |
34 | # Configure parameters from the request object used for authentication. Each entry
35 | # given should be a request method and it will automatically be passed to the
36 | # find_for_authentication method and considered in your model lookup. For instance,
37 | # if you set :request_keys to [:subdomain], :subdomain will be used on authentication.
38 | # The same considerations mentioned for authentication_keys also apply to request_keys.
39 | # config.request_keys = []
40 |
41 | # Configure which authentication keys should be case-insensitive.
42 | # These keys will be downcased upon creating or modifying a user and when used
43 | # to authenticate or find a user. Default is :email.
44 | config.case_insensitive_keys = [ :email ]
45 |
46 | # Configure which authentication keys should have whitespace stripped.
47 | # These keys will have whitespace before and after removed upon creating or
48 | # modifying a user and when used to authenticate or find a user. Default is :email.
49 | config.strip_whitespace_keys = [ :email ]
50 |
51 | # Tell if authentication through request.params is enabled. True by default.
52 | # It can be set to an array that will enable params authentication only for the
53 | # given strategies, for example, `config.params_authenticatable = [:database]` will
54 | # enable it only for database (email + password) authentication.
55 | # config.params_authenticatable = true
56 |
57 | # Tell if authentication through HTTP Auth is enabled. False by default.
58 | # It can be set to an array that will enable http authentication only for the
59 | # given strategies, for example, `config.http_authenticatable = [:database]` will
60 | # enable it only for database authentication. The supported strategies are:
61 | # :database = Support basic authentication with authentication key + password
62 | # config.http_authenticatable = false
63 |
64 | # If 401 status code should be returned for AJAX requests. True by default.
65 | # config.http_authenticatable_on_xhr = true
66 |
67 | # The realm used in Http Basic Authentication. 'Application' by default.
68 | # config.http_authentication_realm = 'Application'
69 |
70 | # It will change confirmation, password recovery and other workflows
71 | # to behave the same regardless if the e-mail provided was right or wrong.
72 | # Does not affect registerable.
73 | # config.paranoid = true
74 |
75 | # By default Devise will store the user in session. You can skip storage for
76 | # particular strategies by setting this option.
77 | # Notice that if you are skipping storage for all authentication paths, you
78 | # may want to disable generating routes to Devise's sessions controller by
79 | # passing skip: :sessions to `devise_for` in your config/routes.rb
80 | config.skip_session_storage = [:http_auth]
81 |
82 | # By default, Devise cleans up the CSRF token on authentication to
83 | # avoid CSRF token fixation attacks. This means that, when using AJAX
84 | # requests for sign in and sign up, you need to get a new CSRF token
85 | # from the server. You can disable this option at your own risk.
86 | # config.clean_up_csrf_token_on_authentication = true
87 |
88 | # ==> Configuration for :database_authenticatable
89 | # For bcrypt, this is the cost for hashing the password and defaults to 10. If
90 | # using other encryptors, it sets how many times you want the password re-encrypted.
91 | #
92 | # Limiting the stretches to just one in testing will increase the performance of
93 | # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
94 | # a value less than 10 in other environments. Note that, for bcrypt (the default
95 | # encryptor), the cost increases exponentially with the number of stretches (e.g.
96 | # a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation).
97 | config.stretches = Rails.env.test? ? 1 : 10
98 |
99 | # Setup a pepper to generate the encrypted password.
100 | # config.pepper = 'be3a23290004d909d2ec1b51af20c90182f4a1754a88e6bbeb567287e1e2aaf564662857fc8ef6aeaa5c27da85af9851b3c14a92f3b398cae50aa91d55dc0f68'
101 |
102 | # ==> Configuration for :confirmable
103 | # A period that the user is allowed to access the website even without
104 | # confirming their account. For instance, if set to 2.days, the user will be
105 | # able to access the website for two days without confirming their account,
106 | # access will be blocked just in the third day. Default is 0.days, meaning
107 | # the user cannot access the website without confirming their account.
108 | # config.allow_unconfirmed_access_for = 2.days
109 |
110 | # A period that the user is allowed to confirm their account before their
111 | # token becomes invalid. For example, if set to 3.days, the user can confirm
112 | # their account within 3 days after the mail was sent, but on the fourth day
113 | # their account can't be confirmed with the token any more.
114 | # Default is nil, meaning there is no restriction on how long a user can take
115 | # before confirming their account.
116 | # config.confirm_within = 3.days
117 |
118 | # If true, requires any email changes to be confirmed (exactly the same way as
119 | # initial account confirmation) to be applied. Requires additional unconfirmed_email
120 | # db field (see migrations). Until confirmed, new email is stored in
121 | # unconfirmed_email column, and copied to email column on successful confirmation.
122 | config.reconfirmable = true
123 |
124 | # Defines which key will be used when confirming an account
125 | # config.confirmation_keys = [ :email ]
126 |
127 | # ==> Configuration for :rememberable
128 | # The time the user will be remembered without asking for credentials again.
129 | # config.remember_for = 2.weeks
130 |
131 | # Invalidates all the remember me tokens when the user signs out.
132 | config.expire_all_remember_me_on_sign_out = true
133 |
134 | # If true, extends the user's remember period when remembered via cookie.
135 | # config.extend_remember_period = false
136 |
137 | # Options to be passed to the created cookie. For instance, you can set
138 | # secure: true in order to force SSL only cookies.
139 | # config.rememberable_options = {}
140 |
141 | # ==> Configuration for :validatable
142 | # Range for password length.
143 | config.password_length = 8..128
144 |
145 | # Email regex used to validate email formats. It simply asserts that
146 | # one (and only one) @ exists in the given string. This is mainly
147 | # to give user feedback and not to assert the e-mail validity.
148 | # config.email_regexp = /\A[^@]+@[^@]+\z/
149 |
150 | # ==> Configuration for :timeoutable
151 | # The time you want to timeout the user session without activity. After this
152 | # time the user will be asked for credentials again. Default is 30 minutes.
153 | # config.timeout_in = 30.minutes
154 |
155 | # If true, expires auth token on session timeout.
156 | # config.expire_auth_token_on_timeout = false
157 |
158 | # ==> Configuration for :lockable
159 | # Defines which strategy will be used to lock an account.
160 | # :failed_attempts = Locks an account after a number of failed attempts to sign in.
161 | # :none = No lock strategy. You should handle locking by yourself.
162 | # config.lock_strategy = :failed_attempts
163 |
164 | # Defines which key will be used when locking and unlocking an account
165 | # config.unlock_keys = [ :email ]
166 |
167 | # Defines which strategy will be used to unlock an account.
168 | # :email = Sends an unlock link to the user email
169 | # :time = Re-enables login after a certain amount of time (see :unlock_in below)
170 | # :both = Enables both strategies
171 | # :none = No unlock strategy. You should handle unlocking by yourself.
172 | # config.unlock_strategy = :both
173 |
174 | # Number of authentication tries before locking an account if lock_strategy
175 | # is failed attempts.
176 | # config.maximum_attempts = 20
177 |
178 | # Time interval to unlock the account if :time is enabled as unlock_strategy.
179 | # config.unlock_in = 1.hour
180 |
181 | # Warn on the last attempt before the account is locked.
182 | # config.last_attempt_warning = true
183 |
184 | # ==> Configuration for :recoverable
185 | #
186 | # Defines which key will be used when recovering the password for an account
187 | # config.reset_password_keys = [ :email ]
188 |
189 | # Time interval you can reset your password with a reset password key.
190 | # Don't put a too small interval or your users won't have the time to
191 | # change their passwords.
192 | config.reset_password_within = 6.hours
193 |
194 | # ==> Configuration for :encryptable
195 | # Allow you to use another encryption algorithm besides bcrypt (default). You can use
196 | # :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1,
197 | # :authlogic_sha512 (then you should set stretches above to 20 for default behavior)
198 | # and :restful_authentication_sha1 (then you should set stretches to 10, and copy
199 | # REST_AUTH_SITE_KEY to pepper).
200 | #
201 | # Require the `devise-encryptable` gem when using anything other than bcrypt
202 | # config.encryptor = :sha512
203 |
204 | # ==> Scopes configuration
205 | # Turn scoped views on. Before rendering "sessions/new", it will first check for
206 | # "users/sessions/new". It's turned off by default because it's slower if you
207 | # are using only default views.
208 | # config.scoped_views = false
209 |
210 | # Configure the default scope given to Warden. By default it's the first
211 | # devise role declared in your routes (usually :user).
212 | # config.default_scope = :user
213 |
214 | # Set this configuration to false if you want /users/sign_out to sign out
215 | # only the current scope. By default, Devise signs out all scopes.
216 | # config.sign_out_all_scopes = true
217 |
218 | # ==> Navigation configuration
219 | # Lists the formats that should be treated as navigational. Formats like
220 | # :html, should redirect to the sign in page when the user does not have
221 | # access, but formats like :xml or :json, should return 401.
222 | #
223 | # If you have any extra navigational formats, like :iphone or :mobile, you
224 | # should add them to the navigational formats lists.
225 | #
226 | # The "*/*" below is required to match Internet Explorer requests.
227 | # config.navigational_formats = ['*/*', :html]
228 |
229 | # The default HTTP method used to sign out a resource. Default is :delete.
230 | config.sign_out_via = :delete
231 |
232 | # ==> OmniAuth
233 | # Add a new OmniAuth provider. Check the wiki for more information on setting
234 | # up on your models and hooks.
235 | # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
236 |
237 | # ==> Warden configuration
238 | # If you want to use other strategies, that are not supported by Devise, or
239 | # change the failure app, you can configure them inside the config.warden block.
240 | #
241 | # config.warden do |manager|
242 | # manager.intercept_401 = false
243 | # manager.default_strategies(scope: :user).unshift :some_external_strategy
244 | # end
245 |
246 | # ==> Mountable engine configurations
247 | # When using Devise inside an engine, let's call it `MyEngine`, and this engine
248 | # is mountable, there are some extra configurations to be taken into account.
249 | # The following options are available, assuming the engine is mounted as:
250 | #
251 | # mount MyEngine, at: '/my_engine'
252 | #
253 | # The router that invoked `devise_for`, in the example above, would be:
254 | # config.router_name = :my_engine
255 | #
256 | # When using omniauth, Devise cannot automatically set Omniauth path,
257 | # so you need to do it manually. For the users scope, it would be:
258 | # config.omniauth_path_prefix = '/my_engine/users/auth'
259 | end
260 |
--------------------------------------------------------------------------------
/config/initializers/devise_permitted_parameters.rb:
--------------------------------------------------------------------------------
1 | module DevisePermittedParameters
2 | extend ActiveSupport::Concern
3 |
4 | included do
5 | before_filter :configure_permitted_parameters
6 | end
7 |
8 | protected
9 |
10 | def configure_permitted_parameters
11 | devise_parameter_sanitizer.for(:sign_up) << :name
12 | devise_parameter_sanitizer.for(:account_update) << :name
13 | end
14 |
15 | end
16 |
17 | DeviseController.send :include, DevisePermittedParameters
18 |
--------------------------------------------------------------------------------
/config/initializers/filter_parameter_logging.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Configure sensitive parameters which will be filtered from the log file.
4 | Rails.application.config.filter_parameters += [:password, :password_confirmation]
5 |
--------------------------------------------------------------------------------
/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new inflection rules using the following format. Inflections
4 | # are locale specific, and you may define rules for as many different
5 | # locales as you wish. All of these examples are active by default:
6 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
7 | # inflect.plural /^(ox)$/i, '\1en'
8 | # inflect.singular /^(ox)en/i, '\1'
9 | # inflect.irregular 'person', 'people'
10 | # inflect.uncountable %w( fish sheep )
11 | # end
12 |
13 | # These inflection rules are supported but not enabled by default:
14 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
15 | # inflect.acronym 'RESTful'
16 | # end
17 |
--------------------------------------------------------------------------------
/config/initializers/mime_types.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new mime types for use in respond_to blocks:
4 | # Mime::Type.register "text/richtext", :rtf
5 |
--------------------------------------------------------------------------------
/config/initializers/pusher.rb:
--------------------------------------------------------------------------------
1 | require 'pusher'
2 |
3 | if ENV['PUSHER_URL'] != nil
4 | Pusher.url = ENV['PUSHER_URL']
5 | elsif ENV['pusher_url'] != nil
6 | Pusher.url = ENV['pusher_url']
7 | end
--------------------------------------------------------------------------------
/config/initializers/session_store.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | Rails.application.config.session_store :cookie_store, key: '_bitcoinary_session'
4 |
--------------------------------------------------------------------------------
/config/initializers/wrap_parameters.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # This file contains settings for ActionController::ParamsWrapper which
4 | # is enabled by default.
5 |
6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7 | ActiveSupport.on_load(:action_controller) do
8 | wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
9 | end
10 |
11 | # To enable root element in JSON for ActiveRecord objects.
12 | # ActiveSupport.on_load(:active_record) do
13 | # self.include_root_in_json = true
14 | # end
15 |
--------------------------------------------------------------------------------
/config/locales/devise.en.yml:
--------------------------------------------------------------------------------
1 | # Additional translations at https://github.com/plataformatec/devise/wiki/I18n
2 |
3 | en:
4 | devise:
5 | confirmations:
6 | confirmed: "Your email address has been successfully confirmed."
7 | send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
8 | send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
9 | failure:
10 | already_authenticated: "You are already signed in."
11 | inactive: "Your account is not activated yet."
12 | invalid: "Invalid %{authentication_keys} or password."
13 | locked: "Your account is locked."
14 | last_attempt: "You have one more attempt before your account is locked."
15 | not_found_in_database: "Invalid %{authentication_keys} or password."
16 | timeout: "Your session expired. Please sign in again to continue."
17 | unauthenticated: "You need to sign in or sign up before continuing."
18 | unconfirmed: "You have to confirm your email address before continuing."
19 | mailer:
20 | confirmation_instructions:
21 | subject: "Confirmation instructions"
22 | reset_password_instructions:
23 | subject: "Reset password instructions"
24 | unlock_instructions:
25 | subject: "Unlock instructions"
26 | omniauth_callbacks:
27 | failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
28 | success: "Successfully authenticated from %{kind} account."
29 | passwords:
30 | no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
31 | send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
32 | send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
33 | updated: "Your password has been changed successfully. You are now signed in."
34 | updated_not_active: "Your password has been changed successfully."
35 | registrations:
36 | destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
37 | signed_up: "Welcome! You have signed up successfully."
38 | signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
39 | signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
40 | signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
41 | update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address."
42 | updated: "Your account has been updated successfully."
43 | sessions:
44 | signed_in: "Signed in successfully."
45 | signed_out: "Signed out successfully."
46 | already_signed_out: "Signed out successfully."
47 | unlocks:
48 | send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
49 | send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
50 | unlocked: "Your account has been unlocked successfully. Please sign in to continue."
51 | errors:
52 | messages:
53 | already_confirmed: "was already confirmed, please try signing in"
54 | confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
55 | expired: "has expired, please request a new one"
56 | not_found: "not found"
57 | not_locked: "was not locked"
58 | not_saved:
59 | one: "1 error prohibited this %{resource} from being saved:"
60 | other: "%{count} errors prohibited this %{resource} from being saved:"
61 |
--------------------------------------------------------------------------------
/config/locales/en.yml:
--------------------------------------------------------------------------------
1 | # Files in the config/locales directory are used for internationalization
2 | # and are automatically loaded by Rails. If you want to use locales other
3 | # than English, add the necessary files in this directory.
4 | #
5 | # To use the locales, use `I18n.t`:
6 | #
7 | # I18n.t 'hello'
8 | #
9 | # In views, this is aliased to just `t`:
10 | #
11 | # <%= t('hello') %>
12 | #
13 | # To use a different locale, set it with `I18n.locale`:
14 | #
15 | # I18n.locale = :es
16 | #
17 | # This would use the information in config/locales/es.yml.
18 | #
19 | # To learn more, please read the Rails Internationalization guide
20 | # available at http://guides.rubyonrails.org/i18n.html.
21 |
22 | en:
23 | hello: "Hello world"
24 |
--------------------------------------------------------------------------------
/config/routes.rb:
--------------------------------------------------------------------------------
1 | Rails.application.routes.draw do
2 |
3 | root to: 'visitors#index'
4 | devise_for :users
5 | resources :users
6 |
7 |
8 | resources :bets, only: [ :show, :create ]
9 | resources :cashouts, only: [ :create ]
10 | resources :transactions, only: [ :index ]
11 |
12 | get 'configuration' => 'visitors#configure'
13 |
14 | get "/bet_table" => "visitors#bet_table"
15 | end
16 |
--------------------------------------------------------------------------------
/config/secrets.yml:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Your secret key is used for verifying the integrity of signed cookies.
4 | # If you change this key, all old signed cookies will become invalid!
5 |
6 | # Make sure the secret is at least 30 characters and all random,
7 | # no regular words or you'll be exposed to dictionary attacks.
8 | # You can use `rake secret` to generate a secure secret key.
9 |
10 | # Make sure the secrets in this file are kept private
11 | # if you're sharing your code publicly.
12 |
13 | development:
14 | admin_name: First User
15 | admin_email: user@example.com
16 | admin_password: changeme
17 | email_provider_username: <%= ENV["SENDGRID_USERNAME"] %>
18 | email_provider_password: <%= ENV["SENDGRID_PASSWORD"] %>
19 | domain_name: example.com
20 | secret_key_base: f29b840a8fbe99988d88dcb998949d2367446adba8e1a16009641e245aaf294533c3117ba752fe2428296ffed1a46d69e63b6aba7a44a5d71ceb45c96a4ebd2a
21 |
22 | test:
23 | domain_name: example.com
24 | secret_key_base: c14065c2e1bbdf17b507ba8f9ba4e83e96f7c9710a19e5e4813683aa4c8eb6284b078f798eed05508492671ccf0d93b29c46bfc99f2c60545ead185b2efe3ad8
25 |
26 | # Do not keep production secrets in the repository,
27 | # instead read values from the environment.
28 | production:
29 | admin_name: <%= ENV["ADMIN_NAME"] %>
30 | admin_email: <%= ENV["ADMIN_EMAIL"] %>
31 | admin_password: <%= ENV["ADMIN_PASSWORD"] %>
32 | email_provider_username: <%= ENV["SENDGRID_USERNAME"] %>
33 | email_provider_password: <%= ENV["SENDGRID_PASSWORD"] %>
34 | domain_name: <%= ENV["DOMAIN_NAME"] %>
35 | secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
36 |
--------------------------------------------------------------------------------
/db/migrate/20140115101221_create_bets.rb:
--------------------------------------------------------------------------------
1 | class CreateBets < ActiveRecord::Migration
2 | def change
3 | create_table :bets do |t|
4 | t.references :user
5 | t.references :secret
6 | t.decimal :amount, scale: 8, precision: 15
7 | t.decimal :multiplier, scale: 4, precision: 8
8 | t.decimal :game, scale: 2, precision: 4
9 | t.decimal :roll, scale: 2, precision: 4
10 | t.string :rolltype, default: 'under'
11 | t.string :client_seed
12 | t.string :server_seed
13 | t.timestamps
14 | end
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/db/migrate/20140116001104_create_secrets.rb:
--------------------------------------------------------------------------------
1 | class CreateSecrets < ActiveRecord::Migration
2 | def change
3 | create_table :secrets do |t|
4 | t.string :secret
5 | t.timestamps
6 | end
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/db/migrate/20140930085512_cold_storage.rb:
--------------------------------------------------------------------------------
1 | class ColdStorage < ActiveRecord::Migration
2 | def change
3 | create_table(:cold_storage) do |t|
4 | ## Database authenticatable
5 | t.string :mpk
6 | t.string :fund_address
7 | end
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20141002112057_create_cashouts.rb:
--------------------------------------------------------------------------------
1 | class CreateCashouts < ActiveRecord::Migration
2 | def change
3 | create_table :cashouts do |t|
4 | t.string :address
5 | t.integer :amount
6 | t.boolean :status
7 |
8 | t.timestamps
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20141009160404_create_transactions.rb:
--------------------------------------------------------------------------------
1 | class CreateTransactions < ActiveRecord::Migration
2 | def change
3 | create_table :transactions do |t|
4 | t.integer :user_id
5 | t.integer :amount
6 | t.string :type
7 | t.string :status
8 |
9 | t.timestamps
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/db/migrate/20141014133052_add_user_id_to_cashouts.rb:
--------------------------------------------------------------------------------
1 | class AddUserIdToCashouts < ActiveRecord::Migration
2 | def change
3 | add_column :cashouts, :user_id, :integer
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20141017133717_add_block_to_coldstore.rb:
--------------------------------------------------------------------------------
1 | class AddBlockToColdstore < ActiveRecord::Migration
2 | def change
3 | add_column :cold_storage, :block, :integer
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20141021062306_create_balances.rb:
--------------------------------------------------------------------------------
1 | class CreateBalances < ActiveRecord::Migration
2 | def change
3 | create_table :balances do |t|
4 | t.string :transaction_hash
5 | t.integer :amount
6 | t.integer :user_id
7 |
8 | t.timestamps
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20141022064014_add_sweep_block_to_cold_storage.rb:
--------------------------------------------------------------------------------
1 | class AddSweepBlockToColdStorage < ActiveRecord::Migration
2 | def change
3 | add_column :cold_storage, :sweep_block, :integer
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20141029123750_devise_create_users.rb:
--------------------------------------------------------------------------------
1 | class DeviseCreateUsers < ActiveRecord::Migration
2 | def change
3 | create_table(:users) do |t|
4 | ## Database authenticatable
5 | t.string :email, null: false, default: ""
6 | t.string :encrypted_password, null: false, default: ""
7 |
8 | ## Recoverable
9 | t.string :reset_password_token
10 | t.datetime :reset_password_sent_at
11 |
12 | ## Rememberable
13 | t.datetime :remember_created_at
14 |
15 | ## Trackable
16 | t.integer :sign_in_count, default: 0, null: false
17 | t.datetime :current_sign_in_at
18 | t.datetime :last_sign_in_at
19 | t.string :current_sign_in_ip
20 | t.string :last_sign_in_ip
21 |
22 | ## Confirmable
23 | # t.string :confirmation_token
24 | # t.datetime :confirmed_at
25 | # t.datetime :confirmation_sent_at
26 | # t.string :unconfirmed_email # Only if using reconfirmable
27 |
28 | ## Lockable
29 | # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
30 | # t.string :unlock_token # Only if unlock strategy is :email or :both
31 | # t.datetime :locked_at
32 |
33 |
34 | t.timestamps
35 | end
36 |
37 | add_index :users, :email, unique: true
38 | add_index :users, :reset_password_token, unique: true
39 | # add_index :users, :confirmation_token, unique: true
40 | # add_index :users, :unlock_token, unique: true
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/db/migrate/20141029123753_add_name_to_users.rb:
--------------------------------------------------------------------------------
1 | class AddNameToUsers < ActiveRecord::Migration
2 | def change
3 | add_column :users, :name, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20141029154512_add_bitcoin_address_to_user.rb:
--------------------------------------------------------------------------------
1 | class AddBitcoinAddressToUser < ActiveRecord::Migration
2 | def change
3 | add_column :users, :bitcoin_address, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20141029160455_remove_mpk_from_cold_storage.rb:
--------------------------------------------------------------------------------
1 | class RemoveMpkFromColdStorage < ActiveRecord::Migration
2 | def change
3 | remove_column :cold_storage, :mpk, :string
4 | remove_column :cold_storage, :fund_address, :string
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20141030135705_remove_multiplier_from_bets.rb:
--------------------------------------------------------------------------------
1 | class RemoveMultiplierFromBets < ActiveRecord::Migration
2 | def change
3 | remove_column :bets, :multiplier, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20141119122639_change_amount_to_integer.rb:
--------------------------------------------------------------------------------
1 | class ChangeAmountToInteger < ActiveRecord::Migration
2 | def change
3 | change_table :bets do |t|
4 | t.change :amount, :integer
5 | end
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/db/migrate/20141217121140_add_unique_constraint_to_server_seed.rb:
--------------------------------------------------------------------------------
1 | class AddUniqueConstraintToServerSeed < ActiveRecord::Migration
2 | def change
3 | add_index(:bets, :server_seed, :unique => true)
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/schema.rb:
--------------------------------------------------------------------------------
1 | # encoding: UTF-8
2 | # This file is auto-generated from the current state of the database. Instead
3 | # of editing this file, please use the migrations feature of Active Record to
4 | # incrementally modify your database, and then regenerate this schema definition.
5 | #
6 | # Note that this schema.rb definition is the authoritative source for your
7 | # database schema. If you need to create the application database on another
8 | # system, you should be using db:schema:load, not running all the migrations
9 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10 | # you'll amass, the slower it'll run and the greater likelihood for issues).
11 | #
12 | # It's strongly recommended that you check this file into your version control system.
13 |
14 | ActiveRecord::Schema.define(version: 20141217121140) do
15 |
16 | create_table "balances", force: true do |t|
17 | t.string "transaction_hash"
18 | t.integer "amount"
19 | t.integer "user_id"
20 | t.datetime "created_at"
21 | t.datetime "updated_at"
22 | end
23 |
24 | create_table "bets", force: true do |t|
25 | t.integer "user_id"
26 | t.integer "secret_id"
27 | t.integer "amount", limit: 15
28 | t.decimal "game", precision: 4, scale: 2
29 | t.decimal "roll", precision: 4, scale: 2
30 | t.string "rolltype", default: "under"
31 | t.string "client_seed"
32 | t.string "server_seed"
33 | t.datetime "created_at"
34 | t.datetime "updated_at"
35 | end
36 |
37 | add_index "bets", ["server_seed"], name: "index_bets_on_server_seed", unique: true
38 |
39 | create_table "cashouts", force: true do |t|
40 | t.string "address"
41 | t.integer "amount"
42 | t.boolean "status"
43 | t.datetime "created_at"
44 | t.datetime "updated_at"
45 | t.integer "user_id"
46 | end
47 |
48 | create_table "cold_storage", force: true do |t|
49 | t.integer "block"
50 | t.integer "sweep_block"
51 | end
52 |
53 | create_table "secrets", force: true do |t|
54 | t.string "secret"
55 | t.datetime "created_at"
56 | t.datetime "updated_at"
57 | end
58 |
59 | create_table "transactions", force: true do |t|
60 | t.integer "user_id"
61 | t.integer "amount"
62 | t.string "type"
63 | t.string "status"
64 | t.datetime "created_at"
65 | t.datetime "updated_at"
66 | end
67 |
68 | create_table "users", force: true do |t|
69 | t.string "email", default: "", null: false
70 | t.string "encrypted_password", default: "", null: false
71 | t.string "reset_password_token"
72 | t.datetime "reset_password_sent_at"
73 | t.datetime "remember_created_at"
74 | t.integer "sign_in_count", default: 0, null: false
75 | t.datetime "current_sign_in_at"
76 | t.datetime "last_sign_in_at"
77 | t.string "current_sign_in_ip"
78 | t.string "last_sign_in_ip"
79 | t.datetime "created_at"
80 | t.datetime "updated_at"
81 | t.string "name"
82 | t.string "bitcoin_address"
83 | end
84 |
85 | add_index "users", ["email"], name: "index_users_on_email", unique: true
86 | add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
87 |
88 | end
89 |
--------------------------------------------------------------------------------
/db/seeds.rb:
--------------------------------------------------------------------------------
1 | # This file should contain all the record creation needed to seed the database with its default values.
2 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
3 | #
4 | # Examples:
5 | #
6 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
7 | # Mayor.create(name: 'Emanuel', city: cities.first)
8 | user = CreateAdminService.new.call
9 | puts 'CREATED ADMIN USER: ' << user.email
10 |
--------------------------------------------------------------------------------
/lib/assets/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bitsino/BitsinoDice/ab7040438fac437b6b146e208f0813dd97c09690/lib/assets/.keep
--------------------------------------------------------------------------------
/lib/tasks/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bitsino/BitsinoDice/ab7040438fac437b6b146e208f0813dd97c09690/lib/tasks/.keep
--------------------------------------------------------------------------------
/lib/tasks/pirate_metrics.rake:
--------------------------------------------------------------------------------
1 | task :pirate_metrics => :environment do
2 |
3 | count = User.where("created_at >= ?", 1.day.ago).count
4 | bets = Bet.where("created_at >= ?", 1.day.ago).count
5 | btc = Balance.where('created_at < ? and length(transaction_hash) > ?', 24.hours.ago, 20).sum(:amount)
6 |
7 | if btc < 10000
8 | btc = "%.8f" % (btc / 100000000.0)
9 | end
10 | btc = btc / 100000000.0
11 |
12 | message = "User Registrations (last 24 hours) : #{count} "
13 | message += "
"
14 | message += "Bets made (last 24 hours) : #{bets} "
15 | message += "
"
16 | message += "BTC Deposited (last 24 hours) : #{btc} "
17 |
18 | uri = URI.parse("https://hall.com")
19 | http = Net::HTTP.new(uri.host, uri.port)
20 | http.use_ssl = true
21 | http.verify_mode = OpenSSL::SSL::VERIFY_NONE
22 | request = Net::HTTP::Post.new("/api/1/services/generic/550e2fabd234eda198cd0936e8799e63")
23 | request.add_field('Content-Type', 'application/json')
24 | request.body = {'title' => 'How are we doing ?', 'message' => message}.to_json
25 | response = http.request(request)
26 | end
--------------------------------------------------------------------------------
/lib/tasks/scheduler.rake:
--------------------------------------------------------------------------------
1 | desc "Generate new secret each day"
2 | task :generate_secret => :environment do
3 | Secret.create
4 | end
5 |
6 | desc "Sweep addresses on block chain"
7 | task :sweep_blockchain => :environment do
8 | User.sweep_for_incoming_coins
9 | end
10 |
11 | desc "Create payouts"
12 | task :create_payouts => :environment do
13 | Cashout.create_onchain_payment_request
14 | end
15 |
16 | desc "Sweep incoming coins to fund"
17 | task :sweep_tx => :environment do
18 | User.sweep_bitcoins_to_onchain_fund
19 | end
--------------------------------------------------------------------------------
/lib/tasks/simulator.rake:
--------------------------------------------------------------------------------
1 | task :simulate_heavy_user => :environment do
2 |
3 | u = User.find_by_email('ian.purton@gmail.com')
4 |
5 | while u.balance > 0 do
6 |
7 | r = rand * 100.0
8 | b = u.bets.new
9 | b.secret = Secret.last
10 | b.server_seed = SecureRandom.hex(12)
11 | b.amount = 10000
12 | b.game = 49.5
13 | b.client_seed = 'baebbde11f8bb328'
14 | b.save
15 |
16 | sleep 4
17 | end
18 | end
19 |
20 | task :simulate_gamblers_ruin, [:email] => :environment do |t, args|
21 |
22 | user_email = args[:email]
23 |
24 | u = User.find_by_email(user_email)
25 |
26 | LIMIT = 20000000
27 | GAMBLE = 10000
28 |
29 | profit = 0
30 |
31 | while u.balance > GAMBLE do
32 |
33 | win = false
34 | amount = GAMBLE
35 |
36 | while win == false and amount < u.balance and amount < LIMIT
37 | b = u.bets.new
38 | b.secret = Secret.last
39 | b.server_seed = SecureRandom.hex(12)
40 | b.amount = amount
41 | b.game = 49.5
42 | b.client_seed = 'baebbde11f8bb328'
43 | b.save
44 |
45 | Pusher['test_channel'].trigger('my_event', b.as_json)
46 |
47 | win = b.win?
48 |
49 | if !win
50 | amount = amount * 2
51 | else
52 | # We won, start again.
53 | puts "A win resetting amount, total we had to bet " + amount.to_s + " profit " + profit.to_s
54 | profit = profit + GAMBLE
55 | amount = GAMBLE
56 | Bet.where("client_seed = ? and created_at < ?", "baebbde11f8bb328", 3.minutes.ago).delete_all
57 | end
58 | sleep (rand 120)
59 | end
60 |
61 | end
62 |
63 | Bet.where("client_seed = ?", "baebbde11f8bb328").delete_all
64 | u.balances.where("amount < 100000000").delete_all
65 | end
--------------------------------------------------------------------------------
/log/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bitsino/BitsinoDice/ab7040438fac437b6b146e208f0813dd97c09690/log/.keep
--------------------------------------------------------------------------------
/public/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The page you were looking for doesn't exist (404)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
The page you were looking for doesn't exist.
62 |
You may have mistyped the address or the page may have moved.
63 |
64 |
If you are the application owner check the logs for more information.
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/public/422.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The change you wanted was rejected (422)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
The change you wanted was rejected.
62 |
Maybe you tried to change something you didn't have access to.
63 |
64 |
If you are the application owner check the logs for more information.
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/public/500.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | We're sorry, but something went wrong (500)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
We're sorry, but something went wrong.
62 |
63 |
If you are the application owner check the logs for more information.
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/public/humans.txt:
--------------------------------------------------------------------------------
1 | /* the humans responsible & colophon */
2 | /* humanstxt.org */
3 |
4 |
5 | /* TEAM */
6 | :
7 | Site:
8 | Twitter:
9 | Location:
10 |
11 | /* THANKS */
12 | Daniel Kehoe (@rails_apps) for the RailsApps project
13 |
14 | /* SITE */
15 | Standards: HTML5, CSS3
16 | Components: jQuery
17 | Software: Ruby on Rails
18 |
19 | /* GENERATED BY */
20 | Rails Composer: http://railscomposer.com/
21 |
--------------------------------------------------------------------------------
/public/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bitsino/BitsinoDice/ab7040438fac437b6b146e208f0813dd97c09690/public/images/favicon.ico
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
2 | #
3 | # To ban all spiders from the entire site uncomment the next two lines:
4 | # User-agent: *
5 | # Disallow: /
6 |
--------------------------------------------------------------------------------
/spec/factories/balances.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :balance do
3 | user_id 1
4 | amount 500000
5 | transaction_hash "dbb4fa1da1d6d53911c45b52d94d38507c3f27fa245a7e58bb2d7e6e7056ed72"
6 | end
7 |
8 | trait :big_spender do
9 | amount 500000000
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/spec/factories/users.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :user do
3 | name "Test User"
4 | email "test@example.com"
5 | password "please123"
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/spec/features/gambling/cashout_spec.rb:
--------------------------------------------------------------------------------
1 | include Warden::Test::Helpers
2 | Warden.test_mode!
3 |
4 | feature 'When cashing out.', :js => true do
5 |
6 | after(:each) do
7 | Warden.test_reset!
8 | end
9 |
10 | scenario 'does the data get saved' do
11 | user = FactoryGirl.create(:user)
12 | user = FactoryGirl.create(:balance)
13 | signin('test@example.com', 'please123')
14 |
15 | click_on 'Cashout'
16 |
17 | fill_in 'address', with: '38BqfF4LUgpbvoYbGpyYAw44qrpS841GA1'
18 | fill_in 'amount', with: '0.001'
19 |
20 | page.save_screenshot('tmp/screenshot.jpg')
21 |
22 | page.find('#cashout-button').click
23 |
24 | click_on 'Transaction History'
25 |
26 | end
27 |
28 | end
29 |
--------------------------------------------------------------------------------
/spec/features/gambling/limits_spec.rb:
--------------------------------------------------------------------------------
1 | include Warden::Test::Helpers
2 | Warden.test_mode!
3 |
4 | feature 'When hacking' do
5 |
6 | after(:each) do
7 | Warden.test_reset!
8 | end
9 |
10 | scenario 'can a user bet more than their balance.' do
11 | user = FactoryGirl.create(:user)
12 | user = FactoryGirl.create(:balance)
13 |
14 | signin('test@example.com', 'please123')
15 |
16 | find("#amount-hidden").set "1000000"
17 |
18 | page.find("#roll-button").click
19 |
20 | b = Bet.all
21 |
22 | expect(b.count).to eq(0)
23 | end
24 |
25 | scenario 'can a bet more than our limit.' do
26 | user = FactoryGirl.create(:user)
27 | user = FactoryGirl.create(:balance, :big_spender)
28 |
29 | signin('test@example.com', 'please123')
30 |
31 | # Bet above the limit
32 | find("#amount-hidden").set "200000000"
33 |
34 | page.find("#roll-button").click
35 |
36 | b = Bet.all
37 |
38 | expect(b.count).to eq(0)
39 |
40 | # Bet just below the limit
41 | find("#amount-hidden").set "9999999"
42 |
43 | page.find("#roll-button").click
44 |
45 | b = Bet.all
46 |
47 | expect(b.count).to eq(1)
48 | end
49 |
50 | end
51 |
--------------------------------------------------------------------------------
/spec/features/gambling/simple_gamble_spec.rb:
--------------------------------------------------------------------------------
1 | include Warden::Test::Helpers
2 | Warden.test_mode!
3 |
4 | feature 'When gambling', :js => true do
5 |
6 | after(:each) do
7 | Warden.test_reset!
8 | end
9 |
10 | scenario 'can the user sign in and roll the dice' do
11 | user = FactoryGirl.create(:user)
12 | signin('test@example.com', 'please123')
13 |
14 | expect(page.all('tbody#bets tr').count).to eq(0)
15 |
16 | page.find("#roll-button").click
17 |
18 | page.save_screenshot('tmp/screenshot.png')
19 |
20 | expect(page.all('tbody#bets tr').count).to eq(1)
21 |
22 | tr = page.find('tbody#bets tr')
23 |
24 | expect(tr.all('td')[0].text).to eq("1")
25 | expect(tr.all('td')[1].text).to eq("Test User")
26 | expect(tr.all('td')[2].text).to eq("less than a minute ago.")
27 | expect(tr.all('td')[3].text).to eq("0.00000000")
28 | expect(tr.all('td')[4].text).to eq("2.0")
29 | expect(tr.all('td')[5].text).to eq("< 49.5")
30 | expect(tr.all('td')[7].text).to eq("0.00000000")
31 | end
32 |
33 | scenario 'is the balance displaying correctly.' do
34 | user = FactoryGirl.create(:user)
35 | user = FactoryGirl.create(:balance)
36 | signin('test@example.com', 'please123')
37 |
38 | bal = page.find('#balance').value
39 |
40 | expect(bal).to eq('0.005')
41 | end
42 |
43 | scenario 'does the users balance increase or decrease with each bet' do
44 | user = FactoryGirl.create(:user)
45 | user = FactoryGirl.create(:balance)
46 | signin('test@example.com', 'please123')
47 |
48 | bal_before = page.find('#balance').value
49 |
50 | page.find("#roll-button").click
51 |
52 | bal_after = page.find('#balance').value
53 |
54 | expect(bal_before).to eq(bal_after)
55 |
56 | # OK let's slide the amount slider and see what happens
57 | page.execute_script("$('#amount-slider').val(20000);$('#amount-slider').change()")
58 |
59 | page.find("#roll-button").click
60 |
61 | bal_after = page.find('#balance').value
62 |
63 | expect(bal_before).to_not eq(bal_after)
64 | end
65 |
66 | scenario 'does the amount slider work.' do
67 |
68 | user = FactoryGirl.create(:user)
69 | user = FactoryGirl.create(:balance)
70 | signin('test@example.com', 'please123')
71 |
72 | page.execute_script("$('#amount-slider').val(10000);$('#amount-slider').change()")
73 |
74 | amount = page.find('#amount-view').value
75 |
76 | expect(amount).to eq("0.00010")
77 |
78 | button = page.find('#roll-button').value
79 |
80 | expect(button).to eq("Click for a 49.5% chance of multiplying your bet by 2.00")
81 |
82 | # OK, Make the bet.
83 | page.find("#roll-button").click
84 |
85 | expect(page.all('tbody#bets tr').count).to eq(1)
86 |
87 | tr = page.find('tbody#bets tr')
88 |
89 | expect(tr.all('td')[0].text).to eq("1")
90 | expect(tr.all('td')[1].text).to eq("Test User")
91 | expect(tr.all('td')[2].text).to eq("less than a minute ago.")
92 | expect(tr.all('td')[3].text).to eq("0.0001")
93 | expect(tr.all('td')[4].text).to eq("2.0")
94 | expect(tr.all('td')[5].text).to eq("< 49.5")
95 |
96 | end
97 |
98 | scenario 'does the probability slider work.' do
99 | user = FactoryGirl.create(:user)
100 | signin('test@example.com', 'please123')
101 |
102 | page.execute_script("$('#probability-slider').val(80);$('#probability-slider').change()")
103 |
104 | prob = page.find('#bet_chance').value
105 |
106 | expect(prob).to eq("80.0%")
107 |
108 | button = page.find('#roll-button').value
109 |
110 | expect(button).to eq("Click for a 80.0% chance of multiplying your bet by 1.24")
111 |
112 | # OK, Make the bet.
113 | page.find("#roll-button").click
114 |
115 | expect(page.all('tbody#bets tr').count).to eq(1)
116 |
117 | tr = page.find('tbody#bets tr')
118 |
119 | expect(tr.all('td')[0].text).to eq("1")
120 | expect(tr.all('td')[1].text).to eq("Test User")
121 | expect(tr.all('td')[2].text).to eq("less than a minute ago.")
122 | expect(tr.all('td')[3].text).to eq("0.00000000")
123 | expect(tr.all('td')[4].text).to eq("1.24")
124 | expect(tr.all('td')[5].text).to eq("< 80.0")
125 | expect(tr.all('td')[7].text).to eq("0.00000000")
126 |
127 | end
128 |
129 | end
130 |
--------------------------------------------------------------------------------
/spec/features/users/sign_in_spec.rb:
--------------------------------------------------------------------------------
1 | # Feature: Sign in
2 | # As a user
3 | # I want to sign in
4 | # So I can visit protected areas of the site
5 | feature 'Sign in', :devise do
6 |
7 | # Scenario: User cannot sign in if not registered
8 | # Given I do not exist as a user
9 | # When I sign in with valid credentials
10 | # Then I see an invalid credentials message
11 | scenario 'user cannot sign in if not registered' do
12 | signin('test@example.com', 'please123')
13 | expect(find('.snackbar', :visible => false).value).to eq I18n.t 'devise.failure.not_found_in_database', authentication_keys: 'email'
14 | end
15 |
16 | # Scenario: User can sign in with valid credentials
17 | # Given I exist as a user
18 | # And I am not signed in
19 | # When I sign in with valid credentials
20 | # Then I see a success message
21 | scenario 'user can sign in with valid credentials' do
22 | user = FactoryGirl.create(:user)
23 | signin(user.email, user.password)
24 | expect(find('.snackbar', :visible => false).value).to eq I18n.t 'devise.sessions.signed_in'
25 | end
26 |
27 | # Scenario: User cannot sign in with wrong email
28 | # Given I exist as a user
29 | # And I am not signed in
30 | # When I sign in with a wrong email
31 | # Then I see an invalid email message
32 | scenario 'user cannot sign in with wrong email' do
33 | user = FactoryGirl.create(:user)
34 | signin('invalid@email.com', user.password)
35 | expect(find('.snackbar', :visible => false).value).to eq I18n.t 'devise.failure.not_found_in_database', authentication_keys: 'email'
36 | end
37 |
38 | # Scenario: User cannot sign in with wrong password
39 | # Given I exist as a user
40 | # And I am not signed in
41 | # When I sign in with a wrong password
42 | # Then I see an invalid password message
43 | scenario 'user cannot sign in with wrong password' do
44 | user = FactoryGirl.create(:user)
45 | signin(user.email, 'invalidpass')
46 | expect(find('.snackbar', :visible => false).value).to eq I18n.t 'devise.failure.invalid', authentication_keys: 'email'
47 | end
48 |
49 | end
50 |
--------------------------------------------------------------------------------
/spec/features/users/sign_out_spec.rb:
--------------------------------------------------------------------------------
1 | # Feature: Sign out
2 | # As a user
3 | # I want to sign out
4 | # So I can protect my account from unauthorized access
5 | feature 'Sign out', :devise do
6 |
7 | # Scenario: User signs out successfully
8 | # Given I am signed in
9 | # When I sign out
10 | # Then I see a signed out message
11 | scenario 'user signs out successfully' do
12 | user = FactoryGirl.create(:user)
13 | signin(user.email, user.password)
14 | expect(find('.snackbar', :visible => false).value).to eq I18n.t 'devise.sessions.signed_in'
15 | click_link 'Sign out'
16 | expect(find('.snackbar', :visible => false).value).to eq I18n.t 'devise.sessions.signed_out'
17 | end
18 |
19 | end
20 |
21 |
22 |
--------------------------------------------------------------------------------
/spec/features/users/user_delete_spec.rb:
--------------------------------------------------------------------------------
1 | include Warden::Test::Helpers
2 | Warden.test_mode!
3 |
4 | # Feature: User delete
5 | # As a user
6 | # I want to delete my user profile
7 | # So I can close my account
8 | feature 'User delete', :devise, :js do
9 |
10 | after(:each) do
11 | Warden.test_reset!
12 | end
13 |
14 | # Scenario: User can delete own account
15 | # Given I am signed in
16 | # When I delete my account
17 | # Then I should see an account deleted message
18 | scenario 'user can delete own account' do
19 | #skip 'skip a slow test'
20 | user = FactoryGirl.create(:user)
21 | login_as(user, :scope => :user)
22 | visit edit_user_registration_path(user)
23 | click_button 'Cancel my account'
24 |
25 | expect(first('.snackbar', :visible => false).value).to eq I18n.t 'devise.registrations.destroyed'
26 | end
27 |
28 | end
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/spec/features/users/user_edit_spec.rb:
--------------------------------------------------------------------------------
1 | include Warden::Test::Helpers
2 | Warden.test_mode!
3 |
4 | # Feature: User edit
5 | # As a user
6 | # I want to edit my user profile
7 | # So I can change my email address
8 | feature 'User edit', :devise do
9 |
10 | after(:each) do
11 | Warden.test_reset!
12 | end
13 |
14 | # Scenario: User changes email address
15 | # Given I am signed in
16 | # When I change my email address
17 | # Then I see an account updated message
18 | scenario 'user changes email address' do
19 | user = FactoryGirl.create(:user)
20 | login_as(user, :scope => :user)
21 | visit edit_user_registration_path(user)
22 | fill_in 'Email', :with => 'newemail@example.com'
23 | fill_in 'Current password', :with => user.password
24 | click_button 'Update'
25 | expect(find('.snackbar', :visible => false).value).to eq I18n.t( 'devise.registrations.updated')
26 | end
27 |
28 | # Scenario: User cannot edit another user's profile
29 | # Given I am signed in
30 | # When I try to edit another user's profile
31 | # Then I see my own 'edit profile' page
32 | scenario "user cannot cannot edit another user's profile", :me do
33 | me = FactoryGirl.create(:user)
34 | other = FactoryGirl.create(:user, email: 'other@example.com')
35 | login_as(me, :scope => :user)
36 | visit edit_user_registration_path(other)
37 | expect(page).to have_content 'Edit User'
38 | expect(page).to have_field('Email', with: me.email)
39 | end
40 |
41 | end
42 |
--------------------------------------------------------------------------------
/spec/features/visitors/home_page_spec.rb:
--------------------------------------------------------------------------------
1 | # Feature: Home page
2 | # As a visitor
3 | # I want to visit a home page
4 | # So I can learn more about the website
5 | feature 'Home page' do
6 |
7 | # Scenario: Visit the home page
8 | # Given I am a visitor
9 | # When I visit the home page
10 | # Then I see "Welcome"
11 | scenario 'visit the home page' do
12 | visit root_path
13 | expect(page).to have_content 'Server Seed'
14 | end
15 |
16 | end
17 |
--------------------------------------------------------------------------------
/spec/features/visitors/navigation_spec.rb:
--------------------------------------------------------------------------------
1 | # Feature: Navigation links
2 | # As a visitor
3 | # I want to see navigation links
4 | # So I can find home, sign in, or sign up
5 | feature 'Navigation links', :devise do
6 |
7 | # Scenario: View navigation links
8 | # Given I am a visitor
9 | # When I visit the home page
10 | # Then I see "home," "sign in," and "sign up"
11 | scenario 'view navigation links' do
12 | visit root_path
13 | expect(page).to have_content 'Bitsino'
14 | expect(page).to have_content 'Sign in'
15 | expect(page).to have_content 'Sign up'
16 | end
17 |
18 | end
19 |
--------------------------------------------------------------------------------
/spec/features/visitors/sign_up_spec.rb:
--------------------------------------------------------------------------------
1 | # Feature: Sign up
2 | # As a visitor
3 | # I want to sign up
4 | # So I can visit protected areas of the site
5 | feature 'Sign Up', :devise do
6 |
7 | # Scenario: Visitor can sign up with valid email address and password
8 | # Given I am not signed in
9 | # When I sign up with a valid email address and password
10 | # Then I see a successful sign up message
11 | scenario 'visitor can sign up with valid email address and password' do
12 | sign_up_with('test@example.com', 'please123', 'please123')
13 | expect(find('.snackbar', :visible => false).value).to eq I18n.t( 'devise.registrations.signed_up')
14 | end
15 |
16 | # Scenario: Visitor cannot sign up with invalid email address
17 | # Given I am not signed in
18 | # When I sign up with an invalid email address
19 | # Then I see an invalid email message
20 | scenario 'visitor cannot sign up with invalid email address' do
21 | sign_up_with('bogus', 'please123', 'please123')
22 | expect(page).to have_content 'Email is invalid'
23 | end
24 |
25 | # Scenario: Visitor cannot sign up without password
26 | # Given I am not signed in
27 | # When I sign up without a password
28 | # Then I see a missing password message
29 | scenario 'visitor cannot sign up without password' do
30 | sign_up_with('test@example.com', '', '')
31 | expect(page).to have_content "Password can't be blank"
32 | end
33 |
34 | # Scenario: Visitor cannot sign up with a short password
35 | # Given I am not signed in
36 | # When I sign up with a short password
37 | # Then I see a 'too short password' message
38 | scenario 'visitor cannot sign up with a short password' do
39 | sign_up_with('test@example.com', 'please', 'please')
40 | expect(page).to have_content "Password is too short"
41 | end
42 |
43 | # Scenario: Visitor cannot sign up without password confirmation
44 | # Given I am not signed in
45 | # When I sign up without a password confirmation
46 | # Then I see a missing password confirmation message
47 | scenario 'visitor cannot sign up without password confirmation' do
48 | sign_up_with('test@example.com', 'please123', '')
49 | expect(page).to have_content "Password confirmation doesn't match"
50 | end
51 |
52 | # Scenario: Visitor cannot sign up with mismatched password and confirmation
53 | # Given I am not signed in
54 | # When I sign up with a mismatched password confirmation
55 | # Then I should see a mismatched password message
56 | scenario 'visitor cannot sign up with mismatched password and confirmation' do
57 | sign_up_with('test@example.com', 'please123', 'mismatch')
58 | expect(page).to have_content "Password confirmation doesn't match"
59 | end
60 |
61 | end
62 |
--------------------------------------------------------------------------------
/spec/models/user_spec.rb:
--------------------------------------------------------------------------------
1 | describe User do
2 |
3 | before(:each) { @user = User.new(email: 'user@example.com') }
4 |
5 | subject { @user }
6 |
7 | it { should respond_to(:email) }
8 |
9 | it "#email returns a string" do
10 | expect(@user.email).to match 'user@example.com'
11 | end
12 |
13 | it "#sweep_bitcoins_to_onchain_fund should create a valid tx" do
14 |
15 | tx = User.sweep_bitcoins_to_onchain_fund
16 |
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/spec/rails_helper.rb:
--------------------------------------------------------------------------------
1 | # This file is copied to spec/ when you run 'rails generate rspec:install'
2 | ENV["RAILS_ENV"] ||= 'test'
3 | require 'spec_helper'
4 | require File.expand_path("../../config/environment", __FILE__)
5 | require 'rspec/rails'
6 | require 'capybara'
7 | require "capybara-webkit"
8 | # Add additional requires below this line. Rails is not loaded until this point!
9 |
10 | # Requires supporting ruby files with custom matchers and macros, etc, in
11 | # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
12 | # run as spec files by default. This means that files in spec/support that end
13 | # in _spec.rb will both be required and run as specs, causing the specs to be
14 | # run twice. It is recommended that you do not name files matching this glob to
15 | # end with _spec.rb. You can configure this pattern with the --pattern
16 | # option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
17 | #
18 | # The following line is provided for convenience purposes. It has the downside
19 | # of increasing the boot-up time by auto-requiring all files in the support
20 | # directory. Alternatively, in the individual `*_spec.rb` files, manually
21 | # require only the support files necessary.
22 | #
23 | Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
24 |
25 | Capybara.javascript_driver = :webkit
26 | # Checks for pending migrations before tests are run.
27 | # If you are not using ActiveRecord, you can remove this line.
28 | ActiveRecord::Migration.maintain_test_schema!
29 |
30 | RSpec.configure do |config|
31 | # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
32 | config.fixture_path = "#{::Rails.root}/spec/fixtures"
33 |
34 | # If you're not using ActiveRecord, or you'd prefer not to run each of your
35 | # examples within a transaction, remove the following line or assign false
36 | # instead of true.
37 | config.use_transactional_fixtures = false
38 |
39 | # RSpec Rails can automatically mix in different behaviours to your tests
40 | # based on their file location, for example enabling you to call `get` and
41 | # `post` in specs under `spec/controllers`.
42 | #
43 | # You can disable this behaviour by removing the line below, and instead
44 | # explicitly tag your specs with their type, e.g.:
45 | #
46 | # RSpec.describe UsersController, :type => :controller do
47 | # # ...
48 | # end
49 | #
50 | # The different available types are documented in the features, such as in
51 | # https://relishapp.com/rspec/rspec-rails/docs
52 | config.infer_spec_type_from_file_location!
53 | end
54 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | require 'simplecov'
2 | SimpleCov.start
3 |
4 | RSpec.configure do |config|
5 | # rspec-expectations config goes here. You can use an alternate
6 | # assertion/expectation library such as wrong or the stdlib/minitest
7 | # assertions if you prefer.
8 |
9 | config.expect_with :rspec do |expectations|
10 | # This option will default to `true` in RSpec 4. It makes the `description`
11 | # and `failure_message` of custom matchers include text for helper methods
12 | # defined using `chain`, e.g.:
13 | # be_bigger_than(2).and_smaller_than(4).description
14 | # # => "be bigger than 2 and smaller than 4"
15 | # ...rather than:
16 | # # => "be bigger than 2"
17 | expectations.include_chain_clauses_in_custom_matcher_descriptions = true
18 | end
19 |
20 | # rspec-mocks config goes here. You can use an alternate test double
21 | # library (such as bogus or mocha) by changing the `mock_with` option here.
22 | config.mock_with :rspec do |mocks|
23 | # Prevents you from mocking or stubbing a method that does not exist on
24 | # a real object. This is generally recommended, and will default to
25 | # `true` in RSpec 4.
26 | mocks.verify_partial_doubles = true
27 | end
28 |
29 | end
30 |
--------------------------------------------------------------------------------
/spec/support/capybara.rb:
--------------------------------------------------------------------------------
1 | Capybara.asset_host = 'http://localhost:3000'
2 |
--------------------------------------------------------------------------------
/spec/support/database_cleaner.rb:
--------------------------------------------------------------------------------
1 | RSpec.configure do |config|
2 | config.before(:suite) do
3 | DatabaseCleaner.clean_with(:truncation)
4 | end
5 |
6 | config.before(:each) do
7 | DatabaseCleaner.strategy = :transaction
8 | end
9 |
10 | config.before(:each, :js => true) do
11 | DatabaseCleaner.strategy = :truncation
12 | end
13 |
14 | config.before(:each) do
15 | DatabaseCleaner.start
16 | end
17 |
18 | config.append_after(:each) do
19 | DatabaseCleaner.clean
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/spec/support/devise.rb:
--------------------------------------------------------------------------------
1 | RSpec.configure do |config|
2 | config.include Devise::TestHelpers, :type => :controller
3 | end
4 |
--------------------------------------------------------------------------------
/spec/support/factory_girl.rb:
--------------------------------------------------------------------------------
1 | RSpec.configure do |config|
2 | config.include FactoryGirl::Syntax::Methods
3 | end
4 |
--------------------------------------------------------------------------------
/spec/support/helpers.rb:
--------------------------------------------------------------------------------
1 | require 'support/helpers/session_helpers'
2 | RSpec.configure do |config|
3 | config.include Features::SessionHelpers, type: :feature
4 | end
5 |
--------------------------------------------------------------------------------
/spec/support/helpers/session_helpers.rb:
--------------------------------------------------------------------------------
1 | module Features
2 | module SessionHelpers
3 | def sign_up_with(email, password, confirmation)
4 | visit new_user_registration_path
5 | fill_in 'Email', with: email
6 | fill_in 'Password', with: password
7 | fill_in 'Password confirmation', :with => confirmation
8 | click_button 'Sign up'
9 | end
10 |
11 | def signin(email, password)
12 | visit new_user_session_path
13 | fill_in 'Email', with: email
14 | fill_in 'Password', with: password
15 | click_button 'Sign in'
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/vendor/assets/javascripts/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bitsino/BitsinoDice/ab7040438fac437b6b146e208f0813dd97c09690/vendor/assets/javascripts/.keep
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bitsino/BitsinoDice/ab7040438fac437b6b146e208f0813dd97c09690/vendor/assets/stylesheets/.keep
--------------------------------------------------------------------------------