Class: Glueby::Internal::Wallet

Inherits:
Object
  • Object
show all
Includes:
GluebyLogger
Defined in:
lib/glueby/internal/wallet.rb,
lib/glueby/internal/wallet/errors.rb,
lib/glueby/internal/wallet/active_record.rb,
lib/glueby/internal/wallet/active_record/key.rb,
lib/glueby/internal/wallet/active_record/utxo.rb,
lib/glueby/internal/wallet/active_record/wallet.rb,
lib/glueby/internal/wallet/mysql_wallet_adapter.rb,
lib/glueby/internal/wallet/abstract_wallet_adapter.rb,
lib/glueby/internal/wallet/tapyrus_core_wallet_adapter.rb,
lib/glueby/internal/wallet/active_record_wallet_adapter.rb,
lib/glueby/internal/wallet/active_record_wallet_adapter/syncer.rb

Overview

# Glueby::Internal::Wallet

This module provides the way to deal about wallet that includes key management, address management, getting UTXOs.

## How to use

First, you need to configure which wallet implementation is used in Glueby::Internal::Wallet. For now, below wallets are supported.

Here shows an example to use Tapyrus Core wallet.

“‘ruby # Setup Tapyrus Core RPC connection config = ’http’, host: ‘127.0.0.1’, port: 12381, user: ‘user’, password: ‘pass’ Glueby::Internal::RPC.configure(config)

# Setup wallet adapter Glueby::Internal::Wallet.wallet_adapter = Glueby::Internal::Wallet::TapyrusCoreWalletAdapter.new

# Create wallet wallet = Glueby::Internal::Wallet.create wallet.balance # => 0 wallet.list_unspent “‘

Defined Under Namespace

Modules: AR, Errors Classes: AbstractWalletAdapter, ActiveRecordWalletAdapter, MySQLWalletAdapter, TapyrusCoreWalletAdapter

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from GluebyLogger

#logger

Constructor Details

#initialize(wallet_id) ⇒ Wallet

Returns a new instance of Wallet.



84
85
86
# File 'lib/glueby/internal/wallet.rb', line 84

def initialize(wallet_id)
  @id = wallet_id
end

Instance Attribute Details

#idObject (readonly)

Returns the value of attribute id.



82
83
84
# File 'lib/glueby/internal/wallet.rb', line 82

def id
  @id
end

Class Method Details

.create(wallet_id = nil) ⇒ Object



40
41
42
43
44
45
46
47
# File 'lib/glueby/internal/wallet.rb', line 40

def create(wallet_id = nil)
  begin
    wallet_id = wallet_adapter.create_wallet(wallet_id)
  rescue Errors::WalletAlreadyCreated => _
    # Ignore when wallet is already created.
  end
  new(wallet_id)
end

.get_addresses_info(addresses) ⇒ Object



77
78
79
# File 'lib/glueby/internal/wallet.rb', line 77

def get_addresses_info(addresses)
  @wallet_adapter.get_addresses_info(addresses)
end

.load(wallet_id) ⇒ Object



49
50
51
52
53
54
55
56
# File 'lib/glueby/internal/wallet.rb', line 49

def load(wallet_id)
  begin
    wallet_adapter.load_wallet(wallet_id)
  rescue Errors::WalletAlreadyLoaded => _
    # Ignore when wallet is already loaded.
  end
  new(wallet_id)
end

.wallet_adapterObject



72
73
74
75
# File 'lib/glueby/internal/wallet.rb', line 72

def wallet_adapter
  @wallet_adapter or
    raise Errors::ShouldInitializeWalletAdapter, 'You should initialize wallet adapter using `Glueby::Internal::Wallet.wallet_adapter = some wallet adapter instance`.'
end

.wallet_adapter=(adapter) ⇒ Object



62
63
64
65
66
67
68
69
70
# File 'lib/glueby/internal/wallet.rb', line 62

def wallet_adapter=(adapter)
  if adapter.is_a?(ActiveRecordWalletAdapter)
    BlockSyncer.register_syncer(ActiveRecordWalletAdapter::Syncer)
  else
    BlockSyncer.unregister_syncer(ActiveRecordWalletAdapter::Syncer)
  end

  @wallet_adapter = adapter
end

.walletsObject



58
59
60
# File 'lib/glueby/internal/wallet.rb', line 58

def wallets
  wallet_adapter.wallets.map { |id| new(id) }
