Class: OpenAssets::Api

Inherits:
Object
  • Object
show all
Includes:
MethodFilter, Util
Defined in:
lib/openassets/api.rb

Constant Summary

Constants included from Util

Util::OA_NAMESPACE, Util::OA_VERSION_BYTE, Util::OA_VERSION_BYTE_TESTNET

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from MethodFilter

included

Methods included from Util

#address_to_asset_id, #address_to_oa_address, #coin_to_satoshi, #decode_leb128, #encode_leb128, #generate_asset_id, #oa_address_to_address, #oa_address_to_asset_id, #pubkey_hash_to_asset_id, #read_leb128, #read_var_integer, #satoshi_to_coin, #script_to_address, #to_bytes, #valid_asset_id?, #validate_address

Constructor Details

#initialize(config = nil) ⇒ Api

Returns a new instance of Api.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/openassets/api.rb', line 17

def initialize(config = nil)
  @config = {:network => 'mainnet',
             :provider => 'bitcoind', :cache => 'cache.db',
             :dust_limit => 600, :default_fees => 10000, :min_confirmation => 1, :max_confirmation => 9999999,
             :rpc => { :host => 'localhost', :port => 8332 , :user => '', :password => '', :schema => 'https', :timeout => 60, :open_timeout => 60}}
  if config
    @config.update(config)
  end
  OpenAssets.configuration = @config
  if @config[:provider] == 'bitcoind'
    @provider = Provider::BitcoinCoreProvider.new(@config[:rpc])
  else
    raise OpenAssets::Error, 'specified unsupported provider.'
  end
  unless @config[:cache] == 'none'
    @tx_cache = Cache::TransactionCache.new(@config[:cache])
    @output_cache = Cache::OutputCache.new(@config[:cache])
  end
  change_network
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



12
13
14
# File 'lib/openassets/api.rb', line 12

def config
  @config
end

#output_cacheObject (readonly)

Returns the value of attribute output_cache.



15
16
17
# File 'lib/openassets/api.rb', line 15

def output_cache
  @output_cache
end

#providerObject (readonly)

Returns the value of attribute provider.



13
14
15
# File 'lib/openassets/api.rb', line 13

def provider
  @provider
end

#tx_cacheObject (readonly)

Returns the value of attribute tx_cache.



14
15
16
# File 'lib/openassets/api.rb', line 14

def tx_cache
  @tx_cache
end

Instance Method Details

#burn_asset(oa_address, asset_id, fees = nil, mode = 'broadcast') ⇒ Object

Creates a transaction for burn asset. @param oa_address The open asset address to burn asset. @param asset_id The asset ID identifying the asset to burn. @param fees The fess in satoshis for the transaction. @param mode ‘broadcast’ (default) for signing and broadcasting the transaction, ‘signed’ for signing the transaction without broadcasting, ‘unsigned’ for getting the raw unsigned transaction without broadcasting“”“=‘broadcast’



193
194
195
196
197
# File 'lib/openassets/api.rb', line 193

def burn_asset(oa_address, asset_id, fees = nil, mode = 'broadcast')
  unspents = get_unspent_outputs([oa_address_to_address(oa_address)])
  tx = create_tx_builder.burn_asset(unspents, asset_id, fees.nil? ? @config[:default_fees]: fees)
  process_transaction(tx, mode)
end

#get_balance(address = nil) ⇒ Object

Returns the balance in both bitcoin and colored coin assets for all of the addresses available in your Bitcoin Core wallet.

Parameters:

  • address (String) (defaults to: nil)

    The open assets address. if unspecified nil.



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/openassets/api.rb', line 58

