cns 0.1.5 → 0.2.2

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.
@@ -50,13 +50,11 @@ module Cns
50
50
  # @param [String] uri Uniform Resource Identifier do pedido HTTP
51
51
  # @return [Array<Hash>] lista completa trades bitcoinde
52
52
  def trades_de(pag = 0, ary = [], uri = 'https://api.bitcoin.de/v4/trades')
53
- p = "#{uri}?#{URI.encode_www_form(state: 1, page: pag + 1)}"
54
- r = JSON.parse(
55
- Curl.get(p) { |h| h.headers = hde(p) }.body,
56
- symbolize_names: true
57
- )
58
- ary += r[:trades]
59
- r[:page][:current] < r[:page][:last] ? trades_de(pag + 1, ary) : ary
53
+ par = "#{uri}?#{URI.encode_www_form(state: 1, page: pag += 1)}"
54
+ res = JSON.parse(Curl.get(par) { |obj| obj.headers = hde(par) }.body, symbolize_names: true)
55
+ ary += res[:trades]
56
+ rep = res[:page]
57
+ rep[:current] < rep[:last] ? trades_de(pag, ary) : ary
60
58
  rescue StandardError
61
59
  ary
62
60
  end
@@ -82,17 +80,38 @@ module Cns
82
80
  # @param (see trades_de)
83
81
  # @return [Array<Hash>] lista completa uniformizada depositos bitcoinde
84
82
  def deposits_de(pag = 0, ary = [], uri = 'https://api.bitcoin.de/v4/btc/deposits')
85
- p = "#{uri}?#{URI.encode_www_form(state: 2, page: pag + 1)}"
86
- r = JSON.parse(
87
- Curl.get(p) { |h| h.headers = hde(p) }.body,
88
- symbolize_names: true
89
- )
90
- ary += deposits_unif_de(r)
91
- r[:page][:current] < r[:page][:last] ? deposits_de(pag + 1, ary) : ary
83
+ par = "#{uri}?#{URI.encode_www_form(state: 2, page: pag += 1)}"
84
+ res = JSON.parse(Curl.get(par) { |obj| obj.headers = hde(par) }.body, symbolize_names: true)
85
+ ary += res[:deposits].map { |has| deposit_unif(has) }
86
+ rep = res[:page]
87
+ rep[:current] < rep[:last] ? deposits_de(pag, ary) : ary
92
88
  rescue StandardError
93
89
  ary
94
90
  end
95
91
 
92
+ # @example deposit_unif
93
+ # [
94
+ # {
95
+ # txid: 177_245,
96
+ # time: '2014-01-31T22:01:30+01:00',
97
+ # tp: 'deposit',
98
+ # add: '1KK6HhG3quojFS4CY1mPcbyrjQ8BMDQxmT',
99
+ # qt: '0.13283',
100
+ # moe: 'btc',
101
+ # fee: '0'
102
+ # },
103
+ # {}
104
+ # ]
105
+ # @return [Hash] deposit uniformizado bitcoinde
106
+ def deposit_unif(has)
107
+ {
108
+ add: has[:address],
109
+ time: Time.parse(has[:created_at]),
110
+ qt: has[:amount],
111
+ txid: Integer(has[:deposit_id])
112
+ }.merge(tp: 'deposit', moe: 'btc', fee: '0')
113
+ end
114
+
96
115
  # @example withdrawals_de
97
116
  # {
98
117
  # withdrawals: [
@@ -116,17 +135,39 @@ module Cns
116
135
  # @param (see deposits_de)
117
136
  # @return [Array<Hash>] lista completa uniformizada withdrawals bitcoinde
118
137
  def withdrawals_de(pag = 0, ary = [], uri = 'https://api.bitcoin.de/v4/btc/withdrawals')
119
- p = "#{uri}?#{URI.encode_www_form(state: 1, page: pag + 1)}"
120
- r = JSON.parse(
121
- Curl.get(p) { |h| h.headers = hde(p) }.body,
122
- symbolize_names: true
123
- )
124
- ary += withdrawals_unif_de(r)
125
- r[:page][:current] < r[:page][:last] ? withdrawals_de(pag + 1, ary) : ary
138
+ par = "#{uri}?#{URI.encode_www_form(state: 1, page: pag += 1)}"
139
+ res = JSON.parse(Curl.get(par) { |obj| obj.headers = hde(par) }.body, symbolize_names: true)
140
+ ary += res[:withdrawals].map { |has| withdrawal_unif(has) }
141
+ rep = res[:page]
142
+ rep[:current] < rep[:last] ? withdrawals_de(pag, ary) : ary
126
143
  rescue StandardError
