glueby 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +35 -0
- data/Gemfile +1 -0
- data/README.md +111 -6
- data/glueby.gemspec +1 -1
- data/lib/generators/glueby/contract/reissuable_token_generator.rb +26 -0
- data/lib/generators/glueby/contract/templates/key_table.rb.erb +3 -3
- data/lib/generators/glueby/contract/templates/reissuable_token_table.rb.erb +10 -0
- data/lib/generators/glueby/contract/templates/system_information_table.rb.erb +2 -2
- data/lib/generators/glueby/contract/templates/timestamp_table.rb.erb +1 -1
- data/lib/generators/glueby/contract/templates/utxo_table.rb.erb +2 -2
- data/lib/generators/glueby/contract/templates/wallet_table.rb.erb +2 -2
- data/lib/glueby.rb +25 -0
- data/lib/glueby/configuration.rb +62 -0
- data/lib/glueby/contract.rb +2 -2
- data/lib/glueby/contract/active_record.rb +1 -0
- data/lib/glueby/contract/active_record/reissuable_token.rb +26 -0
- data/lib/glueby/contract/fee_estimator.rb +38 -0
- data/lib/glueby/contract/payment.rb +4 -4
- data/lib/glueby/contract/timestamp.rb +6 -6
- data/lib/glueby/contract/token.rb +69 -22
- data/lib/glueby/contract/tx_builder.rb +22 -19
- data/lib/glueby/fee_provider.rb +73 -0
- data/lib/glueby/fee_provider/tasks.rb +136 -0
- data/lib/glueby/generator/migrate_generator.rb +1 -1
- data/lib/glueby/internal/wallet.rb +28 -4
- data/lib/glueby/internal/wallet/abstract_wallet_adapter.rb +18 -3
- data/lib/glueby/internal/wallet/active_record/wallet.rb +15 -5
- data/lib/glueby/internal/wallet/active_record_wallet_adapter.rb +15 -5
- data/lib/glueby/internal/wallet/errors.rb +3 -0
- data/lib/glueby/internal/wallet/tapyrus_core_wallet_adapter.rb +36 -11
- data/lib/glueby/version.rb +1 -1
- data/lib/glueby/wallet.rb +3 -2
- data/lib/tasks/glueby/contract/timestamp.rake +1 -1
- data/lib/tasks/glueby/fee_provider.rake +13 -0
- metadata +16 -9
- data/.travis.yml +0 -7
- data/lib/glueby/contract/fee_provider.rb +0 -21
@@ -0,0 +1,136 @@
|
|
1
|
+
module Glueby
|
2
|
+
class FeeProvider
|
3
|
+
class Tasks
|
4
|
+
attr_reader :fee_provider
|
5
|
+
|
6
|
+
STATUS = {
|
7
|
+
# FeeProvider is ready to pay fees.
|
8
|
+
ready: 'Ready',
|
9
|
+
# FeeProvider is ready to pay fees, but it doesn't have enough amount to fill the UTXO pool by UTXOs which is for paying fees.
|
10
|
+
insufficient_amount: 'Insufficient Amount',
|
11
|
+
# FeeProvider is not ready to pay fees. It has no UTXOs for paying fee and amounts.
|
12
|
+
not_ready: 'Not Ready'
|
13
|
+
}
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@fee_provider = Glueby::FeeProvider.new
|
17
|
+
end
|
18
|
+
|
19
|
+
# Create UTXOs for paying fee from TPC amount of the wallet FeeProvider has. Then show the status.
|
20
|
+
#
|
21
|
+
# About the UTXO Pool
|
22
|
+
# FeeProvider have the UTXO pool. the pool is manged to keep some number of UTXOs that have fixed fee value. The
|
23
|
+
# value is configurable by :fixed_fee. This method do the management to the pool.
|
24
|
+
def manage_utxo_pool
|
25
|
+
txb = Tapyrus::TxBuilder.new
|
26
|
+
|
27
|
+
sum, utxos = collect_outputs
|
28
|
+
return if utxos.empty?
|
29
|
+
|
30
|
+
utxos.each { |utxo| txb.add_utxo(utxo) }
|
31
|
+
address = wallet.receive_address
|
32
|
+
|
33
|
+
shortage = [fee_provider.utxo_pool_size - current_utxo_pool_size, 0].max
|
34
|
+
can_create = (sum - fee_provider.fixed_fee) / fee_provider.fixed_fee
|
35
|
+
fee_outputs_count_to_be_created = [shortage, can_create].min
|
36
|
+
|
37
|
+
return if fee_outputs_count_to_be_created == 0
|
38
|
+
|
39
|
+
fee_outputs_count_to_be_created.times do
|
40
|
+
txb.pay(address, fee_provider.fixed_fee)
|
41
|
+
end
|
42
|
+
|
43
|
+
tx = txb.change_address(address)
|
44
|
+
.fee(fee_provider.fixed_fee)
|
45
|
+
.build
|
46
|
+
tx = wallet.sign_tx(tx)
|
47
|
+
wallet.broadcast(tx)
|
48
|
+
ensure
|
49
|
+
status
|
50
|
+
end
|
51
|
+
|
52
|
+
# Show the status of the UTXO pool
|
53
|
+
def status
|
54
|
+
status = :ready
|
55
|
+
|
56
|
+
if current_utxo_pool_size < fee_provider.utxo_pool_size
|
57
|
+
if tpc_amount < value_to_fill_utxo_pool
|
58
|
+
status = :insufficient_amount
|
59
|
+
message = <<~MESSAGE
|
60
|
+
1. Please replenishment TPC which is for paying fee to FeeProvider.
|
61
|
+
FeeProvider needs #{value_to_fill_utxo_pool} tapyrus at least for paying 20 transaction fees.
|
62
|
+
FeeProvider wallet's address is '#{wallet.receive_address}'
|
63
|
+
2. Then create UTXOs for paying in UTXO pool with 'rake glueby:fee_provider:manage_utxo_pool'
|
64
|
+
MESSAGE
|
65
|
+
else
|
66
|
+
message = "Please create UTXOs for paying in UTXO pool with 'rake glueby:fee_provider:manage_utxo_pool'\n"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
status = :not_ready if current_utxo_pool_size == 0
|
71
|
+
|
72
|
+
puts <<~EOS
|
73
|
+
Status: #{STATUS[status]}
|
74
|
+
TPC amount: #{delimit(tpc_amount)}
|
75
|
+
UTXO pool size: #{delimit(current_utxo_pool_size)}
|
76
|
+
#{"\n" if message}#{message}
|
77
|
+
Configuration:
|
78
|
+
fixed_fee = #{delimit(fee_provider.fixed_fee)}
|
79
|
+
utxo_pool_size = #{delimit(fee_provider.utxo_pool_size)}
|
80
|
+
EOS
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def check_wallet_amount!
|
86
|
+
if tpc_amount < fee_provider.fixed_fee
|
87
|
+
raise InsufficientTPC, <<~MESSAGE
|
88
|
+
FeeProvider has insufficient TPC to create fee outputs to fill the UTXO pool.
|
89
|
+
1. Please replenishment TPC which is for paying fee to FeeProvider. FeeProvider needs #{fee_provider.utxo_pool_size * fee_provider.fixed_fee} tapyrus at least. FeeProvider wallet's address is '#{wallet.receive_address}'
|
90
|
+
2. Then create UTXOs for paying in UTXO pool with 'rake glueby:fee_provider:manage_utxo_pool'
|
91
|
+
MESSAGE
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def tpc_amount
|
96
|
+
wallet.balance(false)
|
97
|
+
end
|
98
|
+
|
99
|
+
def collect_outputs
|
100
|
+
wallet.list_unspent.inject([0, []]) do |sum, output|
|
101
|
+
next sum if output[:color_id] || output[:amount] == fee_provider.fixed_fee
|
102
|
+
|
103
|
+
new_sum = sum[0] + output[:amount]
|
104
|
+
new_outputs = sum[1] << {
|
105
|
+
txid: output[:txid],
|
106
|
+
script_pubkey: output[:script_pubkey],
|
107
|
+
value: output[:amount],
|
108
|
+
index: output[:vout] ,
|
109
|
+
finalized: output[:finalized]
|
110
|
+
}
|
111
|
+
return [new_sum, new_outputs] if new_sum >= value_to_fill_utxo_pool
|
112
|
+
|
113
|
+
[new_sum, new_outputs]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def current_utxo_pool_size
|
118
|
+
wallet
|
119
|
+
.list_unspent(false)
|
120
|
+
.count { |o| !o[:color_id] && o[:amount] == fee_provider.fixed_fee }
|
121
|
+
end
|
122
|
+
|
123
|
+
def value_to_fill_utxo_pool
|
124
|
+
fee_provider.fixed_fee * (fee_provider.utxo_pool_size + 1) # +1 is for paying fee
|
125
|
+
end
|
126
|
+
|
127
|
+
def wallet
|
128
|
+
fee_provider.wallet
|
129
|
+
end
|
130
|
+
|
131
|
+
def delimit(num)
|
132
|
+
num.to_s.reverse.scan(/.{1,3}/).join('_').reverse
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -36,8 +36,13 @@ module Glueby
|
|
36
36
|
class << self
|
37
37
|
attr_writer :wallet_adapter
|
38
38
|
|
39
|
-
def create
|
40
|
-
|
39
|
+
def create(wallet_id = nil)
|
40
|
+
begin
|
41
|
+
wallet_id = wallet_adapter.create_wallet(wallet_id)
|
42
|
+
rescue Errors::WalletAlreadyCreated => _
|
43
|
+
# Ignore when wallet is already created.
|
44
|
+
end
|
45
|
+
new(wallet_id)
|
41
46
|
end
|
42
47
|
|
43
48
|
def load(wallet_id)
|
@@ -77,12 +82,27 @@ module Glueby
|
|
77
82
|
wallet_adapter.delete_wallet(id)
|
78
83
|
end
|
79
84
|
|
80
|
-
|
81
|
-
|
85
|
+
# @param [Tapyrus::Tx] tx The tx that is signed
|
86
|
+
# @param [Array<Hash>] prev_txs An array of hash that represents unbroadcasted transaction outputs used by signing tx
|
87
|
+
# @option prev_txs [String] :txid
|
88
|
+
# @option prev_txs [Integer] :vout
|
89
|
+
# @option prev_txs [String] :scriptPubkey
|
90
|
+
# @option prev_txs [Integer] :amount
|
91
|
+
# @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.
|
92
|
+
def sign_tx(tx, prev_txs = [], for_fee_provider_input: false)
|
93
|
+
sighashtype = Tapyrus::SIGHASH_TYPE[:all]
|
94
|
+
|
95
|
+
if !for_fee_provider_input && Glueby.configuration.fee_provider_bears?
|
96
|
+
sighashtype |= Tapyrus::SIGHASH_TYPE[:anyonecanpay]
|
97
|
+
end
|
98
|
+
|
99
|
+
wallet_adapter.sign_tx(id, tx, prev_txs, sighashtype: sighashtype)
|
82
100
|
end
|
83
101
|
|
84
102
|
def broadcast(tx)
|
103
|
+
tx = FeeProvider.provide(tx) if Glueby.configuration.fee_provider_bears?
|
85
104
|
wallet_adapter.broadcast(id, tx)
|
105
|
+
tx
|
86
106
|
end
|
87
107
|
|
88
108
|
def receive_address
|
@@ -112,6 +132,10 @@ module Glueby
|
|
112
132
|
raise Glueby::Contract::Errors::InsufficientFunds
|
113
133
|
end
|
114
134
|
|
135
|
+
def get_addresses
|
136
|
+
wallet_adapter.get_addresses(id)
|
137
|
+
end
|
138
|
+
|
115
139
|
private
|
116
140
|
|
117
141
|
def wallet_adapter
|
@@ -7,8 +7,10 @@ module Glueby
|
|
7
7
|
class AbstractWalletAdapter
|
8
8
|
# Creates a new wallet inside the wallet component and returns `wallet_id`. The created
|
9
9
|
# wallet is loaded from at first.
|
10
|
+
# @params [String] wallet_id - Option. The wallet id that if for the wallet to be created. If this is nil, wallet adapter generates it.
|
10
11
|
# @return [String] wallet_id
|
11
|
-
|
12
|
+
# @raise [Glueby::Internal::Wallet::Errors::WalletAlreadyCreated] when the specified wallet has been already created.
|
13
|
+
def create_wallet(wallet_id = nil)
|
12
14
|
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
13
15
|
end
|
14
16
|
|
@@ -32,6 +34,7 @@ module Glueby
|
|
32
34
|
#
|
33
35
|
# @param [String] wallet_id - The wallet id that is offered by `create_wallet()` method.
|
34
36
|
# @raise [Glueby::Internal::Wallet::Errors::WalletAlreadyLoaded] when the specified wallet has been already loaded.
|
37
|
+
# @raise [Glueby::Internal::Wallet::Errors::WalletNotFound] when the specified wallet is not found.
|
35
38
|
def load_wallet(wallet_id)
|
36
39
|
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
37
40
|
end
|
@@ -83,10 +86,12 @@ module Glueby
|
|
83
86
|
#
|
84
87
|
# @param [String] wallet_id - The wallet id that is offered by `create_wallet()` method.
|
85
88
|
# @param [Tapyrus::Tx] tx - The transaction will be signed.
|
86
|
-
# @param [Array] prevtxs array of hash that represents unbroadcasted transaction outputs used by signing tx.
|
89
|
+
# @param [Array] prevtxs - array of hash that represents unbroadcasted transaction outputs used by signing tx.
|
87
90
|
# Each hash has `txid`, `vout`, `scriptPubKey`, `amount` fields.
|
91
|
+
# @param [Integer] sighashtype - The sighash flag for each signature that would be produced here.
|
88
92
|
# @return [Tapyrus::Tx]
|
89
|
-
|
93
|
+
# @raise [Glueby::Internal::Wallet::Errors::InvalidSighashType] when the specified sighashtype is invalid
|
94
|
+
def sign_tx(wallet_id, tx, prevtxs = [], sighashtype: Tapyrus::SIGHASH_TYPE[:all])
|
90
95
|
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
91
96
|
end
|
92
97
|
|
@@ -125,6 +130,16 @@ module Glueby
|
|
125
130
|
def create_pubkey(wallet_id)
|
126
131
|
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
127
132
|
end
|
133
|
+
|
134
|
+
# Returns an array of addresses
|
135
|
+
#
|
136
|
+
# This method is expected to return the list of addresses that wallet has.
|
137
|
+
#
|
138
|
+
# @param [String] wallet_id - The wallet id that is offered by `create_wallet()` method.
|
139
|
+
# @return [Array<String>] array of P2PKH address
|
140
|
+
def get_addresses(wallet_id)
|
141
|
+
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
|
142
|
+
end
|
128
143
|
end
|
129
144
|
end
|
130
145
|
end
|
@@ -13,13 +13,16 @@ module Glueby
|
|
13
13
|
|
14
14
|
# @param [Tapyrus::Tx] tx
|
15
15
|
# @param [Array] prevtxs array of outputs
|
16
|
-
|
16
|
+
# @param [Integer] sighashtype
|
17
|
+
def sign(tx, prevtxs = [], sighashtype: Tapyrus::SIGHASH_TYPE[:all])
|
18
|
+
validate_sighashtype!(sighashtype)
|
19
|
+
|
17
20
|
tx.inputs.each.with_index do |input, index|
|
18
21
|
script_pubkey = script_for_input(input, prevtxs)
|
19
22
|
next unless script_pubkey
|
20
23
|
key = Key.key_for_script(script_pubkey)
|
21
24
|
next unless key
|
22
|
-
sign_tx_for_p2pkh(tx, index, key, script_pubkey)
|
25
|
+
sign_tx_for_p2pkh(tx, index, key, script_pubkey, sighashtype)
|
23
26
|
end
|
24
27
|
tx
|
25
28
|
end
|
@@ -30,9 +33,9 @@ module Glueby
|
|
30
33
|
|
31
34
|
private
|
32
35
|
|
33
|
-
def sign_tx_for_p2pkh(tx, index, key, script_pubkey)
|
34
|
-
sighash = tx.sighash_for_input(index, script_pubkey)
|
35
|
-
sig = key.sign(sighash) + [
|
36
|
+
def sign_tx_for_p2pkh(tx, index, key, script_pubkey, sighashtype)
|
37
|
+
sighash = tx.sighash_for_input(index, script_pubkey, hash_type: sighashtype)
|
38
|
+
sig = key.sign(sighash) + [sighashtype].pack('C')
|
36
39
|
script_sig = Tapyrus::Script.parse_from_payload(Tapyrus::Script.pack_pushdata(sig) + Tapyrus::Script.pack_pushdata(key.public_key.htb))
|
37
40
|
tx.inputs[index].script_sig = script_sig
|
38
41
|
end
|
@@ -47,6 +50,13 @@ module Glueby
|
|
47
50
|
Tapyrus::Script.parse_from_payload(output[:scriptPubKey].htb) if output
|
48
51
|
end
|
49
52
|
end
|
53
|
+
|
54
|
+
def validate_sighashtype!(sighashtype)
|
55
|
+
hash_type = sighashtype & (~(Tapyrus::SIGHASH_TYPE[:anyonecanpay]))
|
56
|
+
if hash_type < Tapyrus::SIGHASH_TYPE[:all] || hash_type > Tapyrus::SIGHASH_TYPE[:single]
|
57
|
+
raise Errors::InvalidSighashType, "Invalid sighash type '#{sighashtype}'"
|
58
|
+
end
|
59
|
+
end
|
50
60
|
end
|
51
61
|
end
|
52
62
|
end
|
@@ -54,9 +54,13 @@ module Glueby
|
|
54
54
|
# alice_wallet.balances
|
55
55
|
# ```
|
56
56
|
class ActiveRecordWalletAdapter < AbstractWalletAdapter
|
57
|
-
def create_wallet
|
58
|
-
wallet_id = SecureRandom.hex(16)
|
59
|
-
|
57
|
+
def create_wallet(wallet_id = nil)
|
58
|
+
wallet_id = SecureRandom.hex(16) unless wallet_id
|
59
|
+
begin
|
60
|
+
AR::Wallet.create!(wallet_id: wallet_id)
|
61
|
+
rescue ActiveRecord::RecordInvalid => _
|
62
|
+
raise Errors::WalletAlreadyCreated, "wallet_id '#{wallet_id}' is already exists"
|
63
|
+
end
|
60
64
|
wallet_id
|
61
65
|
end
|
62
66
|
|
@@ -65,6 +69,7 @@ module Glueby
|
|
65
69
|
end
|
66
70
|
|
67
71
|
def load_wallet(wallet_id)
|
72
|
+
raise Errors::WalletNotFound, "Wallet #{wallet_id} does not found" unless AR::Wallet.where(wallet_id: wallet_id).exists?
|
68
73
|
end
|
69
74
|
|
70
75
|
def unload_wallet(wallet_id)
|
@@ -97,9 +102,9 @@ module Glueby
|
|
97
102
|
end
|
98
103
|
end
|
99
104
|
|
100
|
-
def sign_tx(wallet_id, tx, prevtxs = [])
|
105
|
+
def sign_tx(wallet_id, tx, prevtxs = [], sighashtype: Tapyrus::SIGHASH_TYPE[:all])
|
101
106
|
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
102
|
-
wallet.sign(tx, prevtxs)
|
107
|
+
wallet.sign(tx, prevtxs, sighashtype: sighashtype)
|
103
108
|
end
|
104
109
|
|
105
110
|
def broadcast(wallet_id, tx)
|
@@ -127,6 +132,11 @@ module Glueby
|
|
127
132
|
key = wallet.keys.create(purpose: :receive)
|
128
133
|
Tapyrus::Key.new(pubkey: key.public_key)
|
129
134
|
end
|
135
|
+
|
136
|
+
def get_addresses(wallet_id)
|
137
|
+
wallet = AR::Wallet.find_by(wallet_id: wallet_id)
|
138
|
+
wallet.keys.map(&:address)
|
139
|
+
end
|
130
140
|
end
|
131
141
|
end
|
132
142
|
end
|
@@ -5,6 +5,9 @@ module Glueby
|
|
5
5
|
class ShouldInitializeWalletAdapter < StandardError; end
|
6
6
|
class WalletUnloaded < StandardError; end
|
7
7
|
class WalletAlreadyLoaded < StandardError; end
|
8
|
+
class WalletAlreadyCreated < StandardError; end
|
9
|
+
class WalletNotFound < StandardError; end
|
10
|
+
class InvalidSighashType < StandardError; end
|
8
11
|
end
|
9
12
|
end
|
10
13
|
end
|
@@ -28,9 +28,18 @@ module Glueby
|
|
28
28
|
RPC_WALLET_ERROR_ERROR_CODE = -4 # Unspecified problem with wallet (key not found etc.)
|
29
29
|
RPC_WALLET_NOT_FOUND_ERROR_CODE = -18 # Invalid wallet specified
|
30
30
|
|
31
|
-
def create_wallet
|
32
|
-
wallet_id = SecureRandom.hex(16)
|
33
|
-
|
31
|
+
def create_wallet(wallet_id = nil)
|
32
|
+
wallet_id = SecureRandom.hex(16) unless wallet_id
|
33
|
+
begin
|
34
|
+
RPC.client.createwallet(wallet_name(wallet_id))
|
35
|
+
rescue Tapyrus::RPC::Error => ex
|
36
|
+
if ex.rpc_error['code'] == RPC_WALLET_ERROR_ERROR_CODE && /Wallet wallet-wallet already exists\./ =~ ex.rpc_error['message']
|
37
|
+
raise Errors::WalletAlreadyCreated, "Wallet #{wallet_id} has been already created."
|
38
|
+
else
|
39
|
+
raise ex
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
34
43
|
wallet_id
|
35
44
|
end
|
36
45
|
|
@@ -42,10 +51,11 @@ module Glueby
|
|
42
51
|
|
43
52
|
def load_wallet(wallet_id)
|
44
53
|
RPC.client.loadwallet(wallet_name(wallet_id))
|
45
|
-
rescue
|
46
|
-
|
47
|
-
if json.is_a?(Hash) && json['code'] == RPC_WALLET_ERROR_ERROR_CODE && /Duplicate -wallet filename specified/ =~ ex.message
|
54
|
+
rescue Tapyrus::RPC::Error => ex
|
55
|
+
if ex.rpc_error['code'] == RPC_WALLET_ERROR_ERROR_CODE && /Duplicate -wallet filename specified/ =~ ex.rpc_error['message']
|
48
56
|
raise Errors::WalletAlreadyLoaded, "Wallet #{wallet_id} has been already loaded."
|
57
|
+
elsif ex.rpc_error['code'] == RPC_WALLET_NOT_FOUND_ERROR_CODE
|
58
|
+
raise Errors::WalletNotFound, "Wallet #{wallet_id} does not found"
|
49
59
|
else
|
50
60
|
raise ex
|
51
61
|
end
|
@@ -95,9 +105,9 @@ module Glueby
|
|
95
105
|
end
|
96
106
|
end
|
97
107
|
|
98
|
-
def sign_tx(wallet_id, tx, prevtxs = [])
|
108
|
+
def sign_tx(wallet_id, tx, prevtxs = [], sighashtype: Tapyrus::SIGHASH_TYPE[:all])
|
99
109
|
perform_as(wallet_id) do |client|
|
100
|
-
res = client.signrawtransactionwithwallet(tx.to_hex, prevtxs)
|
110
|
+
res = client.signrawtransactionwithwallet(tx.to_hex, prevtxs, encode_sighashtype(sighashtype))
|
101
111
|
if res['complete']
|
102
112
|
Tapyrus::Tx.parse_from_payload(res['hex'].htb)
|
103
113
|
else
|
@@ -138,9 +148,8 @@ module Glueby
|
|
138
148
|
RPC.perform_as(wallet_name(wallet_id)) do |client|
|
139
149
|
begin
|
140
150
|
yield(client)
|
141
|
-
rescue
|
142
|
-
|
143
|
-
if json.is_a?(Hash) && json['code'] == RPC_WALLET_NOT_FOUND_ERROR_CODE
|
151
|
+
rescue Tapyrus::RPC::Error => ex
|
152
|
+
if ex.rpc_error['code'] == RPC_WALLET_NOT_FOUND_ERROR_CODE
|
144
153
|
raise Errors::WalletUnloaded, "The wallet #{wallet_id} is unloaded. You should load before use it."
|
145
154
|
else
|
146
155
|
raise ex
|
@@ -152,6 +161,22 @@ module Glueby
|
|
152
161
|
def wallet_name(wallet_id)
|
153
162
|
"#{WALLET_PREFIX}#{wallet_id}"
|
154
163
|
end
|
164
|
+
|
165
|
+
def encode_sighashtype(sighashtype)
|
166
|
+
type = case sighashtype & (~(Tapyrus::SIGHASH_TYPE[:anyonecanpay]))
|
167
|
+
when Tapyrus::SIGHASH_TYPE[:all] then 'ALL'
|
168
|
+
when Tapyrus::SIGHASH_TYPE[:none] then 'NONE'
|
169
|
+
when Tapyrus::SIGHASH_TYPE[:single] then 'SIGNLE'
|
170
|
+
else
|
171
|
+
raise Errors::InvalidSighashType, "Invalid sighash type '#{sighashtype}'"
|
172
|
+
end
|
173
|
+
|
174
|
+
if sighashtype & Tapyrus::SIGHASH_TYPE[:anyonecanpay] == 0x80
|
175
|
+
type += '|ANYONECANPAY'
|
176
|
+
end
|
177
|
+
|
178
|
+
type
|
179
|
+
end
|
155
180
|
end
|
156
181
|
end
|
157
182
|
end
|
data/lib/glueby/version.rb
CHANGED