def get_balance(address = nil)
  outputs = get_unspent_outputs(address.nil? ? [] : [oa_address_to_address(address)])
  colored_outputs = outputs.map{|o|o.output}
  sorted_outputs = colored_outputs.sort_by { |o|o.script.to_string}
  groups = sorted_outputs.group_by{|o| o.script.to_string}
  result = groups.map{|k, v|
    btc_address = script_to_address(v[0].script)
    sorted_script_outputs = v.sort_by{|o|o.asset_id unless o.asset_id}
    group_assets = sorted_script_outputs.group_by{|o|o.asset_id}.select{|k,v| !k.nil?}
    assets = group_assets.map{|asset_id, outputs|
      {
          'asset_id' => asset_id,
          'quantity' => outputs.inject(0) { |sum, o| sum + o.asset_quantity }.to_s,
          'amount' => outputs.inject(0) { |sum, o| sum + o.asset_amount }.to_s,
          'asset_definition_url' => outputs[0].asset_definition_url,
          'proof_of_authenticity' => outputs[0].proof_of_authenticity
      }
    }
    {
        'address' => btc_address,
        'oa_address' => btc_address.nil? ? nil : address_to_oa_address(btc_address),
        'value' => satoshi_to_coin(v.inject(0) { |sum, o|sum +  o.value}),
        'assets' => assets,
        'account' => v[0].
    }
  }
  address.nil? ? result : result.select{|r|r['oa_address'] == address}
end

#get_color_outputs_from_tx(tx) ⇒ Object



230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/openassets/api.rb', line 230

def get_color_outputs_from_tx(tx)
  unless tx.is_coinbase?
    tx.outputs.each_with_index { |out, i|
      marker_output_payload = OpenAssets::Protocol::MarkerOutput.parse_script(out.pk_script)
      unless marker_output_payload.nil?
        marker_output = OpenAssets::Protocol::MarkerOutput.deserialize_payload(marker_output_payload)
        inputs = tx.inputs.map {|input|
          get_output(input.previous_output, input.prev_out_index)
        }
        asset_ids = compute_asset_ids(inputs, i, tx.outputs, marker_output.asset_quantities)
        return asset_ids unless asset_ids.nil?
      end
    }
  end
  tx.outputs.map{|out| OpenAssets::Protocol::TransactionOutput.new(out.value, out.parsed_script, nil, 0, OpenAssets::Protocol::OutputType::UNCOLORED)}
end

#get_output(txid, output_index) ⇒ Object



218
219
220
221
222
223
224
225
226
227
228
# File 'lib/openassets/api.rb', line 218

def get_output(txid, output_index)
  if output_cache
    cached = output_cache.get(txid, output_index)
    return cached unless cached.nil?
  end
  decode_tx = load_cached_tx(txid)
  tx = Bitcoin::Protocol::Tx.new(decode_tx.htb)
  colored_outputs = get_color_outputs_from_tx(tx)
  colored_outputs.each_with_index { |o, index| output_cache.put(txid, index, o)} if output_cache
  colored_outputs[output_index]
end

#get_outputs_from_txid(txid, use_cache = false) ⇒ Object

Get tx outputs. @param txid Transaction ID. @param use_cache If specified true use cache.(default value is false) @return Return array of the transaction output Hash with coloring information.



251
252
253
254
255
# File 'lib/openassets/api.rb', line 251

def get_outputs_from_txid(txid, use_cache = false)
  tx = get_tx(txid, use_cache)
  outputs = get_color_outputs_from_tx(tx)
  outputs.map.with_index{|out, i|out.to_hash.merge({'txid' => tx.hash, 'vout' => i})}
end

#get_tx(txid, use_cache = true) ⇒ Object

Get tx. (This method returns plain Bitcoin::Protocol::Tx object, so it not contains open asset information.) @param txid Transaction ID. @return Return the Bitcoin::Protocol::Tx.



260
261
262
263
# File 'lib/openassets/api.rb', line 260

def get_tx(txid, use_cache = true)
  decode_tx = use_cache ? load_cached_tx(txid) : load_tx(txid)
  Bitcoin::Protocol::Tx.new(decode_tx.htb)
end

#get_unspent_outputs(addresses) ⇒ Array[OpenAssets::Transaction::SpendableOutput]

Get unspent outputs.

Parameters:

  • addresses (Array)

    The array of Bitcoin address.

Returns:



202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/openassets/api.rb', line 202