end

Instance Method Details

#balance(only_finalized = true) ⇒ Object



88
89
90
# File 'lib/glueby/internal/wallet.rb', line 88

def balance(only_finalized = true)
  wallet_adapter.balance(id, only_finalized)
end

#broadcast(tx, without_fee_provider: false, &block) ⇒ Object

Broadcast a transaction via Tapyrus Core RPC

Parameters:

  • tx (Tapyrus::Tx)

    The tx that would be broadcasted

  • block (Proc)

    The block that is called before broadcasting. It can be used to handle tx that is modified by FeeProvider.

  • [Boolean] (Hash)

    a customizable set of options



146
147
148
149
150
151
# File 'lib/glueby/internal/wallet.rb', line 146

def broadcast(tx, without_fee_provider: false, &block)
  tx = FeeProvider.provide(tx) if !without_fee_provider && Glueby.configuration.fee_provider_bears?
  logger.info("Try to broadcast a tx (tx payload: #{tx.to_hex} )")
  wallet_adapter.broadcast(id, tx, &block)
  tx
end

#change_addressObject



157
158
159
# File 'lib/glueby/internal/wallet.rb', line 157

def change_address
  wallet_adapter.change_address(id)
end

#collect_colored_outputs(color_id, amount = nil, label = nil, only_finalized = true, shuffle = false, lock_utxos = false, excludes = []) ⇒ Integer, Array<Hash>

Collect colored coin UTXOs up to the specified amount. ## The UTXO structure

  • txid: [String] Transaction id

  • vout: [Integer] Output index

  • amount: [Integer] Amount of the UTXO as tapyrus unit

  • finalized: [Boolean] Whether the UTXO is finalized

  • script_pubkey: [String] ScriptPubkey of the UTXO

Parameters:

  • color_id (Tapyrus::Color::ColorIdentifier)

    The color identifier of colored token

  • amount (Integer) (defaults to: nil)

    The amount of colored token to collect. If the amount is nil, return all UTXOs with color_id

  • label (String) (defaults to: nil)

    The label of UTXO to collect

  • only_finalized (Boolean) (defaults to: true)

    The flag to collect only finalized UTXO

  • shuffle (Boolean) (defaults to: false)

    The flag to shuffle UTXO before collecting

  • lock_utxos (Boolean) (defaults to: false)

    The flag to lock returning UTXOs to prevent to be used from other threads or processes

  • Array<Hash] (Array<Hash] excludes The UTXO list to exclude the method result. Each hash must hub keys that are :txid and :vout)

    excludes The UTXO list to exclude the method result. Each hash must hub keys that are :txid and :vout

Returns:

  • (Integer)

    The sum of return UTXOs

  • (Array<Hash>)

    An array of UTXO hash



215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/glueby/internal/wallet.rb', line 215

def collect_colored_outputs(
  color_id,
  amount = nil,
  label = nil,
  only_finalized = true,
  shuffle = false,
  lock_utxos = false,
  excludes = []
)
  collect_utxos(amount, label, color_id, only_finalized, shuffle, lock_utxos, excludes) do |output|
    next yield(output) if block_given?

    true
  end
rescue Glueby::Contract::Errors::InsufficientFunds
  raise Glueby::Contract::Errors::InsufficientTokens
end

#collect_uncolored_outputs(amount = nil, label = nil, only_finalized = true, shuffle = false, lock_utxos = false, excludes = []) ⇒ Integer, Array<Hash>

Collect TPC UTXOs up to the specified amount. ## The UTXO structure

  • txid: [String] Transaction id

  • vout: [Integer] Output index

  • amount: [Integer] Amount of the UTXO as tapyrus unit

  • finalized: [Boolean] Whether the UTXO is finalized

  • script_pubkey: [String] ScriptPubkey of the UTXO

Parameters:

  • amount (Integer) (defaults to: nil)

    The amount of colored token to collect. If the amount is nil, return all TPC UTXOs

  • label (String) (defaults to: nil)

    The label of UTXO to collect

  • only_finalized (Boolean) (defaults to: true)

    The flag to collect only finalized UTXO

  • shuffle (Boolean) (defaults to: false)

    The flag to shuffle UTXO before collecting

  • lock_utxos (Boolean) (defaults to: false)

    The flag to lock returning UTXOs to prevent to be used from other threads or processes

  • Array<Hash] (Array<Hash] excludes The UTXO list to exclude the method result. Each hash must hub keys that are :txid and :vout)

    excludes The UTXO list to exclude the method result. Each hash must hub keys that are :txid and :vout

