glueby 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-gemset +1 -1
  3. data/.ruby-version +1 -1
  4. data/.travis.yml +3 -2
  5. data/README.md +27 -17
  6. data/glueby.gemspec +1 -1
  7. data/lib/generators/glueby/{initializer_generator.rb → contract/initializer_generator.rb} +0 -0
  8. data/lib/generators/glueby/contract/templates/initializer.rb.erb +3 -0
  9. data/lib/generators/glueby/contract/templates/key_table.rb.erb +15 -0
  10. data/lib/generators/glueby/{templates → contract/templates}/timestamp_table.rb.erb +2 -1
  11. data/lib/generators/glueby/contract/templates/utxo_table.rb.erb +15 -0
  12. data/lib/generators/glueby/contract/templates/wallet_table.rb.erb +10 -0
  13. data/lib/generators/glueby/contract/timestamp_generator.rb +26 -0
  14. data/lib/generators/glueby/contract/wallet_adapter_generator.rb +46 -0
  15. data/lib/glueby.rb +18 -1
  16. data/lib/glueby/contract.rb +3 -14
  17. data/lib/glueby/contract/active_record/timestamp.rb +8 -5
  18. data/lib/glueby/contract/errors.rb +6 -0
  19. data/lib/glueby/contract/payment.rb +54 -0
  20. data/lib/glueby/contract/timestamp.rb +39 -38
  21. data/lib/glueby/contract/token.rb +193 -0
  22. data/lib/glueby/contract/tx_builder.rb +197 -31
  23. data/lib/glueby/generator.rb +5 -0
  24. data/lib/glueby/generator/migrate_generator.rb +38 -0
  25. data/lib/glueby/internal.rb +6 -0
  26. data/lib/glueby/internal/rpc.rb +35 -0
  27. data/lib/glueby/internal/wallet.rb +122 -0
  28. data/lib/glueby/internal/wallet/abstract_wallet_adapter.rb +131 -0
  29. data/lib/glueby/internal/wallet/active_record.rb +15 -0
  30. data/lib/glueby/internal/wallet/active_record/key.rb +72 -0
  31. data/lib/glueby/internal/wallet/active_record/utxo.rb +50 -0
  32. data/lib/glueby/internal/wallet/active_record/wallet.rb +54 -0
  33. data/lib/glueby/internal/wallet/active_record_wallet_adapter.rb +133 -0
  34. data/lib/glueby/internal/wallet/errors.rb +11 -0
  35. data/lib/glueby/internal/wallet/tapyrus_core_wallet_adapter.rb +158 -0
  36. data/lib/glueby/version.rb +1 -1
  37. data/lib/glueby/wallet.rb +51 -0
  38. data/lib/tasks/glueby/contract/timestamp.rake +5 -5
  39. data/lib/tasks/glueby/contract/wallet_adapter.rake +42 -0
  40. metadata +30 -10
  41. data/lib/generators/glueby/templates/initializer.rb.erb +0 -4
  42. data/lib/generators/glueby/timestamp_generator.rb +0 -57
  43. data/lib/glueby/contract/rpc.rb +0 -15