def get_unspent_outputs(addresses)
  validate_address(addresses)
  unspent = provider.list_unspent(addresses, @config[:min_confirmation], @config[:max_confirmation])
  result = unspent.map{|item|
    output_result = get_output(item['txid'], item['vout'])
    output_result. = item['account']
    output = OpenAssets::Transaction::SpendableOutput.new(
      OpenAssets::Transaction::OutPoint.new(item['txid'], item['vout']), output_result)
    output.confirmations = item['confirmations']
    output.spendable = item['spendable']
    output.solvable = item['solvable']
    output
  }
  result
end

#is_testnet?Boolean

Returns:

  • (Boolean)


42
43
44
# File 'lib/openassets/api.rb', line 42

def is_testnet?
  @config[:network] == 'testnet'
end

#issue_asset(from, amount, metadata = nil, to = nil, fees = nil, mode = 'broadcast', output_qty = 1) ⇒ Object

Creates a transaction for issuing an asset. @param from The open asset address to issue the asset from. @param amount The amount of asset units to issue. @param to The open asset address to send the asset to; if unspecified, the assets are sent back to the issuing address. @param metadata The metadata to embed in the transaction. The asset definition pointer defined by this metadata. @param fees The fess in satoshis for the transaction. @param mode Specify the following mode. ‘broadcast’ (default) for signing and broadcasting the transaction, ‘signed’ for signing the transaction without broadcasting, ‘unsigned’ for getting the raw unsigned transaction without broadcasting“”“=‘broadcast’ @param output_qty The number of divides the issue output. Default value is 1. Ex. amount = 125 and output_qty = 2, asset quantity = [62, 63] and issue TxOut is two. @return The Bitcoin::Protocol::Tx object.



100
101
102
103
104
105
106
107
# File 'lib/openassets/api.rb', line 100

def issue_asset(from, amount,  = nil, to = nil, fees = nil, mode = 'broadcast', output_qty = 1)
  to = from if to.nil?
  colored_outputs = get_unspent_outputs([oa_address_to_address(from)])
  issue_param = OpenAssets::Transaction::TransferParameters.new(colored_outputs, to, from, amount, output_qty)
  tx = create_tx_builder.issue_asset(issue_param, , fees.nil? ? @config[:default_fees]: fees)
  tx = process_transaction(tx, mode)
  tx
end

#list_unspent(oa_address_list = []) ⇒ Array

get UTXO for colored coins.

Parameters:

  • oa_address_list (Array) (defaults to: [])

    Obtain the balance of this open assets address only, or all addresses if unspecified.

Returns:

  • (Array)

    Return array of the unspent information Hash.



49
50
51
52
53
54
# File 'lib/openassets/api.rb', line 49

def list_unspent(oa_address_list = [])
  btc_address_list = oa_address_list.map { |oa_address| oa_address_to_address(oa_address)}
  outputs = get_unspent_outputs(btc_address_list)
  result = outputs.map{|out| out.to_hash}
  result
end

#send_asset(from, asset_id, amount, to, fees = nil, mode = 'broadcast', output_qty = 1) ⇒ Object

Creates a transaction for sending an asset from an address to another. @param from The open asset address to send the asset from. @param asset_id The asset ID identifying the asset to send. @param amount The amount of asset units to send. @param to The open asset address to send the asset to. @param fees The fess in satoshis for the transaction. @param mode ‘broadcast’ (default) for signing and broadcasting the transaction, ‘signed’ for signing the transaction without broadcasting, ‘unsigned’ for getting the raw unsigned transaction without broadcasting“”“=‘broadcast’ @return The resulting transaction.



119
120
121
122
123
124
125
# File 'lib/openassets/api.rb', line 119

def send_asset(from, asset_id, amount, to, fees = nil, mode = 'broadcast', output_qty = 1)
  colored_outputs = get_unspent_outputs([oa_address_to_address(from)])
  asset_transfer_spec = OpenAssets::Transaction::TransferParameters.new(colored_outputs, to, from, amount, output_qty)
  tx = create_tx_builder.transfer_asset(asset_id, asset_transfer_spec, from, fees.nil? ? @config[:default_fees]: fees)
  tx = process_transaction(tx, mode)
  tx
