iota-ruby 1.1.8-java
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 +7 -0
- data/.editorconfig +8 -0
- data/.gitignore +15 -0
- data/.travis.yml +24 -0
- data/.yardopts +7 -0
- data/CHANGELOG.md +18 -0
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/README.md +121 -0
- data/Rakefile +36 -0
- data/bin/iota-console +15 -0
- data/examples/multisig.rb +69 -0
- data/ext/ccurl/ccurl.c +134 -0
- data/ext/ccurl/extconf.rb +22 -0
- data/ext/jcurl/JCurl.java +126 -0
- data/ext/jcurl/JCurlService.java +36 -0
- data/ext/pow/ccurl-0.3.0.dll +0 -0
- data/ext/pow/libccurl-0.3.0.dylib +0 -0
- data/ext/pow/libccurl-0.3.0.so +0 -0
- data/iota-ruby.gemspec +37 -0
- data/lib/iota.rb +76 -0
- data/lib/iota/api/api.rb +251 -0
- data/lib/iota/api/commands.rb +113 -0
- data/lib/iota/api/transport.rb +43 -0
- data/lib/iota/api/wrappers.rb +429 -0
- data/lib/iota/crypto/bundle.rb +163 -0
- data/lib/iota/crypto/converter.rb +244 -0
- data/lib/iota/crypto/curl.rb +18 -0
- data/lib/iota/crypto/curl_c.rb +17 -0
- data/lib/iota/crypto/curl_java.rb +18 -0
- data/lib/iota/crypto/curl_ruby.rb +70 -0
- data/lib/iota/crypto/hmac.rb +27 -0
- data/lib/iota/crypto/kerl.rb +82 -0
- data/lib/iota/crypto/pow_provider.rb +27 -0
- data/lib/iota/crypto/private_key.rb +80 -0
- data/lib/iota/crypto/sha3_ruby.rb +122 -0
- data/lib/iota/crypto/signing.rb +97 -0
- data/lib/iota/models/account.rb +489 -0
- data/lib/iota/models/base.rb +13 -0
- data/lib/iota/models/bundle.rb +87 -0
- data/lib/iota/models/input.rb +38 -0
- data/lib/iota/models/seed.rb +33 -0
- data/lib/iota/models/transaction.rb +52 -0
- data/lib/iota/models/transfer.rb +44 -0
- data/lib/iota/multisig/address.rb +41 -0
- data/lib/iota/multisig/multisig.rb +244 -0
- data/lib/iota/utils/ascii.rb +50 -0
- data/lib/iota/utils/broker.rb +124 -0
- data/lib/iota/utils/input_validator.rb +149 -0
- data/lib/iota/utils/object_validator.rb +34 -0
- data/lib/iota/utils/utils.rb +324 -0
- data/lib/iota/version.rb +3 -0
- data/lib/jcurl.jar +0 -0
- data/lib/patch.rb +17 -0
- data/test/ascii_test.rb +114 -0
- data/test/curl_c_test.rb +31 -0
- data/test/curl_java_test.rb +31 -0
- data/test/curl_ruby_test.rb +27 -0
- data/test/kerl_test.rb +52 -0
- data/test/pow_provider_test.rb +36 -0
- data/test/sha3_test.rb +71 -0
- data/test/test_helper.rb +4 -0
- data/test/utils_test.rb +179 -0
- metadata +183 -0
@@ -0,0 +1,113 @@
|
|
1
|
+
module IOTA
|
2
|
+
module API
|
3
|
+
class Commands
|
4
|
+
def findTransactions(searchValues)
|
5
|
+
command = {
|
6
|
+
command: 'findTransactions'
|
7
|
+
}
|
8
|
+
|
9
|
+
searchValues.each { |k, v| command[k.to_sym] = v }
|
10
|
+
|
11
|
+
command
|
12
|
+
end
|
13
|
+
|
14
|
+
def getBalances(addresses, threshold)
|
15
|
+
{
|
16
|
+
command: 'getBalances',
|
17
|
+
addresses: addresses,
|
18
|
+
threshold: threshold
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def getTrytes(hashes)
|
23
|
+
{
|
24
|
+
command: 'getTrytes',
|
25
|
+
hashes: hashes
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def getInclusionStates(transactions, tips)
|
30
|
+
{
|
31
|
+
command: 'getInclusionStates',
|
32
|
+
transactions: transactions,
|
33
|
+
tips: tips
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def getNodeInfo
|
38
|
+
{ command: 'getNodeInfo'}
|
39
|
+
end
|
40
|
+
|
41
|
+
def getNeighbors
|
42
|
+
{ command: 'getNeighbors' }
|
43
|
+
end
|
44
|
+
|
45
|
+
def addNeighbors(uris)
|
46
|
+
{
|
47
|
+
command: 'addNeighbors',
|
48
|
+
uris: uris
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
def removeNeighbors(uris)
|
53
|
+
{
|
54
|
+
command: 'removeNeighbors',
|
55
|
+
uris: uris
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
def getTips
|
60
|
+
{ command: 'getTips' }
|
61
|
+
end
|
62
|
+
|
63
|
+
def getTransactionsToApprove(depth, reference = nil)
|
64
|
+
{
|
65
|
+
command: 'getTransactionsToApprove',
|
66
|
+
depth: depth
|
67
|
+
}.merge(reference.nil? ? {} : { reference: reference })
|
68
|
+
end
|
69
|
+
|
70
|
+
def attachToTangle(trunkTransaction, branchTransaction, minWeightMagnitude, trytes)
|
71
|
+
{
|
72
|
+
command: 'attachToTangle',
|
73
|
+
trunkTransaction: trunkTransaction,
|
74
|
+
branchTransaction: branchTransaction,
|
75
|
+
minWeightMagnitude: minWeightMagnitude,
|
76
|
+
trytes: trytes
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
def interruptAttachingToTangle
|
81
|
+
{ command: 'interruptAttachingToTangle' }
|
82
|
+
end
|
83
|
+
|
84
|
+
def broadcastTransactions(trytes)
|
85
|
+
{
|
86
|
+
command: 'broadcastTransactions',
|
87
|
+
trytes: trytes
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
def storeTransactions(trytes)
|
92
|
+
{
|
93
|
+
command: 'storeTransactions',
|
94
|
+
trytes: trytes
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
def checkConsistency(tails)
|
99
|
+
{
|
100
|
+
command: 'checkConsistency',
|
101
|
+
tails: tails
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
def wereAddressesSpentFrom(addresses)
|
106
|
+
{
|
107
|
+
command: 'wereAddressesSpentFrom',
|
108
|
+
addresses: addresses
|
109
|
+
}
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module IOTA
|
2
|
+
module API
|
3
|
+
module Transport
|
4
|
+
def sendCommand(command, &callback)
|
5
|
+
@broker.send(command, &callback)
|
6
|
+
end
|
7
|
+
|
8
|
+
def sendBatchedCommand(command, &callback)
|
9
|
+
# Key and value both should be symbols
|
10
|
+
mapping = {
|
11
|
+
getTrytes: [ :hashes ],
|
12
|
+
getBalances: [ :addresses ],
|
13
|
+
wereAddressesSpentFrom: [ :addresses ],
|
14
|
+
getInclusionStates: [ :transactions ],
|
15
|
+
findTransactions: [ :bundles, :addresses, :tags, :approvees ]
|
16
|
+
}
|
17
|
+
|
18
|
+
command_name = command[:command].to_sym
|
19
|
+
if mapping[command_name]
|
20
|
+
results = []
|
21
|
+
|
22
|
+
keys_to_batch = mapping[command_name]
|
23
|
+
keys_to_batch.each do |key|
|
24
|
+
if command[key]
|
25
|
+
command[key].each_slice(@batch_size) do |group|
|
26
|
+
batchedCommand = command.clone.merge({ key => group })
|
27
|
+
sendCommand(batchedCommand) do |status, response|
|
28
|
+
if !status
|
29
|
+
return sendData(false, response, &callback)
|
30
|
+
end
|
31
|
+
results += response
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
return sendData(true, results, &callback)
|
37
|
+
else
|
38
|
+
return sendCommand(command, &callback)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,429 @@
|
|
1
|
+
module IOTA
|
2
|
+
module API
|
3
|
+
module Wrappers
|
4
|
+
def getTransactionsObjects(hashes, &callback)
|
5
|
+
# If not array of hashes, return error
|
6
|
+
if !@validator.isArrayOfHashes(hashes)
|
7
|
+
return sendData(false, "Invalid inputs provided", &callback)
|
8
|
+
end
|
9
|
+
|
10
|
+
ret_status = false
|
11
|
+
ret_data = nil
|
12
|
+
# get the trytes of the transaction hashes
|
13
|
+
getTrytes(hashes) do |status, trytes|
|
14
|
+
ret_status = status
|
15
|
+
if status
|
16
|
+
transactionObjects = []
|
17
|
+
trytes.each do |tryte|
|
18
|
+
if !tryte
|
19
|
+
transactionObjects << nil
|
20
|
+
else
|
21
|
+
transactionObjects << @utils.transactionObject(tryte)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
ret_data = transactionObjects
|
25
|
+
else
|
26
|
+
ret_data = trytes
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
sendData(ret_status, ret_data, &callback)
|
31
|
+
end
|
32
|
+
|
33
|
+
def findTransactionObjects(input, &callback)
|
34
|
+
findTransactions(input) do |status, transactions|
|
35
|
+
if !status
|
36
|
+
return sendData(status, transactions, &callback)
|
37
|
+
else
|
38
|
+
return getTransactionsObjects(transactions, &callback)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def getLatestInclusion(hashes, &callback)
|
44
|
+
ret_status = false
|
45
|
+
ret_data = nil
|
46
|
+
getNodeInfo do |status, data|
|
47
|
+
if status
|
48
|
+
ret_status = true
|
49
|
+
ret_data = data['latestSolidSubtangleMilestone']
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
if ret_status
|
54
|
+
return getInclusionStates(hashes, [ret_data], &callback)
|
55
|
+
else
|
56
|
+
return sendData(ret_status, ret_data, &callback)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def storeAndBroadcast(trytes, &callback)
|
61
|
+
storeTransactions(trytes) do |status, data|
|
62
|
+
if !status
|
63
|
+
return sendData(status, data, &callback)
|
64
|
+
else
|
65
|
+
return broadcastTransactions(trytes, &callback)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def sendTrytes(trytes, depth, minWeightMagnitude, options = {}, &callback)
|
71
|
+
# Check if correct depth and minWeightMagnitude
|
72
|
+
if !@validator.isValue(depth) || !@validator.isValue(minWeightMagnitude)
|
73
|
+
return sendData(false, "Invalid inputs provided", &callback)
|
74
|
+
end
|
75
|
+
|
76
|
+
reference = options[:reference] || options['reference']
|
77
|
+
|
78
|
+
getTransactionsToApprove(depth, reference) do |status, approval_data|
|
79
|
+
if !status
|
80
|
+
return sendData(false, approval_data, &callback)
|
81
|
+
end
|
82
|
+
|
83
|
+
attachToTangle(approval_data['trunkTransaction'], approval_data['branchTransaction'], minWeightMagnitude, trytes) do |status1, attached_data|
|
84
|
+
if !status1
|
85
|
+
return sendData(false, attached_data, &callback)
|
86
|
+
end
|
87
|
+
|
88
|
+
# If the user is connected to the sandbox and local pow is not used, we have to monitor the POW queue to check if the POW job was completed
|
89
|
+
if @sandbox && @pow_provider.nil?
|
90
|
+
# Implement sandbox processing
|
91
|
+
jobUri = @sandbox + '/jobs/' + attached_data['id']
|
92
|
+
|
93
|
+
# Do the Sandbox send function
|
94
|
+
@broker.sandboxSend(jobUri) do |status2, sandbox_data|
|
95
|
+
if !status2
|
96
|
+
return sendData(false, sandbox_data, &callback)
|
97
|
+
end
|
98
|
+
|
99
|
+
storeAndBroadcast(sandbox_data) do |status3, data|
|
100
|
+
if status3
|
101
|
+
return sendData(false, data, &callback)
|
102
|
+
end
|
103
|
+
|
104
|
+
finalTxs = []
|
105
|
+
|
106
|
+
attachedTrytes.each do |trytes1|
|
107
|
+
finalTxs << @utils.transactionObject(trytes1)
|
108
|
+
end
|
109
|
+
|
110
|
+
return sendData(true, finalTxs, &callback)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
else
|
114
|
+
# Broadcast and store tx
|
115
|
+
storeAndBroadcast(attached_data) do |status2, data|
|
116
|
+
if !status2
|
117
|
+
return sendData(false, data, &callback)
|
118
|
+
end
|
119
|
+
|
120
|
+
transactions = attached_data.map { |tryte| @utils.transactionObject(tryte) }
|
121
|
+
|
122
|
+
sendData(true, transactions, &callback)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def bundlesFromAddresses(addresses, inclusionStates, &callback)
|
130
|
+
# call wrapper function to get txs associated with addresses
|
131
|
+
findTransactionObjects(addresses: addresses) do |status, transactionObjects|
|
132
|
+
if !status
|
133
|
+
return sendData(false, transactionObjects, &callback)
|
134
|
+
end
|
135
|
+
|
136
|
+
# set of tail transactions
|
137
|
+
tailTransactions = []
|
138
|
+
nonTailBundleHashes = []
|
139
|
+
|
140
|
+
transactionObjects.each do |trx|
|
141
|
+
# Sort tail and nonTails
|
142
|
+
if trx.currentIndex == 0
|
143
|
+
tailTransactions << trx.hash
|
144
|
+
else
|
145
|
+
nonTailBundleHashes << trx.bundle
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# Get tail transactions for each nonTail via the bundle hash
|
150
|
+
findTransactionObjects(bundles: nonTailBundleHashes.uniq) do |st1, trxObjects|
|
151
|
+
if !st1
|
152
|
+
return sendData(false, trxObjects, &callback)
|
153
|
+
end
|
154
|
+
|
155
|
+
trxObjects.each do |trx|
|
156
|
+
tailTransactions << trx.hash if trx.currentIndex == 0
|
157
|
+
end
|
158
|
+
|
159
|
+
finalBundles = []
|
160
|
+
tailTransactions = tailTransactions.uniq
|
161
|
+
tailTxStates = []
|
162
|
+
|
163
|
+
# If inclusionStates, get the confirmation status of the tail transactions, and thus the bundles
|
164
|
+
if inclusionStates && tailTransactions.length > 0
|
165
|
+
getLatestInclusion(tailTransactions) do |st2, states|
|
166
|
+
# If error, return it to original caller
|
167
|
+
if !status
|
168
|
+
return sendData(false, states, &callback)
|
169
|
+
end
|
170
|
+
|
171
|
+
tailTxStates = states
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
tailTransactions.each do |tailTx|
|
176
|
+
getBundle(tailTx) do |st2, bundleTransactions|
|
177
|
+
if st2
|
178
|
+
if inclusionStates
|
179
|
+
thisInclusion = tailTxStates[tailTransactions.index(tailTx)]
|
180
|
+
|
181
|
+
bundleTransactions.each do |bundleTx|
|
182
|
+
bundleTx.persistence = thisInclusion
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
finalBundles << IOTA::Models::Bundle.new(bundleTransactions)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
# Sort bundles by attachmentTimestamp
|
191
|
+
finalBundles = finalBundles.sort{|a, b| a.attachmentTimestamp <=> b.attachmentTimestamp}
|
192
|
+
return sendData(true, finalBundles, &callback)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def getBundle(transaction, &callback)
|
198
|
+
# Check if correct hash
|
199
|
+
if !@validator.isHash(transaction)
|
200
|
+
return sendData(false, "Invalid transaction input provided", &callback)
|
201
|
+
end
|
202
|
+
|
203
|
+
# Initiate traverseBundle
|
204
|
+
traverseBundle(transaction, nil, []) do |status, bundle|
|
205
|
+
if !status
|
206
|
+
return sendData(false, bundle, &callback)
|
207
|
+
end
|
208
|
+
|
209
|
+
if !@utils.isBundle(bundle)
|
210
|
+
return sendData(false, "Invalid Bundle provided", &callback)
|
211
|
+
end
|
212
|
+
|
213
|
+
return sendData(true, bundle, &callback)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
# Replays or promote transactions based on tail consistency
|
218
|
+
def replayBundle(tail, depth, minWeightMagnitude, forcedReplay = false, &callback)
|
219
|
+
# Check if correct tail hash
|
220
|
+
if !@validator.isHash(tail)
|
221
|
+
return sendData(false, "Invalid trytes provided", &callback)
|
222
|
+
end
|
223
|
+
|
224
|
+
# Check if correct depth and minWeightMagnitude
|
225
|
+
if !@validator.isValue(depth) || !@validator.isValue(minWeightMagnitude)
|
226
|
+
return sendData(false, "Invalid inputs provided", &callback)
|
227
|
+
end
|
228
|
+
|
229
|
+
isPromotable = false
|
230
|
+
if !forcedReplay
|
231
|
+
checkConsistency([tail]) do |status, isConsistent|
|
232
|
+
isPromotable = status && isConsistent
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
getBundle(tail) do |status, transactions|
|
237
|
+
if !status
|
238
|
+
return sendData(false, transactions, &callback)
|
239
|
+
end
|
240
|
+
|
241
|
+
if !isPromotable
|
242
|
+
bundleTrytes = []
|
243
|
+
transactions.each do |trx|
|
244
|
+
bundleTrytes << @utils.transactionTrytes(trx);
|
245
|
+
end
|
246
|
+
|
247
|
+
return sendTrytes(bundleTrytes.reverse, depth, minWeightMagnitude, &callback)
|
248
|
+
else
|
249
|
+
account = IOTA::Models::Account.new(nil, transactions.first.address, self, @validator, @utils)
|
250
|
+
|
251
|
+
transfers = [{
|
252
|
+
address: '9' * 81,
|
253
|
+
value: 0,
|
254
|
+
message: '',
|
255
|
+
tag: ''
|
256
|
+
}]
|
257
|
+
|
258
|
+
begin
|
259
|
+
account.sendTransfer(depth, minWeightMagnitude, transfers, { reference: tail })
|
260
|
+
return sendData(status, transactions, &callback)
|
261
|
+
rescue => e
|
262
|
+
return sendData(false, e.message, &callback)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
def broadcastBundle(tail, &callback)
|
269
|
+
# Check if correct tail hash
|
270
|
+
if !@validator.isHash(tail)
|
271
|
+
return sendData(false, "Invalid trytes provided", &callback)
|
272
|
+
end
|
273
|
+
|
274
|
+
getBundle(tail) do |status, transactions|
|
275
|
+
if !status
|
276
|
+
return sendData(false, transactions, &callback)
|
277
|
+
end
|
278
|
+
|
279
|
+
bundleTrytes = []
|
280
|
+
transactions.each do |trx|
|
281
|
+
bundleTrytes << @utils.transactionTrytes(trx);
|
282
|
+
end
|
283
|
+
|
284
|
+
return broadcastTransactions(bundleTrytes.reverse, &callback)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def traverseBundle(trunkTx, bundleHash, bundle, &callback)
|
289
|
+
# Get trytes of transaction hash
|
290
|
+
getTrytes([trunkTx]) do |status, trytesList|
|
291
|
+
if !status
|
292
|
+
return sendData(false, trytesList, &callback)
|
293
|
+
end
|
294
|
+
|
295
|
+
trytes = trytesList[0]
|
296
|
+
|
297
|
+
if !trytes
|
298
|
+
return sendData(false, "Bundle transactions not visible", &callback)
|
299
|
+
end
|
300
|
+
|
301
|
+
# get the transaction object
|
302
|
+
txObject = @utils.transactionObject(trytes)
|
303
|
+
|
304
|
+
if !trytes
|
305
|
+
return sendData(false, "Invalid trytes, could not create object", &callback)
|
306
|
+
end
|
307
|
+
|
308
|
+
# If first transaction to search is not a tail, return error
|
309
|
+
if !bundleHash && txObject.currentIndex != 0
|
310
|
+
return sendData(false, "Invalid tail transaction supplied", &callback)
|
311
|
+
end
|
312
|
+
|
313
|
+
# If no bundle hash, define it
|
314
|
+
if !bundleHash
|
315
|
+
bundleHash = txObject.bundle
|
316
|
+
end
|
317
|
+
|
318
|
+
# If different bundle hash, return with bundle
|
319
|
+
if bundleHash != txObject.bundle
|
320
|
+
return sendData(true, bundle, &callback)
|
321
|
+
end
|
322
|
+
|
323
|
+
# If only one bundle element, return
|
324
|
+
if txObject.lastIndex == 0 && txObject.currentIndex == 0
|
325
|
+
return sendData(true, [txObject], &callback)
|
326
|
+
end
|
327
|
+
|
328
|
+
# Define new trunkTransaction for search
|
329
|
+
trunkTx = txObject.trunkTransaction
|
330
|
+
|
331
|
+
# Add transaction object to bundle
|
332
|
+
bundle << txObject
|
333
|
+
|
334
|
+
# Continue traversing with new trunkTx
|
335
|
+
return traverseBundle(trunkTx, bundleHash, bundle, &callback)
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
def isReattachable(inputAddresses, &callback)
|
340
|
+
# if string provided, make array
|
341
|
+
inputAddresses = [inputAddresses] if @validator.isString(inputAddresses)
|
342
|
+
|
343
|
+
# Categorized value transactions
|
344
|
+
# hash -> txarray map
|
345
|
+
addressTxsMap = {}
|
346
|
+
addresses = []
|
347
|
+
|
348
|
+
inputAddresses.each do |address|
|
349
|
+
if !@validator.isAddress(address)
|
350
|
+
return sendData(false, "Invalid inputs provided", &callback)
|
351
|
+
end
|
352
|
+
|
353
|
+
address = @utils.noChecksum(address)
|
354
|
+
|
355
|
+
addressTxsMap[address] = []
|
356
|
+
addresses << address
|
357
|
+
end
|
358
|
+
|
359
|
+
findTransactionObjects(addresses: addresses) do |status, transactions|
|
360
|
+
if !status
|
361
|
+
return sendData(false, transactions, &callback)
|
362
|
+
end
|
363
|
+
|
364
|
+
valueTransactions = []
|
365
|
+
|
366
|
+
transactions.each do |trx|
|
367
|
+
if trx.value < 0
|
368
|
+
txAddress = trx.address
|
369
|
+
txHash = trx.hash
|
370
|
+
|
371
|
+
addressTxsMap[txAddress] << txHash
|
372
|
+
valueTransactions << txHash
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
if valueTransactions.length > 0
|
377
|
+
# get the includion states of all the transactions
|
378
|
+
getLatestInclusion(valueTransactions) do |st1, inclusionStates|
|
379
|
+
if !st1
|
380
|
+
return sendData(false, inclusionStates, &callback)
|
381
|
+
end
|
382
|
+
|
383
|
+
# bool array
|
384
|
+
results = addresses.map do |address|
|
385
|
+
txs = addressTxsMap[address]
|
386
|
+
numTxs = txs.length
|
387
|
+
|
388
|
+
if numTxs == 0
|
389
|
+
true
|
390
|
+
else
|
391
|
+
shouldReattach = true
|
392
|
+
|
393
|
+
(0...numTxs).step(1) do |i|
|
394
|
+
tx = txs[i]
|
395
|
+
txIndex = valueTransactions.index(tx)
|
396
|
+
isConfirmed = inclusionStates[txIndex]
|
397
|
+
shouldReattach = isConfirmed ? false : true
|
398
|
+
break if isConfirmed
|
399
|
+
end
|
400
|
+
|
401
|
+
shouldReattach
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
# If only one entry, return first
|
406
|
+
results = results.first if results.length == 1
|
407
|
+
|
408
|
+
return sendData(true, results, &callback)
|
409
|
+
end
|
410
|
+
else
|
411
|
+
results = [];
|
412
|
+
numAddresses = addresses.length;
|
413
|
+
|
414
|
+
# prepare results array if multiple addresses
|
415
|
+
if numAddresses > 1
|
416
|
+
numAddresses.each do |i|
|
417
|
+
results << true
|
418
|
+
end
|
419
|
+
else
|
420
|
+
results = true
|
421
|
+
end
|
422
|
+
|
423
|
+
return sendData(true, results, &callback)
|
424
|
+
end
|
425
|
+
end
|
426
|
+
end
|
427
|
+
end
|
428
|
+
end
|
429
|
+
end
|