@@ -0,0 +1,193 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Glueby
4
+ module Contract
5
+ # This class represents custom token issued by application user.
6
+ # Application users can
7
+ # - issue their own tokens.
8
+ # - send to other users.
9
+ # - make the tokens disable.
10
+ #
11
+ # Examples:
12
+ #
13
+ # alice = Glueby::Wallet.create
14
+ # bob = Glueby::Wallet.create
15
+ #
16
+ # Issue
17
+ # token = Token.issue!(issuer: alice, amount: 100)
18
+ # token.amount(wallet: alice)
19
+ # => 100
20
+ #
21
+ # Send
22
+ # token.transfer!(sender: alice, receiver: bob, amount: 1)
23
+ # token.amount(wallet: alice)
24
+ # => 99
25
+ # token.amount(wallet: bob)
26
+ # => 1
27
+ #
28
+ # Burn
29
+ # token.burn!(sender: alice, amount: 10)
30
+ # token.amount(wallet: alice)
31
+ # => 89
32
+ # token.burn!(sender: alice)
33
+ # token.amount(wallet: alice)
34
+ # => 0
35
+ #
36
+ # Reissue
37
+ # token.reissue!(issuer: alice, amount: 100)
38
+ # token.amount(wallet: alice)
39
+ # => 100
40
+ #
41
+ class Token
42
+ include Glueby::Contract::TxBuilder
43
+ extend Glueby::Contract::TxBuilder
44
+
45
+ class << self
46
+ # Issue new token with specified amount and token type.
47
+ # REISSUABLE token can be reissued with #reissue! method, and
48
+ # NON_REISSUABLE and NFT token can not.
49
+ # Amount is set to 1 when the token type is NFT
50
+ #
51
+ # @param issuer [Glueby::Wallet]
52
+ # @param token_type [TokenTypes]
53
+ # @param amount [Integer]
54
+ # @return [Token] token
55
+ # @raise [InsufficientFunds] if wallet does not have enough TPC to send transaction.
56
+ # @raise [InvalidAmount] if amount is not positive integer.
57
+ # @raise [UnspportedTokenType] if token is not supported.
58
+ def issue!(issuer:, token_type: Tapyrus::Color::TokenTypes::REISSUABLE, amount: 1)
59
+ raise Glueby::Contract::Errors::InvalidAmount unless amount.positive?
60
+
61
+ txs, color_id, script_pubkey = case token_type
62
+ when Tapyrus::Color::TokenTypes::REISSUABLE
63
+ issue_reissuable_token(issuer: issuer, amount: amount)
64
+ when Tapyrus::Color::TokenTypes::NON_REISSUABLE
65
+ issue_non_reissuable_token(issuer: issuer, amount: amount)
66
+ when Tapyrus::Color::TokenTypes::NFT
67
+ issue_nft_token(issuer: issuer)
68
+ else
69
+ raise Glueby::Contract::Errors::UnsupportedTokenType
70
+ end
71
+ txs.each { |tx| issuer.internal_wallet.broadcast(tx) }
72
+ new(color_id: color_id, script_pubkey: script_pubkey)
73
+ end
74
+
75
+ private
76
+
77
+ def issue_reissuable_token(issuer:, amount:)
78
+ estimated_fee = FixedFeeProvider.new.fee(Tapyrus::Tx.new)
79
+ funding_tx = create_funding_tx(wallet: issuer, amount: estimated_fee)
80
+ tx = create_issue_tx_for_reissuable_token(funding_tx: funding_tx, issuer: issuer, amount: amount)
81
+ script_pubkey = funding_tx.outputs.first.script_pubkey
82
+ color_id = Tapyrus::Color::ColorIdentifier.reissuable(script_pubkey)
83
+ [[funding_tx, tx], color_id, script_pubkey]
84
+ end
85
+
86
+ def issue_non_reissuable_token(issuer:, amount:)
87
+ tx = create_issue_tx_for_non_reissuable_token(issuer: issuer, amount: amount)
88
+ out_point = tx.inputs.first.out_point
89
+ color_id = Tapyrus::Color::ColorIdentifier.non_reissuable(out_point)
90
+ [[tx], color_id, nil]
91
+ end
92
+
93
+ def issue_nft_token(issuer:)
94
+ tx = create_issue_tx_for_nft_token(issuer: issuer)
95
+ out_point = tx.inputs.first.out_point
96
+ color_id = Tapyrus::Color::ColorIdentifier.nft(out_point)
97
+ [[tx], color_id, nil]
98
+ end
99
+ end
100
+
101
+ attr_reader :color_id
102
+
103
+ # Re-issue the token with specified amount.
104
+ # A wallet can issue the token only when it is REISSUABLE token.
105
+ # @param issuer [Glueby::Wallet]
106
+ # @param amount [Integer]
107
+ # @raise [InsufficientFunds] if wallet does not have enough TPC to send transaction.
108
+ # @raise [InvalidAmount] if amount is not positive integer.
109
+ # @raise [InvalidTokenType] if token is not reissuable.
110
+ # @raise [UnknownScriptPubkey] when token is reissuable but it doesn't know script pubkey to issue token.
111
+ def reissue!(issuer:, amount:)
112
+ raise Glueby::Contract::Errors::InvalidAmount unless amount.positive?
113
+ raise Glueby::Contract::Errors::InvalidTokenType unless token_type == Tapyrus::Color::TokenTypes::REISSUABLE
114
+ raise Glueby::Contract::Errors::UnknownScriptPubkey unless @script_pubkey
115
+
116
+ estimated_fee = FixedFeeProvider.new.fee(Tapyrus::Tx.new)
117
+ funding_tx = create_funding_tx(wallet: issuer, amount: estimated_fee, script: @script_pubkey)
118
+ tx = create_reissue_tx(funding_tx: funding_tx, issuer: issuer, amount: amount, color_id: color_id)
119
+ [funding_tx, tx].each { |tx| issuer.internal_wallet.broadcast(tx) }
120
+ end
121
+
122
+ # Send the token to other wallet
123
+ #
124
+ # @param sender [Glueby::Wallet] wallet to send this token
125
+ # @param receiver [Glueby::Wallet] wallet to receive this token
126
+ # @param amount [Integer]
127
+ # @return [Token] receiver token
128
+ # @raise [InsufficientFunds] if wallet does not have enough TPC to send transaction.
129
+ # @raise [InsufficientTokens] if wallet does not have enough token to send.
130
+ # @raise [InvalidAmount] if amount is not positive integer.
131
+ def transfer!(sender:, receiver:, amount: 1)
132
+ raise Glueby::Contract::Errors::InvalidAmount unless amount.positive?
133
+
134
+ tx = create_transfer_tx(color_id: color_id, sender: sender, receiver: receiver, amount: amount)
135
+ sender.internal_wallet.broadcast(tx)
136
+ end
137
+
138
+ # Burn token
139
+ # If amount is not specified or 0, burn all token associated with the wallet.
140
+ #
141
+ # @param sender [Glueby::Wallet] wallet to send this token
142
+ # @param amount [Integer]
143
+ # @raise [InsufficientFunds] if wallet does not have enough TPC to send transaction.
144
+ # @raise [InsufficientTokens] if wallet does not have enough token to send transaction.
145
+ # @raise [InvalidAmount] if amount is not positive integer.
146
+ def burn!(sender:, amount: 0)
147
+ raise Glueby::Contract::Errors::InvalidAmount unless amount.positive?
148
+
149
+ tx = create_burn_tx(color_id: color_id, sender: sender, amount: amount)
150
+ sender.internal_wallet.broadcast(tx)
151
+ end
152
+
153
+ # Return balance of token in the specified wallet.
154
+ # @param wallet [Glueby::Wallet]
155
+ # @return [Integer] amount of utxo value associated with this token.
156
+ def amount(wallet:)
157
+ # collect utxo associated with this address
158
+ utxos = wallet.internal_wallet.list_unspent
159
+ _, results = collect_colored_outputs(utxos, color_id)
160
+ results.sum { |result| result[:amount] }
161
+ end
162
+
163
+ # Return token type
164
+ # @return [Tapyrus::Color::TokenTypes]
165
+ def token_type
166
+ color_id.type
167
+ end
168
+
169
+ # Return serialized payload
170
+ # @return [String] payload
171
+ def to_payload
172
+ payload = +''
173
+ payload << @color_id.to_payload
174
+ payload << @script_pubkey.to_payload if @script_pubkey
175
+ end
176
+
177
+ # Restore token from payload
178
+ # @param payload [String]
179
+ # @return [Glueby::Contract::Token]
180
+ def self.parse_from_payload(payload)
181
+ color_id, script_pubkey = payload.unpack('a33a*')
182
+ color_id = Tapyrus::Color::ColorIdentifier.parse_from_payload(color_id)
183
+ script_pubkey = Tapyrus::Script.parse_from_payload(script_pubkey) if script_pubkey
184
+ new(color_id: color_id, script_pubkey: script_pubkey)
185
+ end
186
+
187
+ def initialize(color_id:, script_pubkey:nil)
188
+ @color_id = color_id
189
+ @script_pubkey = script_pubkey
190
+ end
191
+ end
192
+ end
193
+ end
@@ -1,46 +1,212 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Glueby
2
4
  module Contract