127
144
  ary
128
145
  end
129
146
 
147
+ # @example withdrawal_unif
148
+ # [
149
+ # {
150
+ # txid: 136_605,
151
+ # time: '2014-02-05T13:05:17+01:00',
152
+ # tp: 'withdrawal',
153
+ # add: '1K9YMDDrmMV25EoYNqi7KUEK57Kn3TCNUJ',
154
+ # qt: '0.120087',
155
+ # fee: '0',
156
+ # moe: 'btc'
157
+ # },
158
+ # {}
159
+ # ]
160
+ # @return [Hash] withdrawal uniformizada bitcoinde
161
+ def withdrawal_unif(has)
162
+ {
163
+ add: has[:address],
164
+ time: Time.parse(has[:transferred_at]),
165
+ qt: has[:amount],
166
+ fee: has[:network_fee],
167
+ txid: Integer(has[:withdrawal_id])
168
+ }.merge(tp: 'withdrawal', moe: 'btc')
169
+ end
170
+
130
171
  # @example ledger_fr
131
172
  # [
132
173
  # {
@@ -156,11 +197,11 @@ module Cns
156
197
  # @param (see trades_de)
157
198
  # @return [Array<Hash>] lista ledger paymium
158
199
  def ledger_fr(pag = 0, ary = [], uri = 'https://paymium.com/api/v1/user/orders')