end

#send_assets(from, send_asset_params, fees = nil, mode = 'broadcast') ⇒ Object

Creates a transaction for sending multiple asset from an address to another. @param from The open asset address to send the asset from when send_asset_param hasn’t from. to send the bitcoins from, if needed. where to send bitcoin change, if any. @param[Array] send_asset_params The send Asset information(asset_id, amount, to, from). @param fees The fess in satoshis for the transaction. @param mode ‘broadcast’ (default) for signing and broadcasting the transaction, ‘signed’ for signing the transaction without broadcasting, ‘unsigned’ for getting the raw unsigned transaction without broadcasting“”“=‘broadcast’ @return The resulting transaction.



136
137
138
139
140
141
142
143
144
145
146
# File 'lib/openassets/api.rb', line 136

def send_assets(from, send_asset_params, fees = nil, mode = 'broadcast')
  transfer_specs = send_asset_params.map{ |param|
    colored_outputs = get_unspent_outputs([oa_address_to_address(param.from || from)])
    [param.asset_id, OpenAssets::Transaction::TransferParameters.new(colored_outputs, param.to, param.from || from, param.amount)]
  }
  btc_transfer_spec = OpenAssets::Transaction::TransferParameters.new(
      get_unspent_outputs([oa_address_to_address(from)]), nil, oa_address_to_address(from), 0)
  tx = create_tx_builder.transfer_assets(transfer_specs, btc_transfer_spec, fees.nil? ? @config[:default_fees]: fees)
  tx = process_transaction(tx, mode)
  tx
end

#send_bitcoin(from, amount, to, fees = nil, mode = 'broadcast', output_qty = 1) ⇒ Object

Creates a transaction for sending bitcoins from an address to another. @param from The address to send the bitcoins from. @param amount The amount of satoshis to send. @param to The address to send the bitcoins to. @param fees The fess in satoshis for the transaction. @param mode ‘broadcast’ (default) for signing and broadcasting the transaction, ‘signed’ for signing the transaction without broadcasting, ‘unsigned’ for getting the raw unsigned transaction without broadcasting“”“=‘broadcast’ Ex. amount = 125 and output_qty = 2, asset quantity = [62, 63] and issue TxOut is two. @return The resulting transaction.

Parameters:

  • output_qty (Integer) (defaults to: 1)

    The number of divides the issue output. Default value is 1.



159
160
161
162
163
164
165
# File 'lib/openassets/api.rb', line 159

def send_bitcoin(from, amount, to, fees = nil, mode = 'broadcast', output_qty = 1)
  validate_address([from, to])
  colored_outputs = get_unspent_outputs([from])
  btc_transfer_spec = OpenAssets::Transaction::TransferParameters.new(colored_outputs, to, from, amount, output_qty)
  tx = create_tx_builder.transfer_btc(btc_transfer_spec, fees.nil? ? @config[:default_fees]: fees)
  process_transaction(tx, mode)
end

#send_bitcoins(from, send_params, fees = nil, mode = 'broadcast') ⇒ Object

Creates a transaction for sending multiple bitcoins from an address to others. @param from The address to send the bitcoins from. @param[Array] send_params The send information(amount of satoshis and to). @param fees The fees in satoshis for the transaction. @param mode ‘broadcast’ (default) for signing and broadcasting the transaction, ‘signed’ for signing the transaction without broadcasting, ‘unsigned’ for getting the raw unsigned transaction without broadcasting“”“=‘broadcast’ @return The resulting transaction.



175
176
177
178
179
180
181
182
183
# File 'lib/openassets/api.rb', line 175

def send_bitcoins(from, send_params, fees = nil, mode = 'broadcast')
  colored_outputs = get_unspent_outputs([from])
  btc_transfer_specs = send_params.map{|param|
    OpenAssets::Transaction::TransferParameters.new(colored_outputs, param.to, from, param.amount)
  }
  tx = create_tx_builder.transfer_btcs(btc_transfer_specs, fees.nil? ? @config[:default_fees]: fees)
  tx = process_transaction(tx, mode)
  tx
end