3
5
  module TxBuilder
4
- # collect outputs in results so that sum of them exceeds up to the specified amount.
5
- # @param [Array] results of listunspent
6
- # @param [Numeric] amount
7
- # @return [(Numeric, Array)] sum value of outputs and outputs
8
- # @raise [InsufficientFunds] if result of listunspent is not enough to pay the specified amount
9
- def collect_outputs(results, amount)
10
- results.inject([0, []]) do |sum, output|
11
- new_sum = sum[0] + (output['amount'] * 100_000_000)
12
- new_outputs = sum[1] << output
13
- return [new_sum, new_outputs] if new_sum >= amount
6
+ def receive_address(wallet:)
7
+ wallet.receive_address
8
+ end
14
9
 
15
- [new_sum, new_outputs]
10
+ # Create new public key, and new transaction that sends TPC to it
11
+ def create_funding_tx(wallet:, amount:, script: nil, fee_provider: FixedFeeProvider.new)
12
+ tx = Tapyrus::Tx.new
13
+ fee = fee_provider.fee(dummy_tx(tx))
14
+
15
+ sum, outputs = wallet.internal_wallet.collect_uncolored_outputs(fee + amount)
16
+ fill_input(tx, outputs)
17
+
18
+ receiver_script = script ? script : Tapyrus::Script.parse_from_addr(wallet.internal_wallet.receive_address)
19
+ tx.outputs << Tapyrus::TxOut.new(value: amount, script_pubkey: receiver_script)
20
+
21
+ fill_change_tpc(tx, wallet, sum - fee - amount)
22
+ wallet.internal_wallet.sign_tx(tx)
23
+ end
24
+
25
+ def create_issue_tx_for_reissuable_token(funding_tx:, issuer:, amount:, fee_provider: FixedFeeProvider.new)
26
+ tx = Tapyrus::Tx.new
27
+
28
+ out_point = Tapyrus::OutPoint.from_txid(funding_tx.txid, 0)
29
+ tx.inputs << Tapyrus::TxIn.new(out_point: out_point)
30
+ output = funding_tx.outputs.first
31
+
32
+ receiver_script = Tapyrus::Script.parse_from_payload(output.script_pubkey.to_payload)
33
+ color_id = Tapyrus::Color::ColorIdentifier.reissuable(receiver_script)
34
+ receiver_colored_script = receiver_script.add_color(color_id)
35
+ tx.outputs << Tapyrus::TxOut.new(value: amount, script_pubkey: receiver_colored_script)
36
+
37
+ fee = fee_provider.fee(dummy_tx(tx))
38
+ fill_change_tpc(tx, issuer, output.value - fee)
39
+ prev_txs = [{
40
+ txid: funding_tx.txid,
41
+ vout: 0,
42
+ scriptPubKey: output.script_pubkey.to_hex,
43
+ amount: output.value
44
+ }]
45
+ issuer.internal_wallet.sign_tx(tx, prev_txs)
46
+ end
47
+
48
+ def create_issue_tx_for_non_reissuable_token(issuer:, amount:, fee_provider: FixedFeeProvider.new)
49
+ create_issue_tx_from_out_point(token_type: Tapyrus::Color::TokenTypes::NON_REISSUABLE, issuer: issuer, amount: amount, fee_provider: fee_provider)
50
+ end
51
+
52
+ def create_issue_tx_for_nft_token(issuer:, fee_provider: FixedFeeProvider.new)
53
+ create_issue_tx_from_out_point(token_type: Tapyrus::Color::TokenTypes::NFT, issuer: issuer, amount: 1, fee_provider: fee_provider)
54
+ end
55
+
56
+ def create_issue_tx_from_out_point(token_type:, issuer:, amount:, fee_provider: FixedFeeProvider.new)
57
+ tx = Tapyrus::Tx.new
58
+
59
+ fee = fee_provider.fee(dummy_issue_tx_from_out_point)
60
+ sum, outputs = issuer.internal_wallet.collect_uncolored_outputs(fee)
61
+ fill_input(tx, outputs)
62
+
63
+ out_point = tx.inputs.first.out_point
64
+ color_id = case token_type
65
+ when Tapyrus::Color::TokenTypes::NON_REISSUABLE
66
+ Tapyrus::Color::ColorIdentifier.non_reissuable(out_point)
67
+ when Tapyrus::Color::TokenTypes::NFT
68
+ Tapyrus::Color::ColorIdentifier.nft(out_point)
69
+ else
70
+ raise Glueby::Contract::Errors::UnsupportedTokenType
16
71
  end
