glueby 0.4.4 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +463 -387
- data/glueby.gemspec +33 -33
- data/lib/generators/glueby/contract/templates/initializer.rb.erb +8 -8
- data/lib/generators/glueby/contract/templates/key_table.rb.erb +16 -16
- data/lib/generators/glueby/contract/templates/utxo_table.rb.erb +16 -16
- data/lib/glueby/block_syncer.rb +97 -97
- data/lib/glueby/configuration.rb +26 -2
- data/lib/glueby/contract/timestamp/syncer.rb +13 -13
- data/lib/glueby/contract/timestamp.rb +108 -102
- data/lib/glueby/contract/token.rb +270 -244
- data/lib/glueby/contract/tx_builder.rb +97 -30
- data/lib/glueby/fee_provider/tasks.rb +140 -140
- data/lib/glueby/fee_provider.rb +11 -0
- data/lib/glueby/internal/wallet/abstract_wallet_adapter.rb +151 -151
- data/lib/glueby/internal/wallet/active_record/utxo.rb +51 -51
- data/lib/glueby/internal/wallet/active_record_wallet_adapter/syncer.rb +13 -13
- data/lib/glueby/internal/wallet/active_record_wallet_adapter.rb +151 -151
- data/lib/glueby/internal/wallet/tapyrus_core_wallet_adapter.rb +186 -186
- data/lib/glueby/internal/wallet.rb +163 -162
- data/lib/glueby/railtie.rb +10 -9
- data/lib/glueby/utxo_provider/tasks.rb +135 -0
- data/lib/glueby/utxo_provider.rb +85 -0
- data/lib/glueby/version.rb +3 -3
- data/lib/glueby.rb +40 -39
- data/lib/tasks/glueby/block_syncer.rake +28 -28
- data/lib/tasks/glueby/contract/timestamp.rake +46 -39
- data/lib/tasks/glueby/fee_provider.rake +18 -18
- data/lib/tasks/glueby/utxo_provider.rake +18 -0
- metadata +5 -2
@@ -1,151 +1,151 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'securerandom'
|
4
|
-
|
5
|
-
module Glueby
|
6
|
-
module Internal
|
7
|
-
class Wallet
|
8
|
-
# ActiveRecordWalletAdapter
|
9
|
-
#
|
10
|
-
# This class represents a wallet adapter that use Active Record to manage wallet and utxos.
|
11
|
-
# To use this wallet adapter, you should do the following steps:
|
12
|
-
#
|
13
|
-
# (1) Generate migrations for wallets, keys, utxos tables.
|
14
|
-
# The generator `glueby:contract:wallet_adapter` is available for migration.
|
15
|
-
# ```
|
16
|
-
# rails g glueby:contract:wallet_adapter
|
17
|
-
# ```
|
18
|
-
# this generator generates 3 files to create tables used by ActiveRecordWalletAdatper.
|
19
|
-
# then, migrate them
|
20
|
-
# ```
|
21
|
-
# $ rails db:migrate
|
22
|
-
# ```
|
23
|
-
#
|
24
|
-
# (2) Add configuration for activerecord
|
25
|
-
# ```
|
26
|
-
# config = {adapter: 'activerecord', schema: 'http', host: '127.0.0.1', port: 12381, user: 'user', password: 'pass'}
|
27
|
-
# Glueby::Wallet.configure(config)
|
28
|
-
# ```
|
29
|
-
#
|
30
|
-
# (3) Generate wallet and receive address
|
31
|
-
# ```
|
32
|
-
# alice_wallet = Glueby::Wallet.create
|
33
|
-
# address = alice_wallet.internal_wallet.receive_address
|
34
|
-
# ```
|
35
|
-
# `Glueby::Internal::Wallet#receive_address` returns Base58 encoded Tapyrus address like '1CY6TSSARn8rAFD9chCghX5B7j4PKR8S1a'.
|
36
|
-
#
|
37
|
-
# (4) Send TPC to created address and import into wallet.
|
38
|
-
# In general, ActiveRecordWalletAdapter handle only utxos generated by glueby.
|
39
|
-
# So, to start to use wallet, some external utxo should be imported into the wallet first.
|
40
|
-
# This step should be done by external transaction without Glueby::Wallet, such as 'sendtoaddress' or 'generatetoaddress' RPC command of Tapyrus Core
|
41
|
-
# ```
|
42
|
-
# $ tapyrus-cli sendtoaddress 1CY6TSSARn8rAFD9chCghX5B7j4PKR8S1a 1
|
43
|
-
# 1740af9f65ffd8537bdd06ccfa911bf1f4d6833222807d29c99d72b47838917d
|
44
|
-
# ```
|
45
|
-
#
|
46
|
-
# then, import into wallet by rake task `glueby:contract:wallet_adapter:import_tx` or `glueby:contract:wallet_adapter:import_block`
|
47
|
-
# ```
|
48
|
-
# $ rails "glueby:contract:wallet_adapter:import_tx[1740af9f65ffd8537bdd06ccfa911bf1f4d6833222807d29c99d72b47838917d]""
|
49
|
-
# ```
|
50
|
-
#
|
51
|
-
# (5) You are ready to use ActiveRecordWalletAdatper, check `Glueby::Internal::Wallet#list_unspent` or `Glueby::Wallet#balances`
|
52
|
-
# ```
|
53
|
-
# alice_wallet = Glueby::Wallet.create
|
54
|
-
# alice_wallet.balances
|
55
|
-
# ```
|
56
|
-
class ActiveRecordWalletAdapter < AbstractWalletAdapter
|
57
|
-
|
58
|
-
autoload :Syncer, 'glueby/internal/wallet/active_record_wallet_adapter/syncer'
|
59
|
-
|
60
|
-
def create_wallet(wallet_id = nil)
|
61
|
-
wallet_id = SecureRandom.hex(16) unless wallet_id
|
62
|
-
begin
|
63
|
-
AR::Wallet.create!(wallet_id: wallet_id)
|
64
|
-
rescue ActiveRecord::RecordInvalid => _
|
65
|
-
raise Errors::WalletAlreadyCreated, "wallet_id '#{wallet_id}' is already exists"
|
66
|
-
end
|
67
|
-
wallet_id
|
68
|
-
end
|
69
|
-
|
70
|
-
def delete_wallet(wallet_id)
|
71
|
-
AR::Wallet.destroy_by(wallet_id: wallet_id)
|
72
|
-
end
|
73
|
-
|
74
|
-
def load_wallet(wallet_id)
|
75
|
-
raise Errors::WalletNotFound, "Wallet #{wallet_id} does not found" unless AR::Wallet.where(wallet_id: wallet_id).exists?
|
76
|
-
end
|
77
|
-
|
78
|
-
def unload_wallet(wallet_id)
|
79
|
-
end
|
80
|
-
|
81
|
-
def wallets
|
82
|
-
AR::Wallet.all.map(&:wallet_id).sort
|
83
|
-
end
|
84
|
-
|
85
|
-
def balance(wallet_id, only_finalized = true)
|
86
|
-
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
87
|
-
utxos = wallet.utxos
|
88
|
-
utxos = utxos.where(status: :finalized) if only_finalized
|
89
|
-
utxos.sum(&:value)
|
90
|
-
end
|
91
|
-
|
92
|
-
def list_unspent(wallet_id, only_finalized = true, label = nil)
|
93
|
-
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
94
|
-
utxos = wallet.utxos
|
95
|
-
utxos = utxos.where(status: :finalized) if only_finalized
|
96
|
-
utxos = utxos.where(label: label) if label && (label != :unlabeled)
|
97
|
-
utxos = utxos.where(label: nil) if label == :unlabeled
|
98
|
-
utxos.map do |utxo|
|
99
|
-
{
|
100
|
-
txid: utxo.txid,
|
101
|
-
vout: utxo.index,
|
102
|
-
script_pubkey: utxo.script_pubkey,
|
103
|
-
color_id: utxo.color_id,
|
104
|
-
amount: utxo.value,
|
105
|
-
finalized: utxo.status == 'finalized'
|
106
|
-
}
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def sign_tx(wallet_id, tx, prevtxs = [], sighashtype: Tapyrus::SIGHASH_TYPE[:all])
|
111
|
-
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
112
|
-
wallet.sign(tx, prevtxs, sighashtype: sighashtype)
|
113
|
-
end
|
114
|
-
|
115
|
-
def broadcast(wallet_id, tx, &block)
|
116
|
-
::ActiveRecord::Base.transaction do
|
117
|
-
AR::Utxo.destroy_for_inputs(tx)
|
118
|
-
AR::Utxo.create_or_update_for_outputs(tx, status: :broadcasted)
|
119
|
-
block.call(tx) if block
|
120
|
-
Glueby::Internal::RPC.client.sendrawtransaction(tx.to_hex)
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
def receive_address(wallet_id, label = nil)
|
125
|
-
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
126
|
-
key = wallet.keys.create(purpose: :receive, label: label)
|
127
|
-
key.address
|
128
|
-
end
|
129
|
-
|
130
|
-
def change_address(wallet_id)
|
131
|
-
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
132
|
-
key = wallet.keys.create(purpose: :change)
|
133
|
-
key.address
|
134
|
-
end
|
135
|
-
|
136
|
-
def create_pubkey(wallet_id)
|
137
|
-
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
138
|
-
key = wallet.keys.create(purpose: :receive)
|
139
|
-
Tapyrus::Key.new(pubkey: key.public_key)
|
140
|
-
end
|
141
|
-
|
142
|
-
def get_addresses(wallet_id, label = nil)
|
143
|
-
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
144
|
-
keys = wallet.keys
|
145
|
-
keys = keys.where(label: label) if label
|
146
|
-
keys.map(&:address)
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'securerandom'
|
4
|
+
|
5
|
+
module Glueby
|
6
|
+
module Internal
|
7
|
+
class Wallet
|
8
|
+
# ActiveRecordWalletAdapter
|
9
|
+
#
|
10
|
+
# This class represents a wallet adapter that use Active Record to manage wallet and utxos.
|
11
|
+
# To use this wallet adapter, you should do the following steps:
|
12
|
+
#
|
13
|
+
# (1) Generate migrations for wallets, keys, utxos tables.
|
14
|
+
# The generator `glueby:contract:wallet_adapter` is available for migration.
|
15
|
+
# ```
|
16
|
+
# rails g glueby:contract:wallet_adapter
|
17
|
+
# ```
|
18
|
+
# this generator generates 3 files to create tables used by ActiveRecordWalletAdatper.
|
19
|
+
# then, migrate them
|
20
|
+
# ```
|
21
|
+
# $ rails db:migrate
|
22
|
+
# ```
|
23
|
+
#
|
24
|
+
# (2) Add configuration for activerecord
|
25
|
+
# ```
|
26
|
+
# config = {adapter: 'activerecord', schema: 'http', host: '127.0.0.1', port: 12381, user: 'user', password: 'pass'}
|
27
|
+
# Glueby::Wallet.configure(config)
|
28
|
+
# ```
|
29
|
+
#
|
30
|
+
# (3) Generate wallet and receive address
|
31
|
+
# ```
|
32
|
+
# alice_wallet = Glueby::Wallet.create
|
33
|
+
# address = alice_wallet.internal_wallet.receive_address
|
34
|
+
# ```
|
35
|
+
# `Glueby::Internal::Wallet#receive_address` returns Base58 encoded Tapyrus address like '1CY6TSSARn8rAFD9chCghX5B7j4PKR8S1a'.
|
36
|
+
#
|
37
|
+
# (4) Send TPC to created address and import into wallet.
|
38
|
+
# In general, ActiveRecordWalletAdapter handle only utxos generated by glueby.
|
39
|
+
# So, to start to use wallet, some external utxo should be imported into the wallet first.
|
40
|
+
# This step should be done by external transaction without Glueby::Wallet, such as 'sendtoaddress' or 'generatetoaddress' RPC command of Tapyrus Core
|
41
|
+
# ```
|
42
|
+
# $ tapyrus-cli sendtoaddress 1CY6TSSARn8rAFD9chCghX5B7j4PKR8S1a 1
|
43
|
+
# 1740af9f65ffd8537bdd06ccfa911bf1f4d6833222807d29c99d72b47838917d
|
44
|
+
# ```
|
45
|
+
#
|
46
|
+
# then, import into wallet by rake task `glueby:contract:wallet_adapter:import_tx` or `glueby:contract:wallet_adapter:import_block`
|
47
|
+
# ```
|
48
|
+
# $ rails "glueby:contract:wallet_adapter:import_tx[1740af9f65ffd8537bdd06ccfa911bf1f4d6833222807d29c99d72b47838917d]""
|
49
|
+
# ```
|
50
|
+
#
|
51
|
+
# (5) You are ready to use ActiveRecordWalletAdatper, check `Glueby::Internal::Wallet#list_unspent` or `Glueby::Wallet#balances`
|
52
|
+
# ```
|
53
|
+
# alice_wallet = Glueby::Wallet.create
|
54
|
+
# alice_wallet.balances
|
55
|
+
# ```
|
56
|
+
class ActiveRecordWalletAdapter < AbstractWalletAdapter
|
57
|
+
|
58
|
+
autoload :Syncer, 'glueby/internal/wallet/active_record_wallet_adapter/syncer'
|
59
|
+
|
60
|
+
def create_wallet(wallet_id = nil)
|
61
|
+
wallet_id = SecureRandom.hex(16) unless wallet_id
|
62
|
+
begin
|
63
|
+
AR::Wallet.create!(wallet_id: wallet_id)
|
64
|
+
rescue ActiveRecord::RecordInvalid => _
|
65
|
+
raise Errors::WalletAlreadyCreated, "wallet_id '#{wallet_id}' is already exists"
|
66
|
+
end
|
67
|
+
wallet_id
|
68
|
+
end
|
69
|
+
|
70
|
+
def delete_wallet(wallet_id)
|
71
|
+
AR::Wallet.destroy_by(wallet_id: wallet_id)
|
72
|
+
end
|
73
|
+
|
74
|
+
def load_wallet(wallet_id)
|
75
|
+
raise Errors::WalletNotFound, "Wallet #{wallet_id} does not found" unless AR::Wallet.where(wallet_id: wallet_id).exists?
|
76
|
+
end
|
77
|
+
|
78
|
+
def unload_wallet(wallet_id)
|
79
|
+
end
|
80
|
+
|
81
|
+
def wallets
|
82
|
+
AR::Wallet.all.map(&:wallet_id).sort
|
83
|
+
end
|
84
|
+
|
85
|
+
def balance(wallet_id, only_finalized = true)
|
86
|
+
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
87
|
+
utxos = wallet.utxos
|
88
|
+
utxos = utxos.where(status: :finalized) if only_finalized
|
89
|
+
utxos.sum(&:value)
|
90
|
+
end
|
91
|
+
|
92
|
+
def list_unspent(wallet_id, only_finalized = true, label = nil)
|
93
|
+
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
94
|
+
utxos = wallet.utxos
|
95
|
+
utxos = utxos.where(status: :finalized) if only_finalized
|
96
|
+
utxos = utxos.where(label: label) if label && (label != :unlabeled)
|
97
|
+
utxos = utxos.where(label: nil) if label == :unlabeled
|
98
|
+
utxos.map do |utxo|
|
99
|
+
{
|
100
|
+
txid: utxo.txid,
|
101
|
+
vout: utxo.index,
|
102
|
+
script_pubkey: utxo.script_pubkey,
|
103
|
+
color_id: utxo.color_id,
|
104
|
+
amount: utxo.value,
|
105
|
+
finalized: utxo.status == 'finalized'
|
106
|
+
}
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def sign_tx(wallet_id, tx, prevtxs = [], sighashtype: Tapyrus::SIGHASH_TYPE[:all])
|
111
|
+
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
112
|
+
wallet.sign(tx, prevtxs, sighashtype: sighashtype)
|
113
|
+
end
|
114
|
+
|
115
|
+
def broadcast(wallet_id, tx, &block)
|
116
|
+
::ActiveRecord::Base.transaction do
|
117
|
+
AR::Utxo.destroy_for_inputs(tx)
|
118
|
+
AR::Utxo.create_or_update_for_outputs(tx, status: :broadcasted)
|
119
|
+
block.call(tx) if block
|
120
|
+
Glueby::Internal::RPC.client.sendrawtransaction(tx.to_hex)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def receive_address(wallet_id, label = nil)
|
125
|
+
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
126
|
+
key = wallet.keys.create(purpose: :receive, label: label)
|
127
|
+
key.address
|
128
|
+
end
|
129
|
+
|
130
|
+
def change_address(wallet_id)
|
131
|
+
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
132
|
+
key = wallet.keys.create(purpose: :change)
|
133
|
+
key.address
|
134
|
+
end
|
135
|
+
|
136
|
+
def create_pubkey(wallet_id)
|
137
|
+
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
138
|
+
key = wallet.keys.create(purpose: :receive)
|
139
|
+
Tapyrus::Key.new(pubkey: key.public_key)
|
140
|
+
end
|
141
|
+
|
142
|
+
def get_addresses(wallet_id, label = nil)
|
143
|
+
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
144
|
+
keys = wallet.keys
|
145
|
+
keys = keys.where(label: label) if label
|
146
|
+
keys.map(&:address)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|