glueby 0.4.0 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +387 -281
- data/glueby.gemspec +33 -32
- data/lib/generators/glueby/contract/templates/initializer.rb.erb +8 -3
- data/lib/generators/glueby/contract/templates/key_table.rb.erb +16 -15
- data/lib/generators/glueby/contract/templates/utxo_table.rb.erb +16 -15
- data/lib/glueby/block_syncer.rb +98 -0
- data/lib/glueby/contract/timestamp/syncer.rb +13 -0
- data/lib/glueby/contract/timestamp.rb +102 -100
- data/lib/glueby/contract/token.rb +244 -243
- data/lib/glueby/fee_provider/tasks.rb +140 -135
- data/lib/glueby/internal/wallet/abstract_wallet_adapter.rb +151 -145
- data/lib/glueby/internal/wallet/active_record/utxo.rb +51 -50
- data/lib/glueby/internal/wallet/active_record_wallet_adapter/syncer.rb +14 -0
- data/lib/glueby/internal/wallet/active_record_wallet_adapter.rb +151 -143
- data/lib/glueby/internal/wallet/tapyrus_core_wallet_adapter.rb +186 -183
- data/lib/glueby/internal/wallet.rb +162 -146
- data/lib/glueby/railtie.rb +10 -0
- data/lib/glueby/version.rb +3 -3
- data/lib/glueby.rb +39 -49
- data/lib/tasks/glueby/block_syncer.rake +29 -0
- data/lib/tasks/glueby/contract/timestamp.rake +39 -61
- data/lib/tasks/glueby/fee_provider.rake +18 -13
- metadata +26 -9
- data/lib/tasks/glueby/contract/block_syncer.rake +0 -36
- data/lib/tasks/glueby/contract/wallet_adapter.rake +0 -42
@@ -1,146 +1,162 @@
|
|
1
|
-
module Glueby
|
2
|
-
module Internal
|
3
|
-
# # Glueby::Internal::Wallet
|
4
|
-
#
|
5
|
-
# This module provides the way to deal about wallet that includes key management, address management, getting UTXOs.
|
6
|
-
#
|
7
|
-
# ## How to use
|
8
|
-
#
|
9
|
-
# First, you need to configure which wallet implementation is used in Glueby::Internal::Wallet. For now, below wallets are
|
10
|
-
# supported.
|
11
|
-
#
|
12
|
-
# * [Tapyrus Core](https://github.com/chaintope/tapyrus-core)
|
13
|
-
#
|
14
|
-
# Here shows an example to use Tapyrus Core wallet.
|
15
|
-
#
|
16
|
-
# ```ruby
|
17
|
-
# # Setup Tapyrus Core RPC connection
|
18
|
-
# config = {schema: 'http', host: '127.0.0.1', port: 12381, user: 'user', password: 'pass'}
|
19
|
-
# Glueby::Internal::RPC.configure(config)
|
20
|
-
#
|
21
|
-
# # Setup wallet adapter
|
22
|
-
# Glueby::Internal::Wallet.wallet_adapter = Glueby::Internal::Wallet::TapyrusCoreWalletAdapter.new
|
23
|
-
#
|
24
|
-
# # Create wallet
|
25
|
-
# wallet = Glueby::Internal::Wallet.create
|
26
|
-
# wallet.balance # => 0
|
27
|
-
# wallet.list_unspent
|
28
|
-
# ```
|
29
|
-
class Wallet
|
30
|
-
autoload :AbstractWalletAdapter, 'glueby/internal/wallet/abstract_wallet_adapter'
|
31
|
-
autoload :AR, 'glueby/internal/wallet/active_record'
|
32
|
-
autoload :TapyrusCoreWalletAdapter, 'glueby/internal/wallet/tapyrus_core_wallet_adapter'
|
33
|
-
autoload :ActiveRecordWalletAdapter, 'glueby/internal/wallet/active_record_wallet_adapter'
|
34
|
-
autoload :Errors, 'glueby/internal/wallet/errors'
|
35
|
-
|
36
|
-
class << self
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
def
|
78
|
-
|
79
|
-
end
|
80
|
-
|
81
|
-
def
|
82
|
-
wallet_adapter.
|
83
|
-
end
|
84
|
-
|
85
|
-
# @param [
|
86
|
-
# @param [
|
87
|
-
#
|
88
|
-
#
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
1
|
+
module Glueby
|
2
|
+
module Internal
|
3
|
+
# # Glueby::Internal::Wallet
|
4
|
+
#
|
5
|
+
# This module provides the way to deal about wallet that includes key management, address management, getting UTXOs.
|
6
|
+
#
|
7
|
+
# ## How to use
|
8
|
+
#
|
9
|
+
# First, you need to configure which wallet implementation is used in Glueby::Internal::Wallet. For now, below wallets are
|
10
|
+
# supported.
|
11
|
+
#
|
12
|
+
# * [Tapyrus Core](https://github.com/chaintope/tapyrus-core)
|
13
|
+
#
|
14
|
+
# Here shows an example to use Tapyrus Core wallet.
|
15
|
+
#
|
16
|
+
# ```ruby
|
17
|
+
# # Setup Tapyrus Core RPC connection
|
18
|
+
# config = {schema: 'http', host: '127.0.0.1', port: 12381, user: 'user', password: 'pass'}
|
19
|
+
# Glueby::Internal::RPC.configure(config)
|
20
|
+
#
|
21
|
+
# # Setup wallet adapter
|
22
|
+
# Glueby::Internal::Wallet.wallet_adapter = Glueby::Internal::Wallet::TapyrusCoreWalletAdapter.new
|
23
|
+
#
|
24
|
+
# # Create wallet
|
25
|
+
# wallet = Glueby::Internal::Wallet.create
|
26
|
+
# wallet.balance # => 0
|
27
|
+
# wallet.list_unspent
|
28
|
+
# ```
|
29
|
+
class Wallet
|
30
|
+
autoload :AbstractWalletAdapter, 'glueby/internal/wallet/abstract_wallet_adapter'
|
31
|
+
autoload :AR, 'glueby/internal/wallet/active_record'
|
32
|
+
autoload :TapyrusCoreWalletAdapter, 'glueby/internal/wallet/tapyrus_core_wallet_adapter'
|
33
|
+
autoload :ActiveRecordWalletAdapter, 'glueby/internal/wallet/active_record_wallet_adapter'
|
34
|
+
autoload :Errors, 'glueby/internal/wallet/errors'
|
35
|
+
|
36
|
+
class << self
|
37
|
+
def create(wallet_id = nil)
|
38
|
+
begin
|
39
|
+
wallet_id = wallet_adapter.create_wallet(wallet_id)
|
40
|
+
rescue Errors::WalletAlreadyCreated => _
|
41
|
+
# Ignore when wallet is already created.
|
42
|
+
end
|
43
|
+
new(wallet_id)
|
44
|
+
end
|
45
|
+
|
46
|
+
def load(wallet_id)
|
47
|
+
begin
|
48
|
+
wallet_adapter.load_wallet(wallet_id)
|
49
|
+
rescue Errors::WalletAlreadyLoaded => _
|
50
|
+
# Ignore when wallet is already loaded.
|
51
|
+
end
|
52
|
+
new(wallet_id)
|
53
|
+
end
|
54
|
+
|
55
|
+
def wallets
|
56
|
+
wallet_adapter.wallets.map { |id| new(id) }
|
57
|
+
end
|
58
|
+
|
59
|
+
def wallet_adapter=(adapter)
|
60
|
+
if adapter.is_a?(ActiveRecordWalletAdapter)
|
61
|
+
BlockSyncer.register_syncer(ActiveRecordWalletAdapter::Syncer)
|
62
|
+
else
|
63
|
+
BlockSyncer.unregister_syncer(ActiveRecordWalletAdapter::Syncer)
|
64
|
+
end
|
65
|
+
|
66
|
+
@wallet_adapter = adapter
|
67
|
+
end
|
68
|
+
|
69
|
+
def wallet_adapter
|
70
|
+
@wallet_adapter or
|
71
|
+
raise Errors::ShouldInitializeWalletAdapter, 'You should initialize wallet adapter using `Glueby::Internal::Wallet.wallet_adapter = some wallet adapter instance`.'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
attr_reader :id
|
76
|
+
|
77
|
+
def initialize(wallet_id)
|
78
|
+
@id = wallet_id
|
79
|
+
end
|
80
|
+
|
81
|
+
def balance(only_finalized = true)
|
82
|
+
wallet_adapter.balance(id, only_finalized)
|
83
|
+
end
|
84
|
+
|
85
|
+
# @param only_finalized [Boolean] The flag to get a UTXO with status only finalized
|
86
|
+
# @param label [String] This label is used to filtered the UTXOs with labeled if a key or Utxo is labeled.
|
87
|
+
# - If label is not specified (label=nil), all UTXOs will be returned.
|
88
|
+
# - If label=:unlabeled, only unlabeled UTXOs will be returned.
|
89
|
+
def list_unspent(only_finalized = true, label = nil)
|
90
|
+
wallet_adapter.list_unspent(id, only_finalized, label)
|
91
|
+
end
|
92
|
+
|
93
|
+
def delete
|
94
|
+
wallet_adapter.delete_wallet(id)
|
95
|
+
end
|
96
|
+
|
97
|
+
# @param [Tapyrus::Tx] tx The tx that is signed
|
98
|
+
# @param [Array<Hash>] prev_txs An array of hash that represents unbroadcasted transaction outputs used by signing tx
|
99
|
+
# @option prev_txs [String] :txid
|
100
|
+
# @option prev_txs [Integer] :vout
|
101
|
+
# @option prev_txs [String] :scriptPubkey
|
102
|
+
# @option prev_txs [Integer] :amount
|
103
|
+
# @param [Boolean] for_fee_provider_input The flag to notify whether the caller is FeeProvider and called for signing a input that is by FeeProvider.
|
104
|
+
def sign_tx(tx, prev_txs = [], for_fee_provider_input: false)
|
105
|
+
sighashtype = Tapyrus::SIGHASH_TYPE[:all]
|
106
|
+
|
107
|
+
if !for_fee_provider_input && Glueby.configuration.fee_provider_bears?
|
108
|
+
sighashtype |= Tapyrus::SIGHASH_TYPE[:anyonecanpay]
|
109
|
+
end
|
110
|
+
|
111
|
+
wallet_adapter.sign_tx(id, tx, prev_txs, sighashtype: sighashtype)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Broadcast a transaction via Tapyrus Core RPC
|
115
|
+
# @param [Tapyrus::Tx] tx The tx that would be broadcasted
|
116
|
+
# @option [Boolean] without_fee_provider The flag to avoid to use FeeProvider temporary.
|
117
|
+
# @param [Proc] block The block that is called before broadcasting. It can be used to handle tx that is modified by FeeProvider.
|
118
|
+
def broadcast(tx, without_fee_provider: false, &block)
|
119
|
+
tx = FeeProvider.provide(tx) if !without_fee_provider && Glueby.configuration.fee_provider_bears?
|
120
|
+
wallet_adapter.broadcast(id, tx, &block)
|
121
|
+
tx
|
122
|
+
end
|
123
|
+
|
124
|
+
def receive_address(label = nil)
|
125
|
+
wallet_adapter.receive_address(id, label)
|
126
|
+
end
|
127
|
+
|
128
|
+
def change_address
|
129
|
+
wallet_adapter.change_address(id)
|
130
|
+
end
|
131
|
+
|
132
|
+
def create_pubkey
|
133
|
+
wallet_adapter.create_pubkey(id)
|
134
|
+
end
|
135
|
+
|
136
|
+
def collect_uncolored_outputs(amount, label = nil, only_finalized = true)
|
137
|
+
utxos = list_unspent(only_finalized, label)
|
138
|
+
|
139
|
+
utxos.inject([0, []]) do |sum, output|
|
140
|
+
next sum if output[:color_id]
|
141
|
+
|
142
|
+
new_sum = sum[0] + output[:amount]
|
143
|
+
new_outputs = sum[1] << output
|
144
|
+
return [new_sum, new_outputs] if new_sum >= amount
|
145
|
+
|
146
|
+
[new_sum, new_outputs]
|
147
|
+
end
|
148
|
+
raise Glueby::Contract::Errors::InsufficientFunds
|
149
|
+
end
|
150
|
+
|
151
|
+
def get_addresses(label = nil)
|
152
|
+
wallet_adapter.get_addresses(id, label)
|
153
|
+
end
|
154
|
+
|
155
|
+
private
|
156
|
+
|
157
|
+
def wallet_adapter
|
158
|
+
self.class.wallet_adapter
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
data/lib/glueby/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module Glueby
|
2
|
-
VERSION = "0.4.
|
3
|
-
end
|
1
|
+
module Glueby
|
2
|
+
VERSION = "0.4.4"
|
3
|
+
end
|
data/lib/glueby.rb
CHANGED
@@ -1,49 +1,39 @@
|
|
1
|
-
require "glueby/version"
|
2
|
-
require 'tapyrus'
|
3
|
-
|
4
|
-
module Glueby
|
5
|
-
autoload :Contract, 'glueby/contract'
|
6
|
-
autoload :Generator, 'glueby/generator'
|
7
|
-
autoload :Wallet, 'glueby/wallet'
|
8
|
-
autoload :Internal, 'glueby/internal'
|
9
|
-
autoload :AR, 'glueby/active_record'
|
10
|
-
autoload :FeeProvider, 'glueby/fee_provider'
|
11
|
-
autoload :Configuration, 'glueby/configuration'
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
'
|
16
|
-
end
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
#
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
#
|
41
|
-
# @example
|
42
|
-
# Glueby.configure do |config|
|
43
|
-
# config.wallet_adapter = :activerecord
|
44
|
-
# config.rpc_config = { schema: 'http', host: '127.0.0.1', port: 12381, user: 'user', password: 'pass' }
|
45
|
-
# end
|
46
|
-
def self.configure
|
47
|
-
yield configuration if block_given?
|
48
|
-
end
|
49
|
-
end
|
1
|
+
require "glueby/version"
|
2
|
+
require 'tapyrus'
|
3
|
+
|
4
|
+
module Glueby
|
5
|
+
autoload :Contract, 'glueby/contract'
|
6
|
+
autoload :Generator, 'glueby/generator'
|
7
|
+
autoload :Wallet, 'glueby/wallet'
|
8
|
+
autoload :Internal, 'glueby/internal'
|
9
|
+
autoload :AR, 'glueby/active_record'
|
10
|
+
autoload :FeeProvider, 'glueby/fee_provider'
|
11
|
+
autoload :Configuration, 'glueby/configuration'
|
12
|
+
autoload :BlockSyncer, 'glueby/block_syncer'
|
13
|
+
|
14
|
+
if defined? ::Rails::Railtie
|
15
|
+
require 'glueby/railtie'
|
16
|
+
end
|
17
|
+
|
18
|
+
# Add prefix to activerecord table names
|
19
|
+
def self.table_name_prefix
|
20
|
+
'glueby_'
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns the global [Configuration](RSpec/Core/Configuration) object.
|
24
|
+
def self.configuration
|
25
|
+
@configuration ||= Glueby::Configuration.new
|
26
|
+
end
|
27
|
+
|
28
|
+
# Yields the global configuration to a block.
|
29
|
+
# @yield [Configuration] global configuration
|
30
|
+
#
|
31
|
+
# @example
|
32
|
+
# Glueby.configure do |config|
|
33
|
+
# config.wallet_adapter = :activerecord
|
34
|
+
# config.rpc_config = { schema: 'http', host: '127.0.0.1', port: 12381, user: 'user', password: 'pass' }
|
35
|
+
# end
|
36
|
+
def self.configure
|
37
|
+
yield configuration if block_given?
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
namespace :glueby do
|
2
|
+
namespace :contract do
|
3
|
+
namespace :block_syncer do
|
4
|
+
desc '[Deprecated use glueby:block_syncer:start instead] sync block into database'
|
5
|
+
task :start, [] => [:environment] do |_, _|
|
6
|
+
puts '[Deprecated] glueby:contract:block_syncer:start is deprecated. Use \'glueby:block_syncer:start\''
|
7
|
+
Rake::Task['glueby:block_syncer:start'].execute
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
namespace :glueby do
|
15
|
+
namespace :block_syncer do
|
16
|
+
desc 'sync block into database'
|
17
|
+
task :start, [] => [:environment] do |_, _|
|
18
|
+
latest_block_num = Glueby::Internal::RPC.client.getblockcount
|
19
|
+
synced_block = Glueby::AR::SystemInformation.synced_block_height
|
20
|
+
(synced_block.int_value + 1..latest_block_num).each do |height|
|
21
|
+
::ActiveRecord::Base.transaction do
|
22
|
+
Glueby::BlockSyncer.new(height).run
|
23
|
+
synced_block.update(info_value: height.to_s)
|
24
|
+
end
|
25
|
+
puts "success in synchronization (block height=#{height})"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,62 +1,40 @@
|
|
1
|
-
module Glueby
|
2
|
-
module Contract
|
3
|
-
module Task
|
4
|
-
module Timestamp
|
5
|
-
module_function
|
6
|
-
extend Glueby::Contract::TxBuilder
|
7
|
-
extend Glueby::Contract::Timestamp::Util
|
8
|
-
|
9
|
-
def create
|
10
|
-
timestamps = Glueby::Contract::AR::Timestamp.where(status: :init)
|
11
|
-
timestamps.each do |t|
|
12
|
-
begin
|
13
|
-
::ActiveRecord::Base.transaction do
|
14
|
-
wallet = Glueby::Wallet.load(t.wallet_id)
|
15
|
-
tx = create_tx(wallet, t.prefix, t.content_hash, Glueby::Contract::FixedFeeEstimator.new)
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
puts "broadcasted (id=#{t.id}, txid=#{tx.txid})"
|
20
|
-
end
|
21
|
-
rescue => e
|
22
|
-
puts "failed to broadcast (id=#{t.id}, reason=#{e.message})"
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
namespace :glueby do
|
49
|
-
namespace :contract do
|
50
|
-
namespace :timestamp do
|
51
|
-
desc 'create and broadcast glueby timestamp tx'
|
52
|
-
task :create, [] => [:environment] do |_, _|
|
53
|
-
Glueby::Contract::Task::Timestamp.create
|
54
|
-
end
|
55
|
-
|
56
|
-
desc 'confirm glueby timestamp tx'
|
57
|
-
task :confirm, [] => [:environment] do |_, _|
|
58
|
-
Glueby::Contract::Task::Timestamp.confirm
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
1
|
+
module Glueby
|
2
|
+
module Contract
|
3
|
+
module Task
|
4
|
+
module Timestamp
|
5
|
+
module_function
|
6
|
+
extend Glueby::Contract::TxBuilder
|
7
|
+
extend Glueby::Contract::Timestamp::Util
|
8
|
+
|
9
|
+
def create
|
10
|
+
timestamps = Glueby::Contract::AR::Timestamp.where(status: :init)
|
11
|
+
timestamps.each do |t|
|
12
|
+
begin
|
13
|
+
::ActiveRecord::Base.transaction do
|
14
|
+
wallet = Glueby::Wallet.load(t.wallet_id)
|
15
|
+
tx = create_tx(wallet, t.prefix, t.content_hash, Glueby::Contract::FixedFeeEstimator.new)
|
16
|
+
wallet.internal_wallet.broadcast(tx) do |tx|
|
17
|
+
t.update(txid: tx.txid, status: :unconfirmed)
|
18
|
+
end
|
19
|
+
puts "broadcasted (id=#{t.id}, txid=#{tx.txid})"
|
20
|
+
end
|
21
|
+
rescue => e
|
22
|
+
puts "failed to broadcast (id=#{t.id}, reason=#{e.message})"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
namespace :glueby do
|
32
|
+
namespace :contract do
|
33
|
+
namespace :timestamp do
|
34
|
+
desc 'create and broadcast glueby timestamp tx'
|
35
|
+
task :create, [] => [:environment] do |_, _|
|
36
|
+
Glueby::Contract::Task::Timestamp.create
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
62
40
|
end
|