Returns:

  • (Integer)

    The sum of return UTXOs

  • (Array<Hash>)

    An array of UTXO hash



182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/glueby/internal/wallet.rb', line 182

def collect_uncolored_outputs(
  amount = nil,
  label = nil,
  only_finalized = true,
  shuffle = false,
  lock_utxos = false,
  excludes = []
)
  collect_utxos(amount, label, Tapyrus::Color::ColorIdentifier.default, only_finalized, shuffle, lock_utxos, excludes) do |output|
    next yield(output) if block_given?

    true
  end
end

#create_pay_to_contract_address(contents) ⇒ Object



237
238
239
# File 'lib/glueby/internal/wallet.rb', line 237

def create_pay_to_contract_address(contents)
  wallet_adapter.create_pay_to_contract_address(id, contents)
end

#create_pubkeyObject



161
162
163
# File 'lib/glueby/internal/wallet.rb', line 161

def create_pubkey
  wallet_adapter.create_pubkey(id)
end

#deleteObject



121
122
123
# File 'lib/glueby/internal/wallet.rb', line 121

def delete
  wallet_adapter.delete_wallet(id)
end

#fill_uncolored_inputs(tx, target_amount:, current_amount: 0, fee_estimator: Contract::FeeEstimator::Fixed.new, &block) ⇒ Tapyrus::Tx, ...

Fill inputs in the tx up to target_amount of TPC from UTXOs in the wallet. This method should be called before adding change output and script_sig in outputs. FeeEstimator.dummy_tx returns fee amount to the TX that will be added one TPC input, a change TPC output and script sigs in outputs.

Parameters:

  • tx (Tapyrus::Tx)

    The tx that will be filled the inputs

  • target_amount (Integer)

    The tapyrus amount the tx is expected to be added in this method

  • current_amount (Integer) (defaults to: 0)

    The tapyrus amount the tx already has in its inputs

  • fee_estimator (Glueby::Contract::FeeEstimator) (defaults to: Contract::FeeEstimator::Fixed.new)

Returns:

  • (Tapyrus::Tx)

    tx The tx that is added inputs

  • (Integer)

    fee The final fee after the inputs are filled

  • (Integer)

    current_amount The final amount of the tx inputs

  • (Array<Hash>)

    provided_utxos The utxos that are added to the tx inputs



265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
# File 'lib/glueby/internal/wallet.rb', line 265

def fill_uncolored_inputs(
  tx,
  target_amount: ,
  current_amount: 0,
  fee_estimator: Contract::FeeEstimator::Fixed.new,
  &block
)
  fee = fee_estimator.fee(Contract::FeeEstimator.dummy_tx(tx, dummy_input_count: 0))
  provided_utxos = []

  while current_amount - fee < target_amount
    sum, utxos = collect_uncolored_outputs(
      fee + target_amount - current_amount,
      nil, false, true, true,
      provided_utxos,
      &block
    )

    utxos.each do |utxo|
      tx.inputs << Tapyrus::TxIn.new(out_point: Tapyrus::OutPoint.from_txid(utxo[:txid], utxo[:vout]))
      provided_utxos << utxo
    end
    current_amount += sum

    new_fee = fee_estimator.fee(Contract::FeeEstimator.dummy_tx(tx, dummy_input_count: 0))
    fee = new_fee
  end

  [tx, fee, current_amount, provided_utxos]
end

#get_addresses(label = nil) ⇒ Object



233
234
235
# File 'lib/glueby/internal/wallet.rb', line 233

def get_addresses(label = nil)
  wallet_adapter.get_addresses(id, label)
end

#has_address?(address) ⇒ Boolean

Returns:

  • (Boolean)


249
250
251
# File 'lib/glueby/internal/wallet.rb', line 249

def has_address?(address)
  wallet_adapter.has_address?(id, address)
end

#list_unspent(only_finalized = true, label = :unlabeled, color_id: nil) ⇒ Object