17
- raise Glueby::Contract::Errors::InsufficientFunds
72
+
73
+ receiver_script = Tapyrus::Script.parse_from_addr(issuer.internal_wallet.receive_address)
74
+ receiver_colored_script = receiver_script.add_color(color_id)
75
+ tx.outputs << Tapyrus::TxOut.new(value: amount, script_pubkey: receiver_colored_script)
76
+
77
+ fill_change_tpc(tx, issuer, sum - fee)
78
+ issuer.internal_wallet.sign_tx(tx)
79
+ end
80
+
81
+ def create_reissue_tx(funding_tx:, issuer:, amount:, color_id:, fee_provider: FixedFeeProvider.new)
82
+ tx = Tapyrus::Tx.new
83
+
84
+ out_point = Tapyrus::OutPoint.from_txid(funding_tx.txid, 0)
85
+ tx.inputs << Tapyrus::TxIn.new(out_point: out_point)
86
+ output = funding_tx.outputs.first
87
+
88
+ receiver_script = Tapyrus::Script.parse_from_payload(output.script_pubkey.to_payload)
89
+ receiver_colored_script = receiver_script.add_color(color_id)
90
+ tx.outputs << Tapyrus::TxOut.new(value: amount, script_pubkey: receiver_colored_script)
91
+
92
+ fee = fee_provider.fee(dummy_tx(tx))
93
+ fill_change_tpc(tx, issuer, output.value - fee)
94
+ prev_txs = [{
95
+ txid: funding_tx.txid,
96
+ vout: 0,
97
+ scriptPubKey: output.script_pubkey.to_hex,
98
+ amount: output.value
99
+ }]
100
+ issuer.internal_wallet.sign_tx(tx, prev_txs)
101
+ end
102
+
103
+ def create_transfer_tx(color_id:, sender:, receiver:, amount:, fee_provider: FixedFeeProvider.new)
104
+ tx = Tapyrus::Tx.new
105
+
106
+ utxos = sender.internal_wallet.list_unspent
107
+ sum_token, outputs = collect_colored_outputs(utxos, color_id, amount)
108
+ fill_input(tx, outputs)
109
+
110
+ receiver_script = Tapyrus::Script.parse_from_addr(receiver.internal_wallet.receive_address)
111
+ receiver_colored_script = receiver_script.add_color(color_id)
112
+ tx.outputs << Tapyrus::TxOut.new(value: amount, script_pubkey: receiver_colored_script)
113
+
114
+ fill_change_token(tx, sender, sum_token - amount, color_id)
115
+
116
+ fee = fee_provider.fee(dummy_tx(tx))
117
+ sum_tpc, outputs = sender.internal_wallet.collect_uncolored_outputs(fee)
118
+ fill_input(tx, outputs)
119
+
120
+ fill_change_tpc(tx, sender, sum_tpc - fee)
121
+ sender.internal_wallet.sign_tx(tx)
122
+ end
123
+
124
+ def create_burn_tx(color_id:, sender:, amount: 0, fee_provider: FixedFeeProvider.new)
125
+ tx = Tapyrus::Tx.new
126
+
127
+ utxos = sender.internal_wallet.list_unspent
128
+ sum_token, outputs = collect_colored_outputs(utxos, color_id, amount)
129
+ fill_input(tx, outputs)
130
+
131
+ fill_change_token(tx, sender, sum_token - amount, color_id) if amount.positive?
132
+
133
+ fee = fee_provider.fee(dummy_tx(tx))
134
+
135
+ dust = 600 # in case that the wallet has output which has just fee amount.
136
+ sum_tpc, outputs = sender.internal_wallet.collect_uncolored_outputs(fee + dust)
137
+ fill_input(tx, outputs)
138
+
139
+ fill_change_tpc(tx, sender, sum_tpc - fee)
140
+ sender.internal_wallet.sign_tx(tx)
18
141
  end
