Class: OpenAssets::Api

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

Constant Summary

Constants included from Util

Util::OA_NAMESPACE, Util::OA_VERSION_BYTE

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Util

#address_to_oa_address, #decode_leb128, #encode_leb128, #generate_asset_id, #oa_address_to_address, #pubkey_hash_to_asset_id, #satoshi_to_coin, #script_to_address, #to_bytes, #validate_address

Constructor Details

#initialize(config = nil) ⇒ Api

Returns a new instance of Api.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/openassets/api.rb', line 13

def initialize(config = nil)
  @cache = {}
  @config = {:network => 'mainnet',
             :provider => 'bitcoind',
             :dust_limit => 600, :default_fees => 10000,
             :rpc => { :host => 'localhost', :port => 8332 , :user => '', :password => '', :schema => 'https'}}
  if config
    @config.update(config)
  end
  if @config[:provider] == 'bitcoind'
    @provider = Provider::BitcoinCoreProvider.new(@config[:rpc])
  else
    raise OpenAssets::Error, 'specified unsupported provider.'
  end
end

Instance Attribute Details

#cacheObject (readonly)

Returns the value of attribute cache.



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

def cache
  @cache
end

#configObject (readonly)

Returns the value of attribute config.



9
10
11
# File 'lib/openassets/api.rb', line 9

def config
  @config
end

#providerObject (readonly)

Returns the value of attribute provider.



10
11
12
# File 'lib/openassets/api.rb', line 10

def provider
  @provider
end

Instance Method Details

#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.



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/openassets/api.rb', line 65

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
      }
    }
    {
        '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_transaction(tx) ⇒ Object



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/openassets/api.rb', line 183

def get_color_transaction(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



172
173
174
175
176
177
178
179
180
181
# File 'lib/openassets/api.rb', line 172

def get_output(txid, output_index)
  cached_output = @cache[txid + output_index.to_s]
  return cached_output if cached_output
  decode_tx = provider.get_transaction(txid, 0)
  raise OpenAssets::Transaction::TransactionBuildError, "txid #{txid} could not be retrieved." if decode_tx.nil?
  tx = Bitcoin::Protocol::Tx.new(decode_tx.htb)
  colored_outputs = get_color_transaction(tx)
  colored_outputs.each_with_index { |o, index | @cache[txid + index.to_s] = o}
  colored_outputs[output_index]
end

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

Get unspent outputs.

Parameters:

  • addresses (Array)

    The array of Bitcoin address.

Returns:



158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/openassets/api.rb', line 158

def get_unspent_outputs(addresses)
  validate_address(addresses)
  unspent = provider.list_unspent(addresses)
  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
  }
  result
end

#is_testnet?Boolean

Returns:

  • (Boolean)


33
34
35
# File 'lib/openassets/api.rb', line 33

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.



106
107
108
109
110
111
112
113
114
# File 'lib/openassets/api.rb', line 106

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

#list_unspent(oa_address = []) ⇒ Array

get UTXO for colored coins.

Parameters:

  • oa_address (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.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/openassets/api.rb', line 40

def list_unspent(oa_address = [])
  outputs = get_unspent_outputs([])
  result = outputs.map {|out|
    address = script_to_address(out.output.script)
    script = out.output.script.to_payload.bth
    {
      'txid' => out.out_point.hash,
      'vout' =>  out.out_point.index,
      'address' =>  address,
      'oa_address' => address.nil? ? nil : address_to_oa_address(address),
      'script' => script,
      'amount' => satoshi_to_coin(out.output.value),
      'confirmations' => out.confirmations,
      'asset_id' => out.output.asset_id,
      'account' => out.output.,
      'asset_quantity' => out.output.asset_quantity.to_s,
      'asset_amount' => out.output.asset_amount.to_s,
      'asset_definition_url' => out.output.asset_definition_url
    }
  }
  oa_address.empty? ? result : result.select{|r|oa_address.include?(r['oa_address'])}
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.



126
127
128
129
130
131
132
133
# File 'lib/openassets/api.rb', line 126

def send_asset(from, asset_id, amount, to, fees = nil, mode = 'broadcast', output_qty = 1)
  builder = OpenAssets::Transaction::TransactionBuilder.new(@config[:dust_limit])
  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 = builder.transfer_assets(asset_id, asset_transfer_spec, from, 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.



146
147
148
149
150
151
152
153
# File 'lib/openassets/api.rb', line 146

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