Parameters:

  • only_finalized (Boolean) (defaults to: true)

    The flag to get a UTXO with status only finalized

  • label (String) (defaults to: :unlabeled)

    This label is used to filtered the UTXOs with labeled if a key or Utxo is labeled.

    • If label is nil or :unlabeled, only unlabeled UTXOs will be returned.

    • If label=:all, all UTXOs will be returned.

  • color_id (Tapyrus::Color::ColorIdentifier) (defaults to: nil)

    The color identifier associated with UTXO. It will return only UTXOs with specified color_id. If color_id is nil, it will return all UTXOs. If Tapyrus::Color::ColorIdentifier.default is specified, it will return uncolored UTXOs(i.e. TPC)



112
113
114
115
# File 'lib/glueby/internal/wallet.rb', line 112

def list_unspent(only_finalized = true, label = :unlabeled, color_id: nil )
  label = :unlabeled unless label
  wallet_adapter.list_unspent(id, only_finalized, label, color_id: color_id)
end

#list_unspent_with_count(only_finalized = true, label = nil, color_id: nil, page: 1, per: 25) ⇒ Object

Parameters:

  • only_finalized (Boolean) (defaults to: true)

    The flag to get a UTXO with status only finalized

  • label (String) (defaults to: nil)

    This label is used to filtered the UTXOs with labeled if a key or Utxo is labeled.

    • If label is nil or :unlabeled, only unlabeled UTXOs will be returned.

    • If label=:all, all UTXOs will be returned.

  • color_id (Tapyrus::Color::ColorIdentifier) (defaults to: nil)

    The color identifier associated with UTXO. It will return only UTXOs with specified color_id. If color_id is nil, it will return all UTXOs. If Tapyrus::Color::ColorIdentifier.default is specified, it will return uncolored UTXOs(i.e. TPC)

  • page (Integer) (defaults to: 1)

    The page parameter is responsible for specifying the current page being viewed within the paginated results. default is 1.

  • per (Integer) (defaults to: 25)

    The per parameter is used to determine the number of items to display per page. default is 25.



101
102
103
# File 'lib/glueby/internal/wallet.rb', line 101

def list_unspent_with_count(only_finalized = true, label = nil, color_id: nil, page: 1, per: 25)
  wallet_adapter.list_unspent_with_count(id, only_finalized, label, color_id: color_id, page: page, per: per)
end

#lock_unspent(utxo) ⇒ Object



117
118
119
# File 'lib/glueby/internal/wallet.rb', line 117

def lock_unspent(utxo)
  wallet_adapter.lock_unspent(id, utxo)
end

#pay_to_contract_key(payment_base, contents) ⇒ Object



241
242
243
# File 'lib/glueby/internal/wallet.rb', line 241

def pay_to_contract_key(payment_base, contents)
  wallet_adapter.pay_to_contract_key(id, payment_base, contents)
end

#receive_address(label = nil) ⇒ Object



153
154
155
# File 'lib/glueby/internal/wallet.rb', line 153

def receive_address(label = nil)
  wallet_adapter.receive_address(id, label)
end

#sign_to_pay_to_contract_address(tx, utxo, payment_base, contents) ⇒ Object



245
246
247
# File 'lib/glueby/internal/wallet.rb', line 245

def sign_to_pay_to_contract_address(tx, utxo, payment_base, contents)
  wallet_adapter.sign_to_pay_to_contract_address(id, tx, utxo, payment_base, contents)
end

#sign_tx(tx, prev_txs = [], for_fee_provider_input: false) ⇒ Object

Parameters:

  • tx (Tapyrus::Tx)

    The tx that is signed

  • prev_txs (Array<Hash>) (defaults to: [])

    An array of hash that represents unbroadcasted transaction outputs used by signing tx @option prev_txs [String] :txid @option prev_txs [Integer] :vout @option prev_txs [String] :scriptPubkey @option prev_txs [Integer] :amount

  • for_fee_provider_input (Boolean) (defaults to: false)

    The flag to notify whether the caller is FeeProvider and called for signing a input that is by FeeProvider.



132
133
134
135
136
137
138
139
140
# File 'lib/glueby/internal/wallet.rb', line 132

def sign_tx(tx, prev_txs = [], for_fee_provider_input: false)
  sighashtype = Tapyrus::SIGHASH_TYPE[:all]

  if !for_fee_provider_input && Glueby.configuration.fee_provider_bears?
    sighashtype |= Tapyrus::SIGHASH_TYPE[:anyonecanpay]
  end

  wallet_adapter.sign_tx(id, tx, prev_txs, sighashtype: sighashtype)
end