19
142
 
20
- # Add inputs to tx
21
- # @param [Tapyrus::Tx] tx
22
- # @param [Array] outputs provided as result of listunspent and extracted by #collect_outputs methods
23
- # @return [Tapyrus::Tx] tx which has enough amount in inputs.
24
143
  def fill_input(tx, outputs)
25
144
  outputs.each do |output|
26
- out_point = Tapyrus::OutPoint.new(output['txid'].rhex, output['vout'])
145
+ out_point = Tapyrus::OutPoint.new(output[:txid].rhex, output[:vout])
27
146
  tx.inputs << Tapyrus::TxIn.new(out_point: out_point)
28
147
  end
29
- tx
30
- end
31
-
32
- # Add output to tx, so that allow tx to return the change of the transaction.
33
- # @param [Tapyrus::Tx] tx
34
- # @param [Numeric] fee
35
- # @param [Tapyrus::Script] script for change
36
- # @param [Numeric] sum value of inputs
37
- def fill_change_output(tx, fee, change_script, sum)
38
- amount = fee + tx.outputs.map(&:value).sum
39
- if amount.positive?
40
- change = sum - amount
41
- tx.outputs << Tapyrus::TxOut.new(value: change, script_pubkey: change_script)
148
+ end
149
+
150
+ def fill_change_tpc(tx, wallet, change)
151
+ return unless change.positive?
152
+
153
+ change_script = Tapyrus::Script.parse_from_addr(wallet.internal_wallet.change_address)
154
+ tx.outputs << Tapyrus::TxOut.new(value: change, script_pubkey: change_script)
155
+ end
156
+
157
+ def fill_change_token(tx, wallet, change, color_id)
158
+ return unless change.positive?
159
+
160
+ change_script = Tapyrus::Script.parse_from_addr(wallet.internal_wallet.change_address)
161
+ change_colored_script = change_script.add_color(color_id)
162
+ tx.outputs << Tapyrus::TxOut.new(value: change, script_pubkey: change_colored_script)
163
+ end
164
+
165
+ # Returns the set of utxos that satisfies the specified amount and has the specified color_id.
166
+ # if amount is not specified or 0, return all utxos with color_id
167
+ # @param results [Array] response of Glueby::Internal::Wallet#list_unspent
168
+ # @param color_id [Tapyrus::Color::ColorIdentifier] color identifier
169
+ # @param amount [Integer]
170
+ def collect_colored_outputs(results, color_id, amount = 0)
171
+ results = results.inject([0, []]) do |sum, output|
172
+ next sum unless output[:color_id] == color_id.to_hex
173
+
174
+ new_sum = sum[0] + output[:amount]
175
+ new_outputs = sum[1] << output
176
+ return [new_sum, new_outputs] if new_sum >= amount && amount.positive?
177
+
178
+ [new_sum, new_outputs]
42
179
  end