159
- r = JSON.parse(
160
- Curl.get(uri, offset: pag) { |h| h.headers = hfr("#{uri}?#{URI.encode_www_form(offset: pag)}") }.body,
200
+ res = JSON.parse(
201
+ Curl.get(uri, offset: pag) { |obj| obj.headers = hfr("#{uri}?#{URI.encode_www_form(offset: pag)}") }.body,
161
202
  symbolize_names: true
162
203
  )
163
- r.empty? ? ary : ledger_fr(pag + r.size, ary + r)
204
+ res.empty? ? ary : ledger_fr(pag + res.size, ary + res)
164
205
  rescue StandardError
165
206
  ary
166
207
  end
@@ -194,11 +235,11 @@ module Cns
194
235
  # @param (see trades_de)
195
236
  # @return [Array<Hash>] lista ledger therock
196
237
  def ledger_mt(pag = 1, ary = [], uri = 'https://api.therocktrading.com/v1/transactions')
197
- r = JSON.parse(
198
- Curl.get(uri, page: pag) { |h| h.headers = hmt("#{uri}?#{URI.encode_www_form(page: pag)}") }.body,
238
+ res = JSON.parse(
239
+ Curl.get(uri, page: pag) { |obj| obj.headers = hmt("#{uri}?#{URI.encode_www_form(page: pag)}") }.body,
199
240
  symbolize_names: true
200
241
  )[:transactions]
201
- r.empty? ? ary : ledger_mt(pag + r.size, ary + r)
242
+ res.empty? ? ary : ledger_mt(pag + res.size, ary + res)
202
243
  rescue StandardError
203
244
  ary
204
245
  end
@@ -230,14 +271,15 @@ module Cns
230
271
  # @param [Hash] has acumulador dos dados
231
272
  # @param (see account_us)
232
273
  # @return [Hash] dados trades kraken
233
- def trades_us(ofs = 0, has = {}, urb = 'https://api.kraken.com/0/private', uri = 'TradesHistory', non = nnc)
234
- r = JSON.parse(
235
- Curl.post("#{urb}/#{uri}", nonce: non, ofs: ofs) { |h| h.headers = hus(uri, nonce: non, ofs: ofs) }.body,
274
+ def trades_us(ofs = 0, has = {}, urb = 'https://api.kraken.com/0/private')
275
+ uri = 'TradesHistory'
276
+ non = nnc
277
+ res = JSON.parse(
278
+ Curl.post("#{urb}/#{uri}", nonce: non, ofs: ofs) { |obj| obj.headers = hus(uri, nonce: non, ofs: ofs) }.body,
236
279
  symbolize_names: true
237
280
  )[:result]
238
- has.merge!(r[:trades])
239
- ofs += 50
240
- ofs < r[:count] ? trades_us(ofs, has) : has
281
+ has.merge!(res[:trades])
282
+ (ofs += 50) < res[:count] ? trades_us(ofs, has) : has
241
283
  rescue StandardError
242
284
  has
243
285
  end
@@ -265,14 +307,15 @@ module Cns
265
307
  # }
266
308
  # @param (see trades_us)
267
309
  # @return [Hash] dados ledger kraken
268
- def ledger_us(ofs = 0, has = {}, urb = 'https://api.kraken.com/0/private', uri = 'Ledgers', non = nnc)
269
- r = JSON.parse(
270
- Curl.post("#{urb}/#{uri}", nonce: non, ofs: ofs) { |h| h.headers = hus(uri, nonce: non, ofs: ofs) }.body,
310
+ def ledger_us(ofs = 0, has = {}, urb = 'https://api.kraken.com/0/private')
311
+ uri = 'Ledgers'
312
+ non = nnc
313
+ res = JSON.parse(
314
+ Curl.post("#{urb}/#{uri}", nonce: non, ofs: ofs) { |obj| obj.headers = hus(uri, nonce: non, ofs: ofs) }.body,
271
315
  symbolize_names: true
272
316
  )[:result]
273
- has.merge!(r[:ledger])
274
- ofs += 50
275
- ofs < r[:count] ? ledger_us(ofs, has) : has
317
+ has.merge!(res[:ledger])
318
+ (ofs += 50) < res[:count] ? ledger_us(ofs, has) : has
276
319
  rescue StandardError
277
320
  has
278
321
  end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require('bigdecimal/util')
4
+
5
+ # @author Hernani Rodrigues Vaz
6
+ module Cns
7
+ # (see Beaconchain)
8
+ class Beaconchain
9
+ # @return [Apibc] API blockchains
10
+ attr_reader :api
11
+ # @return [Array<Hash>] todos os dados bigquery
12
+ attr_reader :bqd
13
+ # @return [Thor::CoreExt::HashWithIndifferentAccess] opcoes trabalho
14
+ attr_reader :ops
15
+
16
+ # @param [Hash] dad todos os dados bigquery
17
+ # @param [Thor::CoreExt::HashWithIndifferentAccess] pop opcoes trabalho
18
+ # @option pop [Boolean] :v (false) mostra saldos?
19
+ # @option pop [Boolean] :t (false) mostra todos saldos ou somente novos?
20
+ # @return [Beaconchain] API beaconchain - processar historico saldos
21
+ def initialize(dad, pop)
22
+ @api = Apibc.new
23
+ @bqd = dad
24
+ @ops = pop
25
+ end
26
+
27
+ # @return [Array<Hash>] lista balancos novos
28
+ def nov
29
+ @nov ||= bcd.map { |obc| obc[:bx].select { |obj| idb.include?(itx(obj[:epoch], obj[:validatorindex])) } }.flatten
30
+ end
31
+
32
+ # @return [Array<Integer>] lista dos meus validators
33
+ def lax
34
+ @lax ||= bqd[:wb].map { |obj| obj[:id] }
35
+ end
36
+
37
+ # @return [Array<Hash>] todos os dados beaconchain - saldos & historico
38
+ def bcd
39
+ @bcd ||= api.data_bc("/api/v1/validator/#{lax.join(',')}").map { |obj| base_bc(obj) }
40
+ end
41
+
42
+ # @return [Array<Hash>] todos os dados juntos bigquery & beaconchain
43
+ def dados
44
+ @dados ||= bqd[:wb].map { |obq| bq_bc(obq, bcd.select { |obc| obq[:id] == obc[:ax] }.first) }
45
+ end
46
+
47
+ # @return [Array<Integer>] lista historicos novos
48
+ def idb
49
+ @idb ||= bcd.map { |obc| obc[:bx].map { |obj| itx(obj[:epoch], obj[:validatorindex]) } }.flatten -
50
+ (ops[:t] ? [] : bqd[:nb].map { |obq| obq[:itx] })
51
+ end
52
+
53
+ # @param [Integer] intum
54
+ # @param [Integer] intdois
55
+ # @return [Integer] szudzik pairing two integers
56
+ def itx(intum, intdois)
57
+ intum >= intdois ? intum * intum + intum + intdois : intum + intdois * intdois
58
+ end
59
+
60
+ # @example
61
+ # {
62
+ # activationeligibilityepoch: 0,
63
+ # activationepoch: 0,
64
+ # balance: 32_489_497_108,
65
+ # effectivebalance: 32_000_000_000,
66
+ # exitepoch: 9_223_372_036_854_775_807,
67
+ # lastattestationslot: 265_446,
68
+ # name: '',
69
+ # pubkey: '0x93bf23a587f11f9eca329a12ef51296b8a9848af8c0fe61201524b14cb85b0c6fbd3e427501cdfa3b28719bd1ed96fff',
70
+ # slashed: false,
71
+ # status: 'active_online',
72
+ # validatorindex: 11_766,
73
+ # withdrawableepoch: 9_223_372_036_854_775_807,
74
+ # withdrawalcredentials: '0x004f11be01cb72187715c55d6348c67c5a3880687cd42692306fdbc91ac2da9b'
75
+ # }
76
+ # @param [Hash] abc account beaconchain
77
+ # @return [Hash] dados beaconchain - index, saldo & historico
78
+ def base_bc(abc)
79
+ acc = abc[:validatorindex]
80
+ {
81
+ ax: acc,
82
+ sl: (abc[:balance].to_d / 10**9).round(10),
83
+ bx: api.data_bc("/api/v1/validator/#{acc}/balancehistory")
84
+ }
85
+ end
86
+
87
+ # @param [Hash] wbq wallet bigquery
88
+ # @param abc (see base_bc)
89
+ # @return [Hash] dados juntos bigquery & beaconchain
90
+ def bq_bc(wbq, abc)
91
+ xbq = wbq[:id]
92
+ {
93
+ id: xbq,
94
+ ax: wbq[:ax],
95
+ bs: wbq[:sl],
96
+ bb: bqd[:nb].select { |onb| onb[:iax] == xbq },
97
+ es: abc[:sl],
98
+ eb: abc[:bx]
99
+ }
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @author Hernani Rodrigues Vaz
4
+ module Cns
5
+ # classe para processar historicos da beaconchain
6
+ class Beaconchain
7
+ # @return [String] texto validadores & saldos historicos
8
+ def mostra_resumo
9
+ return unless dados.count.positive?
10
+
11
+ puts("\nindex address beaconchain blh bigquery blh")
12
+ dados.each { |obj| puts(formata_validador(obj)) }
13
+ mostra_saldos
14
+ end
15
+
16
+ # @param [Hash] hjn dados juntos bigquery & beaconchain
17
+ # @return [String] texto formatado dum validador
18
+ def formata_validador(hjn)
19
+ format(
20
+ '%<s1>-5.5s %<s2>-34.34s ',
21
+ s1: hjn[:id],
22
+ s2: formata_endereco(hjn[:ax], 34)
23
+ ) + formata_valores(hjn)
24
+ end
25
+
26
+ # @param (see formata_validador)
27
+ # @return [String] texto formatado valores dum validador
28
+ def formata_valores(hjn)
29
+ format(
30
+ '%<v1>11.6f %<n1>3i %<v2>12.6f %<n2>6i %<ok>-3s',
31
+ v1: hjn[:es],
32
+ n1: hjn[:eb].count,
33
+ v2: hjn[:bs],
34
+ n2: hjn[:bb].count,
35
+ ok: ok?(hjn) ? 'OK' : 'NOK'
36
+ )
37
+ end
38
+
39
+ # @param (see formata_validador)
40
+ # @return [Boolean] validador tem historicos novos(sim=NOK, nao=OK)?
41
+ def ok?(hjn)
42
+ hjn[:bs] == hjn[:es]
43
+ end
44
+
45
+ # @example pubkey inicio..fim
46
+ # 0x10f3a0cf0b534c..c033cf32e8a03586
47
+ # @param [String] add chave publica validador
48
+ # @param [Integer] max chars a mostrar
49
+ # @return [String] pubkey formatada
50
+ def formata_endereco(add, max)
51
+ int = Integer((max - 2) / 2)
52
+ max < 7 ? 'erro' : "#{add[0, int - 3]}..#{add[-int - 3..]}"
53
+ end
54
+
55
+ # @example
56
+ # {
57
+ # balance: 32_489_497_108,
58
+ # effectivebalance: 32_000_000_000,
59
+ # epoch: 8296,
60
+ # validatorindex: 11_766,
61
+ # week: 5
62
+ # }
63
+ # @param [Hash] hbh historico beaconchain
64
+ # @return [String] texto formatado historico beaconchain
65
+ def formata_saldos(hbh)
66
+ idx = hbh[:validatorindex]
67
+ epc = hbh[:epoch]
68
+ format(
69
+ '%<vi>5i %<vl>17.6f %<ep>6i %<id>9i',
70
+ vi: idx,
71
+ vl: (hbh[:balance].to_d / 10**9).round(10),
72
+ ep: epc,
73
+ id: itx(epc, idx)
74
+ )
75
+ end
76
+
77
+ # @return [String] texto historico saldos
78
+ def mostra_saldos
79
+ return unless ops[:v] && nov.count.positive?
80
+
81
+ puts("\nindex saldo epoch itx")
82
+ sorbx.each { |obj| puts(formata_saldos(obj)) }
83
+ end
84
+
85
+ # @return [Array<Hash>] lista ordenada historico saldos
86
+ def sorbx
87
+ nov.sort { |ant, prx| ant[:itx] <=> prx[:itx] }
88
+ end
89
+ end
90
+ end
@@ -8,7 +8,7 @@ module Cns
8
8
  BD = 'hernanirvaz.coins'
9
9
 
10
10
  # (see Bigquery)
11
- class Cns::Bigquery
11
+ class Bigquery
12
12
  # @return [Google::Cloud::Bigquery] API bigquery
13
13
  attr_reader :api
14
14
  # @return [Google::Cloud::Bigquery::QueryJob] job bigquery
@@ -30,7 +30,7 @@ module Cns
30
30
  @ops = pop
31
31
  end
32
32
 
33
- # mostra situacao completa entre kraken/bitcoinde/paymium/therock/etherscan/greymass & bigquery
33
+ # mostra situacao completa entre kraken/bitcoinde/paymium/therock/etherscan/greymass/beaconchain & bigquery
34
34
  def mostra_tudo
35
35
  apius.mostra_resumo
36
36
  apide.mostra_resumo
@@ -38,51 +38,55 @@ module Cns
38
38
  apimt.mostra_resumo
39
39
  apies.mostra_resumo
40
40
  apigm.mostra_resumo
41
+ apibc.mostra_resumo
41
42
  end
42
43
 
43
- # insere (caso existam) transacoes novas kraken/bitcoinde/paymium/therock/etherscan/greymass no bigquery
44
+ # insere (caso existam) dados novos kraken/bitcoinde/paymium/therock/etherscan/greymass/beaconchain no bigquery
44
45
  def processa_tudo
45
46
  processa_us
46
47
  processa_de
47
- processa_fr
48
- processa_mt
48
+ processa_frmt
49
49
  processa_eth
50
50
  processa_eos
51
+ processa_bc
51
52
  end
52
53
 
53
54
  private
54
55
 
55
56
  # insere transacoes exchange kraken novas nas tabelas ust (trades), usl (ledger)
56
57
  def processa_us
57
- puts(format("%<n>2i TRADES KRAKEN INSERIDAS #{BD}.ust", n: apius.trades.empty? ? 0 : dml(ust_ins)))
58
- puts(format("%<n>2i LEDGER KRAKEN INSERIDAS #{BD}.usl", n: apius.ledger.empty? ? 0 : dml(usl_ins)))
58
+ puts(format("%<n>4i TRADES\tKRAKEN\t\tINSERIDAS ust", n: apius.trades.empty? ? 0 : dml(ust_ins)))
59
+ puts(format("%<n>4i LEDGER\tKRAKEN\t\tINSERIDAS usl", n: apius.ledger.empty? ? 0 : dml(usl_ins)))
59
60
  end
60
61
 
61
62
  # insere transacoes exchange bitcoinde novas nas tabelas det (trades), del (ledger)
62
63
  def processa_de
63
- puts(format("%<n>2i TRADES BITCOINDE INSERIDAS #{BD}.det", n: apide.trades.empty? ? 0 : dml(det_ins)))
64
- puts(format("%<n>2i LEDGER BITCOINDE INSERIDAS #{BD}.del", n: apide.ledger.empty? ? 0 : dml(del_ins)))
64
+ puts(format("%<n>4i TRADES\tBITCOINDE\tINSERIDAS det", n: apide.trades.empty? ? 0 : dml(det_ins)))
65
+ puts(format("%<n>4i LEDGER\tBITCOINDE\tINSERIDAS del", n: apide.ledger.empty? ? 0 : dml(del_ins)))
65
66
  end
66
67
 
67
- # insere transacoes exchange paymium novas na tabela fr (ledger)
68
- def processa_fr
69
- puts(format("%<n>2i LEDGER PAYMIUM INSERIDAS #{BD}.fr", n: apifr.ledger.empty? ? 0 : dml(frl_ins)))
70
- end
71
-
72
- # insere transacoes exchange therock novas na tabela mt (ledger)
73
- def processa_mt
74
- puts(format("%<n>2i LEDGER THEROCK INSERIDAS #{BD}.mt", n: apimt.ledger.empty? ? 0 : dml(mtl_ins)))
68
+ # insere transacoes exchange paymium/therock novas na tabela fr/mt (ledger)
69
+ def processa_frmt
70
+ puts(format("%<n>4i LEDGER\tPAYMIUM\t\tINSERIDAS fr", n: apifr.ledger.empty? ? 0 : dml(frl_ins)))
71
+ puts(format("%<n>4i LEDGER\tTHEROCK\t\tINSERIDAS mt", n: apimt.ledger.empty? ? 0 : dml(mtl_ins)))
75
72
  end
76
73
 
77
74
  # insere transacoes blockchain novas nas tabelas etht (norml), ethk (token)
78
75
  def processa_eth
79
- puts(format("%<n>2i TRANSACOES ETH INSERIDAS #{BD}.etht", n: apies.novtx.empty? ? 0 : dml(etht_ins)))
80
- puts(format("%<n>2i TOKEN EVENTS ETH INSERIDAS #{BD}.ethk", n: apies.novkx.empty? ? 0 : dml(ethk_ins)))
76
+ puts(format("%<n>4i TRANSACOES\tETH\t\tINSERIDAS etht", n: apies.novtx.empty? ? 0 : dml(etht_ins)))
77
+ puts(format("%<n>4i TOKENS\tETH\t\tINSERIDAS ethk", n: apies.novkx.empty? ? 0 : dml(ethk_ins)))
81
78
  end
82
79
 
83
80
  # insere transacoes blockchain novas na tabela eos
84
81
  def processa_eos
85
- puts(format("%<n>2i TRANSACOES EOS INSERIDAS #{BD}.eos ", n: apigm.novax.empty? ? 0 : dml(eost_ins)))
82
+ puts(format("%<n>4i TRANSACOES\tEOS\t\tINSERIDAS eos ", n: apigm.novax.empty? ? 0 : dml(eost_ins)))
83
+ end
84
+
85
+ # insere historico sados novos na tabela eth2bh
86
+ def processa_bc
87
+ # puts(format("%<n>4i ATTESTATIONS INSERIDAS #{BD}.eth2at", n: apibc.novtx.empty? ? 0 : dml(eth2at_ins)))
88
+ # puts(format("%<n>4i PROPOSALS INSERIDAS #{BD}.eth2pr", n: apibc.novkx.empty? ? 0 : dml(eth2pr_ins)))
89
+ puts(format("%<n>4i BALANCES\tETH2\t\tINSERIDOS eth2bh", n: apibc.nov.empty? ? 0 : dml(eth2bh_ins)))
86
90
  end
87
91
 
88
92
  # cria job bigquery & verifica execucao
@@ -91,9 +95,10 @@ module Cns
91
95
  # @return [Boolean] job ok?
92
96
  def job?(cmd)
93
97
  @job = api.query_job(cmd)
94
- @job.wait_until_done!
95
- puts(@job.error['message']) if @job.failed?
96
- @job.failed?
98
+ job.wait_until_done!
99
+ fld = job.failed?
100
+ puts(job.error['message']) if fld
101
+ fld
97
102
  end
98
103
 
99
104
  # cria Structured Query Language (SQL) job bigquery