43
- tx
180
+ raise Glueby::Contract::Errors::InsufficientTokens if amount.positive?
181
+
182
+ results
183
+ end
184
+
185
+ # Add dummy inputs and outputs to tx
186
+ def dummy_tx(tx)
187
+ dummy = Tapyrus::Tx.parse_from_payload(tx.to_payload)
188
+
189
+ # dummy input for tpc
190
+ out_point = Tapyrus::OutPoint.new('00' * 32, 0)
191
+ dummy.inputs << Tapyrus::TxIn.new(out_point: out_point)
192
+
193
+ # Add script_sig to all intpus
194
+ dummy.inputs.each do |input|
195
+ input.script_sig = Tapyrus::Script.parse_from_payload('000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'.htb)
196
+ end
197
+
198
+ # dummy output to return change
199
+ change_script = Tapyrus::Script.to_p2pkh('0000000000000000000000000000000000000000')
200
+ dummy.outputs << Tapyrus::TxOut.new(value: 0, script_pubkey: change_script)
201
+ dummy
202
+ end
203
+
204
+ # Add dummy inputs and outputs to tx for issue non-reissuable transaction and nft transaction
205
+ def dummy_issue_tx_from_out_point
206
+ tx = Tapyrus::Tx.new
207
+ receiver_colored_script = Tapyrus::Script.parse_from_payload('21c20000000000000000000000000000000000000000000000000000000000000000bc76a914000000000000000000000000000000000000000088ac'.htb)
208
+ tx.outputs << Tapyrus::TxOut.new(value: 0, script_pubkey: receiver_colored_script)
209
+ dummy_tx(tx)
44
210
  end
45
211
  end
46
212
  end
@@ -0,0 +1,5 @@
1
+ module Glueby
2
+ module Generator
3
+ autoload :MigrateGenerator, 'glueby/generator/migrate_generator'
4
+ end
5
+ end
@@ -0,0 +1,38 @@
1
+ module Glueby
2
+ module Generator
3
+ module MigrateGenerator
4
+ module ClassMethod
5
+ def next_migration_number(dirname)
6
+ # ::ActiveRecord::Migration.next_migration_number(number)
7
+ # ::ActiveRecord::Generators::Base.next_migration_number(dirname)
8
+ next_migration_number = current_migration_number(dirname) + 1
9
+ ::ActiveRecord::Migration.next_migration_number(next_migration_number)
10
+ end
11
+ end
12
+
13
+ MYSQL_ADAPTERS = [
14
+ "ActiveRecord::ConnectionAdapters::MysqlAdapter",
15
+ "ActiveRecord::ConnectionAdapters::Mysql2Adapter"
16
+ ].freeze
17
+
18
+ def migration_version
19
+ major = ::Rails::VERSION::MAJOR
20
+ if major >= 5
21
+ "[#{major}.#{::Rails::VERSION::MINOR}]"
22
+ end
23
+ end
24
+
25
+ def mysql?
26
+ MYSQL_ADAPTERS.include?(::ActiveRecord::Base.connection.class.name)
27
+ end
28
+
29
+ def table_options
30
+ if mysql?
31
+ ', { options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci" }'
32
+ else
33
+ ""
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end