antd 0.1.0
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/LICENSE-APACHE +201 -0
- data/LICENSE-MIT +21 -0
- data/README.md +184 -0
- data/lib/antd/client.rb +675 -0
- data/lib/antd/discover.rb +132 -0
- data/lib/antd/errors.rb +73 -0
- data/lib/antd/grpc_client.rb +549 -0
- data/lib/antd/models.rb +198 -0
- data/lib/antd/v1/chunks_pb.rb +26 -0
- data/lib/antd/v1/chunks_services_pb.rb +32 -0
- data/lib/antd/v1/common_pb.rb +21 -0
- data/lib/antd/v1/data_pb.rb +31 -0
- data/lib/antd/v1/data_services_pb.rb +36 -0
- data/lib/antd/v1/files_pb.rb +25 -0
- data/lib/antd/v1/files_services_pb.rb +31 -0
- data/lib/antd/v1/health_pb.rb +18 -0
- data/lib/antd/v1/health_services_pb.rb +24 -0
- data/lib/antd/v1/upload_pb.rb +25 -0
- data/lib/antd/v1/upload_services_pb.rb +51 -0
- data/lib/antd/v1/wallet_pb.rb +22 -0
- data/lib/antd/v1/wallet_services_pb.rb +42 -0
- data/lib/antd/version.rb +5 -0
- data/lib/antd.rb +14 -0
- metadata +145 -0
|
@@ -0,0 +1,549 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Proto-generated Ruby stubs — produced by `grpc_tools_ruby_protoc`.
|
|
4
|
+
# Run:
|
|
5
|
+
# grpc_tools_ruby_protoc \
|
|
6
|
+
# -I../../antd/proto \
|
|
7
|
+
# --ruby_out=lib --grpc_out=lib \
|
|
8
|
+
# antd/v1/common.proto antd/v1/health.proto antd/v1/data.proto \
|
|
9
|
+
# antd/v1/chunks.proto antd/v1/files.proto antd/v1/upload.proto
|
|
10
|
+
#
|
|
11
|
+
# The generated files are expected under lib/antd/v1/.
|
|
12
|
+
|
|
13
|
+
require "grpc"
|
|
14
|
+
require_relative "v1/health_services_pb"
|
|
15
|
+
require_relative "v1/data_services_pb"
|
|
16
|
+
require_relative "v1/chunks_services_pb"
|
|
17
|
+
require_relative "v1/files_services_pb"
|
|
18
|
+
require_relative "v1/upload_services_pb"
|
|
19
|
+
require_relative "v1/wallet_services_pb"
|
|
20
|
+
|
|
21
|
+
module Antd
|
|
22
|
+
DEFAULT_GRPC_TARGET = "localhost:50051"
|
|
23
|
+
|
|
24
|
+
# gRPC client for the antd daemon.
|
|
25
|
+
#
|
|
26
|
+
# Provides the same methods as the REST +Client+, but communicates over
|
|
27
|
+
# gRPC using the proto-generated stubs from +antd/v1/*.proto+.
|
|
28
|
+
class GrpcClient
|
|
29
|
+
# Creates a gRPC client using port discovery.
|
|
30
|
+
#
|
|
31
|
+
# Reads the daemon.port file to find the gRPC port. Falls back to the
|
|
32
|
+
# default target if the port file is not found.
|
|
33
|
+
#
|
|
34
|
+
# @return [Array(GrpcClient, String)] the client and the resolved target
|
|
35
|
+
def self.auto_discover
|
|
36
|
+
target = Antd::Discover.grpc_target
|
|
37
|
+
target = DEFAULT_GRPC_TARGET if target.empty?
|
|
38
|
+
[new(target: target), target]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @param target [String] gRPC target address (default: "localhost:50051")
|
|
42
|
+
def initialize(target: DEFAULT_GRPC_TARGET)
|
|
43
|
+
@target = target
|
|
44
|
+
@health_stub = Antd::V1::HealthService::Stub.new(target, :this_channel_is_insecure)
|
|
45
|
+
@data_stub = Antd::V1::DataService::Stub.new(target, :this_channel_is_insecure)
|
|
46
|
+
@chunk_stub = Antd::V1::ChunkService::Stub.new(target, :this_channel_is_insecure)
|
|
47
|
+
@file_stub = Antd::V1::FileService::Stub.new(target, :this_channel_is_insecure)
|
|
48
|
+
@upload_stub = Antd::V1::UploadService::Stub.new(target, :this_channel_is_insecure)
|
|
49
|
+
@wallet_stub = Antd::V1::WalletService::Stub.new(target, :this_channel_is_insecure)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# --- Health ---
|
|
53
|
+
|
|
54
|
+
# Check daemon status.
|
|
55
|
+
# @return [HealthStatus]
|
|
56
|
+
def health
|
|
57
|
+
resp = grpc_call { @health_stub.check(Antd::V1::HealthCheckRequest.new) }
|
|
58
|
+
HealthStatus.new(
|
|
59
|
+
ok: resp.status == "ok",
|
|
60
|
+
network: resp.network,
|
|
61
|
+
version: resp.version,
|
|
62
|
+
evm_network: resp.evm_network,
|
|
63
|
+
uptime_seconds: resp.uptime_seconds,
|
|
64
|
+
build_commit: resp.build_commit,
|
|
65
|
+
payment_token_address: resp.payment_token_address,
|
|
66
|
+
payment_vault_address: resp.payment_vault_address
|
|
67
|
+
)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# --- Data ---
|
|
71
|
+
|
|
72
|
+
# Store private encrypted data. Returns the caller-held DataMap (hex).
|
|
73
|
+
# @param data [String] raw bytes
|
|
74
|
+
# @param payment_mode [String] PaymentMode::AUTO | MERKLE | SINGLE
|
|
75
|
+
# @return [DataPutResult]
|
|
76
|
+
def data_put(data, payment_mode: PaymentMode::AUTO)
|
|
77
|
+
req = Antd::V1::PutDataRequest.new(data: data.b, payment_mode: payment_mode)
|
|
78
|
+
resp = grpc_call { @data_stub.put(req) }
|
|
79
|
+
DataPutResult.new(data_map: resp.data_map, chunks_stored: resp.chunks_stored, payment_mode_used: resp.payment_mode_used)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Retrieve private data from a caller-held DataMap (hex).
|
|
83
|
+
# @param data_map [String]
|
|
84
|
+
# @return [String] raw bytes
|
|
85
|
+
def data_get(data_map)
|
|
86
|
+
req = Antd::V1::GetDataRequest.new(data_map: data_map)
|
|
87
|
+
resp = grpc_call { @data_stub.get(req) }
|
|
88
|
+
resp.data
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Store public data. Returns the on-network DataMap address.
|
|
92
|
+
# @param data [String] raw bytes
|
|
93
|
+
# @param payment_mode [String] PaymentMode::AUTO | MERKLE | SINGLE
|
|
94
|
+
# @return [DataPutPublicResult]
|
|
95
|
+
def data_put_public(data, payment_mode: PaymentMode::AUTO)
|
|
96
|
+
req = Antd::V1::PutPublicDataRequest.new(data: data.b, payment_mode: payment_mode)
|
|
97
|
+
resp = grpc_call { @data_stub.put_public(req) }
|
|
98
|
+
DataPutPublicResult.new(address: resp.address, chunks_stored: resp.chunks_stored, payment_mode_used: resp.payment_mode_used)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Retrieve public data by address.
|
|
102
|
+
# @param address [String] hex address
|
|
103
|
+
# @return [String] raw bytes
|
|
104
|
+
def data_get_public(address)
|
|
105
|
+
req = Antd::V1::GetPublicDataRequest.new(address: address)
|
|
106
|
+
resp = grpc_call { @data_stub.get_public(req) }
|
|
107
|
+
resp.data
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Stream private data from a caller-held DataMap (hex), one decrypt batch at
|
|
111
|
+
# a time, instead of buffering the whole object. The gRPC counterpart to
|
|
112
|
+
# +data_get+ and mirror of the REST client's +data_stream+.
|
|
113
|
+
#
|
|
114
|
+
# When a block is given, each raw byte chunk is yielded as it arrives and the
|
|
115
|
+
# method returns +nil+. When no block is given, an +Enumerator+ over the
|
|
116
|
+
# chunks is returned.
|
|
117
|
+
#
|
|
118
|
+
# @param data_map [String] hex-encoded DataMap
|
|
119
|
+
# @yieldparam chunk [String] a raw byte chunk of the decrypted payload
|
|
120
|
+
# @return [nil, Enumerator]
|
|
121
|
+
def data_stream(data_map, &block)
|
|
122
|
+
return enum_for(:data_stream, data_map) unless block_given?
|
|
123
|
+
|
|
124
|
+
req = Antd::V1::StreamDataRequest.new(data_map: data_map)
|
|
125
|
+
grpc_call { @data_stub.stream(req).each { |chunk| block.call(chunk.data) } }
|
|
126
|
+
nil
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Stream public data by address — the gRPC counterpart to +data_get_public+.
|
|
130
|
+
# Same block/Enumerator contract as +data_stream+.
|
|
131
|
+
#
|
|
132
|
+
# @param address [String] hex address
|
|
133
|
+
# @yieldparam chunk [String] a raw byte chunk of the decrypted payload
|
|
134
|
+
# @return [nil, Enumerator]
|
|
135
|
+
def data_stream_public(address, &block)
|
|
136
|
+
return enum_for(:data_stream_public, address) unless block_given?
|
|
137
|
+
|
|
138
|
+
req = Antd::V1::StreamPublicDataRequest.new(address: address)
|
|
139
|
+
grpc_call { @data_stub.stream_public(req).each { |chunk| block.call(chunk.data) } }
|
|
140
|
+
nil
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Like +data_stream+ but requests interleaved fetch-progress frames so the
|
|
144
|
+
# caller can drive a *determinate* progress bar. Sets the request's
|
|
145
|
+
# +include_progress+ flag and yields +DownloadFrame+s — each either a
|
|
146
|
+
# plaintext byte chunk (+frame.data+) or a +DownloadProgress+ update
|
|
147
|
+
# (+frame.progress+). The byte denominator is surfaced as a leading
|
|
148
|
+
# +DownloadFrame+ (+frame.meta+), read from the response's
|
|
149
|
+
# +x-content-length+ initial metadata before any chunk.
|
|
150
|
+
#
|
|
151
|
+
# When a block is given each frame is yielded and the method returns +nil+;
|
|
152
|
+
# otherwise an +Enumerator+ over the frames is returned.
|
|
153
|
+
#
|
|
154
|
+
# @param data_map [String] hex-encoded DataMap
|
|
155
|
+
# @yieldparam frame [DownloadFrame]
|
|
156
|
+
# @return [nil, Enumerator]
|
|
157
|
+
def data_stream_with_progress(data_map, &block)
|
|
158
|
+
return enum_for(:data_stream_with_progress, data_map) unless block_given?
|
|
159
|
+
|
|
160
|
+
req = Antd::V1::StreamDataRequest.new(data_map: data_map, include_progress: true)
|
|
161
|
+
grpc_call { stream_with_progress(@data_stub.stream(req, return_op: true), &block) }
|
|
162
|
+
nil
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Like +data_stream_public+ but requests interleaved fetch-progress frames.
|
|
166
|
+
# See +data_stream_with_progress+ for the contract.
|
|
167
|
+
#
|
|
168
|
+
# @param address [String] hex address
|
|
169
|
+
# @yieldparam frame [DownloadFrame]
|
|
170
|
+
# @return [nil, Enumerator]
|
|
171
|
+
def data_stream_public_with_progress(address, &block)
|
|
172
|
+
return enum_for(:data_stream_public_with_progress, address) unless block_given?
|
|
173
|
+
|
|
174
|
+
req = Antd::V1::StreamPublicDataRequest.new(address: address, include_progress: true)
|
|
175
|
+
grpc_call { stream_with_progress(@data_stub.stream_public(req, return_op: true), &block) }
|
|
176
|
+
nil
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# Pre-upload cost breakdown for the given bytes.
|
|
180
|
+
# @param data [String] raw bytes
|
|
181
|
+
# @param payment_mode [String] PaymentMode::AUTO | MERKLE | SINGLE
|
|
182
|
+
# @return [UploadCostEstimate]
|
|
183
|
+
def data_cost(data, payment_mode: PaymentMode::AUTO)
|
|
184
|
+
req = Antd::V1::DataCostRequest.new(data: data.b, payment_mode: payment_mode)
|
|
185
|
+
resp = grpc_call { @data_stub.cost(req) }
|
|
186
|
+
UploadCostEstimate.new(
|
|
187
|
+
cost: resp.atto_tokens,
|
|
188
|
+
file_size: resp.file_size,
|
|
189
|
+
chunk_count: resp.chunk_count,
|
|
190
|
+
estimated_gas_cost_wei: resp.estimated_gas_cost_wei,
|
|
191
|
+
payment_mode: resp.payment_mode
|
|
192
|
+
)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# --- Chunks ---
|
|
196
|
+
|
|
197
|
+
# Store a raw chunk on the network.
|
|
198
|
+
# @param data [String] raw bytes
|
|
199
|
+
# @return [PutResult]
|
|
200
|
+
def chunk_put(data)
|
|
201
|
+
req = Antd::V1::PutChunkRequest.new(data: data.b)
|
|
202
|
+
resp = grpc_call { @chunk_stub.put(req) }
|
|
203
|
+
PutResult.new(cost: resp.cost.atto_tokens, address: resp.address)
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Retrieve a chunk by address.
|
|
207
|
+
# @param address [String] hex address
|
|
208
|
+
# @return [String] raw bytes
|
|
209
|
+
def chunk_get(address)
|
|
210
|
+
req = Antd::V1::GetChunkRequest.new(address: address)
|
|
211
|
+
resp = grpc_call { @chunk_stub.get(req) }
|
|
212
|
+
resp.data
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# --- Files ---
|
|
216
|
+
|
|
217
|
+
# Upload a file privately. Returns the caller-held DataMap (hex).
|
|
218
|
+
# @param path [String] local file path
|
|
219
|
+
# @param payment_mode [String] PaymentMode::AUTO | MERKLE | SINGLE
|
|
220
|
+
# @return [FilePutResult]
|
|
221
|
+
def file_put(path, payment_mode: PaymentMode::AUTO)
|
|
222
|
+
req = Antd::V1::PutFileRequest.new(path: path, payment_mode: payment_mode)
|
|
223
|
+
resp = grpc_call { @file_stub.put(req) }
|
|
224
|
+
FilePutResult.new(
|
|
225
|
+
data_map: resp.data_map,
|
|
226
|
+
storage_cost_atto: resp.storage_cost_atto,
|
|
227
|
+
gas_cost_wei: resp.gas_cost_wei,
|
|
228
|
+
chunks_stored: resp.chunks_stored,
|
|
229
|
+
payment_mode_used: resp.payment_mode_used
|
|
230
|
+
)
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# Download a private file from a caller-held DataMap.
|
|
234
|
+
# @param data_map [String]
|
|
235
|
+
# @param dest_path [String]
|
|
236
|
+
# @return [void]
|
|
237
|
+
def file_get(data_map, dest_path)
|
|
238
|
+
req = Antd::V1::GetFileRequest.new(data_map: data_map, dest_path: dest_path)
|
|
239
|
+
grpc_call { @file_stub.get(req) }
|
|
240
|
+
nil
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# Upload a file publicly. Returns the on-network DataMap address.
|
|
244
|
+
# @param path [String] local file path
|
|
245
|
+
# @param payment_mode [String] PaymentMode::AUTO | MERKLE | SINGLE
|
|
246
|
+
# @return [FilePutPublicResult]
|
|
247
|
+
def file_put_public(path, payment_mode: PaymentMode::AUTO)
|
|
248
|
+
req = Antd::V1::PutFileRequest.new(path: path, payment_mode: payment_mode)
|
|
249
|
+
resp = grpc_call { @file_stub.put_public(req) }
|
|
250
|
+
FilePutPublicResult.new(
|
|
251
|
+
address: resp.address,
|
|
252
|
+
storage_cost_atto: resp.storage_cost_atto,
|
|
253
|
+
gas_cost_wei: resp.gas_cost_wei,
|
|
254
|
+
chunks_stored: resp.chunks_stored,
|
|
255
|
+
payment_mode_used: resp.payment_mode_used
|
|
256
|
+
)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# Download a public file from an on-network DataMap address.
|
|
260
|
+
# @param address [String]
|
|
261
|
+
# @param dest_path [String]
|
|
262
|
+
# @return [void]
|
|
263
|
+
def file_get_public(address, dest_path)
|
|
264
|
+
req = Antd::V1::GetFilePublicRequest.new(address: address, dest_path: dest_path)
|
|
265
|
+
grpc_call { @file_stub.get_public(req) }
|
|
266
|
+
nil
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# Pre-upload cost breakdown for the file at +path+.
|
|
270
|
+
# @param path [String]
|
|
271
|
+
# @param is_public [Boolean]
|
|
272
|
+
# @param payment_mode [String] PaymentMode::AUTO | MERKLE | SINGLE
|
|
273
|
+
# @return [UploadCostEstimate]
|
|
274
|
+
def file_cost(path, is_public, payment_mode: PaymentMode::AUTO)
|
|
275
|
+
req = Antd::V1::FileCostRequest.new(
|
|
276
|
+
path: path,
|
|
277
|
+
is_public: is_public,
|
|
278
|
+
payment_mode: payment_mode
|
|
279
|
+
)
|
|
280
|
+
resp = grpc_call { @file_stub.cost(req) }
|
|
281
|
+
UploadCostEstimate.new(
|
|
282
|
+
cost: resp.atto_tokens,
|
|
283
|
+
file_size: resp.file_size,
|
|
284
|
+
chunk_count: resp.chunk_count,
|
|
285
|
+
estimated_gas_cost_wei: resp.estimated_gas_cost_wei,
|
|
286
|
+
payment_mode: resp.payment_mode
|
|
287
|
+
)
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
# --- External Signer (chunks) ---
|
|
291
|
+
|
|
292
|
+
# Prepare a single chunk for external-signer publish.
|
|
293
|
+
#
|
|
294
|
+
# When the chunk is already on-network the result has
|
|
295
|
+
# +already_stored: true+ and the caller can skip +finalize_chunk_upload+
|
|
296
|
+
# entirely.
|
|
297
|
+
#
|
|
298
|
+
# @param data [String] raw chunk bytes
|
|
299
|
+
# @return [PrepareChunkResult]
|
|
300
|
+
def prepare_chunk_upload(data)
|
|
301
|
+
req = Antd::V1::PrepareChunkRequest.new(data: data.b)
|
|
302
|
+
resp = grpc_call { @chunk_stub.prepare_chunk(req) }
|
|
303
|
+
PrepareChunkResult.new(
|
|
304
|
+
address: resp.address,
|
|
305
|
+
already_stored: resp.already_stored,
|
|
306
|
+
upload_id: resp.upload_id,
|
|
307
|
+
payment_type: resp.payment_type,
|
|
308
|
+
payments: resp.payments.map { |p|
|
|
309
|
+
PaymentInfo.new(
|
|
310
|
+
quote_hash: p.quote_hash,
|
|
311
|
+
rewards_address: p.rewards_address,
|
|
312
|
+
amount: p.amount
|
|
313
|
+
)
|
|
314
|
+
},
|
|
315
|
+
total_amount: resp.total_amount,
|
|
316
|
+
payment_vault_address: resp.payment_vault_address,
|
|
317
|
+
payment_token_address: resp.payment_token_address,
|
|
318
|
+
rpc_url: resp.rpc_url
|
|
319
|
+
)
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
# Submit a prepared chunk after external payment. Returns the chunk address.
|
|
323
|
+
#
|
|
324
|
+
# @param upload_id [String]
|
|
325
|
+
# @param tx_hashes [Hash<String, String>]
|
|
326
|
+
# @return [String] hex chunk address
|
|
327
|
+
def finalize_chunk_upload(upload_id, tx_hashes)
|
|
328
|
+
req = Antd::V1::FinalizeChunkRequest.new(
|
|
329
|
+
upload_id: upload_id,
|
|
330
|
+
tx_hashes: tx_hashes
|
|
331
|
+
)
|
|
332
|
+
resp = grpc_call { @chunk_stub.finalize_chunk(req) }
|
|
333
|
+
resp.address
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
# --- External Signer (uploads) ---
|
|
337
|
+
|
|
338
|
+
# Prepare a file upload for external signing.
|
|
339
|
+
#
|
|
340
|
+
# @param path [String] local file path on the daemon host
|
|
341
|
+
# @param visibility [String, nil] +"private"+ (default when nil) or
|
|
342
|
+
# +"public"+ to bundle the DataMap chunk into the same external-signer
|
|
343
|
+
# payment batch
|
|
344
|
+
# @return [PrepareUploadResult]
|
|
345
|
+
def prepare_upload(path, visibility: nil)
|
|
346
|
+
req = Antd::V1::PrepareFileUploadRequest.new(
|
|
347
|
+
path: path,
|
|
348
|
+
visibility: visibility.to_s
|
|
349
|
+
)
|
|
350
|
+
resp = grpc_call { @upload_stub.prepare_file_upload(req) }
|
|
351
|
+
build_prepare_upload_result(resp)
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
# Convenience wrapper for +prepare_upload(path, visibility: "public")+.
|
|
355
|
+
#
|
|
356
|
+
# @param path [String]
|
|
357
|
+
# @return [PrepareUploadResult]
|
|
358
|
+
def prepare_upload_public(path)
|
|
359
|
+
prepare_upload(path, visibility: "public")
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
# Prepare an in-memory data upload for external signing.
|
|
363
|
+
#
|
|
364
|
+
# @param data [String] raw bytes
|
|
365
|
+
# @param visibility [String, nil] same semantics as +prepare_upload+
|
|
366
|
+
# @return [PrepareUploadResult]
|
|
367
|
+
def prepare_data_upload(data, visibility: nil)
|
|
368
|
+
req = Antd::V1::PrepareDataUploadRequest.new(
|
|
369
|
+
data: data.b,
|
|
370
|
+
visibility: visibility.to_s
|
|
371
|
+
)
|
|
372
|
+
resp = grpc_call { @upload_stub.prepare_data_upload(req) }
|
|
373
|
+
build_prepare_upload_result(resp)
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
# Finalize a wave-batch upload after external payment.
|
|
377
|
+
#
|
|
378
|
+
# @param upload_id [String]
|
|
379
|
+
# @param tx_hashes [Hash<String, String>]
|
|
380
|
+
# @return [FinalizeUploadResult]
|
|
381
|
+
def finalize_upload(upload_id, tx_hashes)
|
|
382
|
+
req = Antd::V1::FinalizeUploadRequest.new(
|
|
383
|
+
upload_id: upload_id,
|
|
384
|
+
tx_hashes: tx_hashes
|
|
385
|
+
)
|
|
386
|
+
resp = grpc_call { @upload_stub.finalize_upload(req) }
|
|
387
|
+
FinalizeUploadResult.new(
|
|
388
|
+
address: resp.address,
|
|
389
|
+
chunks_stored: resp.chunks_stored.to_i,
|
|
390
|
+
data_map: resp.data_map,
|
|
391
|
+
data_map_address: resp.data_map_address
|
|
392
|
+
)
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
# Finalize a merkle-batch upload after the winning pool has been
|
|
396
|
+
# determined.
|
|
397
|
+
#
|
|
398
|
+
# @param upload_id [String]
|
|
399
|
+
# @param winner_pool_hash [String]
|
|
400
|
+
# @param store_data_map [Boolean]
|
|
401
|
+
# @return [FinalizeUploadResult]
|
|
402
|
+
def finalize_merkle_upload(upload_id, winner_pool_hash, store_data_map: false)
|
|
403
|
+
req = Antd::V1::FinalizeUploadRequest.new(
|
|
404
|
+
upload_id: upload_id,
|
|
405
|
+
winner_pool_hash: winner_pool_hash,
|
|
406
|
+
store_data_map: store_data_map
|
|
407
|
+
)
|
|
408
|
+
resp = grpc_call { @upload_stub.finalize_upload(req) }
|
|
409
|
+
FinalizeUploadResult.new(
|
|
410
|
+
address: resp.address,
|
|
411
|
+
chunks_stored: resp.chunks_stored.to_i,
|
|
412
|
+
data_map: resp.data_map,
|
|
413
|
+
data_map_address: resp.data_map_address
|
|
414
|
+
)
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
# --- Wallet ---
|
|
418
|
+
|
|
419
|
+
# V2-286: parity with REST Antd::Client. A missing daemon wallet emits
|
|
420
|
+
# GRPC::FailedPrecondition which grpc_call surfaces as PaymentError
|
|
421
|
+
# (established FailedPrecondition->Payment convention across all SDKs).
|
|
422
|
+
|
|
423
|
+
# @return [WalletAddress]
|
|
424
|
+
def wallet_address
|
|
425
|
+
resp = grpc_call { @wallet_stub.get_address(Antd::V1::GetWalletAddressRequest.new) }
|
|
426
|
+
WalletAddress.new(address: resp.address)
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
# @return [WalletBalance]
|
|
430
|
+
def wallet_balance
|
|
431
|
+
resp = grpc_call { @wallet_stub.get_balance(Antd::V1::GetWalletBalanceRequest.new) }
|
|
432
|
+
WalletBalance.new(balance: resp.balance, gas_balance: resp.gas_balance)
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
# @return [Boolean]
|
|
436
|
+
def wallet_approve
|
|
437
|
+
resp = grpc_call { @wallet_stub.approve(Antd::V1::WalletApproveRequest.new) }
|
|
438
|
+
resp.approved
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
private
|
|
442
|
+
|
|
443
|
+
# Drives a +return_op: true+ server-streaming call, yielding +DownloadFrame+s.
|
|
444
|
+
# The byte denominator is surfaced first as a leading +DownloadFrame+ (its
|
|
445
|
+
# +meta+ set), read from the response's +x-content-length+ initial metadata;
|
|
446
|
+
# then each wire +DataChunk+ is mapped to a data/progress frame.
|
|
447
|
+
#
|
|
448
|
+
# +op+ is a +GRPC::ActiveCall::Operation+ (from calling the stub method with
|
|
449
|
+
# +return_op: true+). +op.execute+ returns the response enumerator and starts
|
|
450
|
+
# the call; +op.metadata+ then holds the server's initial metadata. An
|
|
451
|
+
# absent or unparseable +x-content-length+ (older daemons) yields no Meta
|
|
452
|
+
# frame.
|
|
453
|
+
def stream_with_progress(op)
|
|
454
|
+
responses = op.execute
|
|
455
|
+
meta = meta_frame_from_op(op)
|
|
456
|
+
yield meta unless meta.nil?
|
|
457
|
+
responses.each { |chunk| yield frame_from_chunk(chunk) }
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
# Builds a leading byte-total +DownloadFrame+ from a server-stream
|
|
461
|
+
# operation's +x-content-length+ initial metadata, or +nil+ when the header
|
|
462
|
+
# is absent or unparseable.
|
|
463
|
+
def meta_frame_from_op(op)
|
|
464
|
+
md = op.metadata
|
|
465
|
+
return nil if md.nil?
|
|
466
|
+
|
|
467
|
+
value = md["x-content-length"]
|
|
468
|
+
return nil if value.nil?
|
|
469
|
+
|
|
470
|
+
value = value.first if value.is_a?(Array)
|
|
471
|
+
total = Integer(value, 10) rescue nil
|
|
472
|
+
return nil if total.nil?
|
|
473
|
+
|
|
474
|
+
DownloadFrame.new(meta: total)
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
# Maps a wire +DataChunk+ (oneof kind {data | progress}) onto a public
|
|
478
|
+
# +DownloadFrame+. A chunk with no arm set (shouldn't occur) is treated as
|
|
479
|
+
# an empty data frame, matching the antd-rust reference consumer.
|
|
480
|
+
def frame_from_chunk(chunk)
|
|
481
|
+
if chunk.kind == :progress
|
|
482
|
+
p = chunk.progress
|
|
483
|
+
DownloadFrame.new(progress: DownloadProgress.new(phase: p.phase, fetched: p.fetched, total: p.total))
|
|
484
|
+
else
|
|
485
|
+
DownloadFrame.new(data: chunk.data)
|
|
486
|
+
end
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
# Maps a PrepareUploadResponse proto into a +PrepareUploadResult+ struct,
|
|
490
|
+
# populating the merkle-only fields (+depth+, +pool_commitments+,
|
|
491
|
+
# +merkle_payment_timestamp+) only when +payment_type+ is +"merkle"+.
|
|
492
|
+
def build_prepare_upload_result(resp)
|
|
493
|
+
is_merkle = resp.payment_type == "merkle"
|
|
494
|
+
pool_commitments = if is_merkle
|
|
495
|
+
resp.pool_commitments.map { |pc|
|
|
496
|
+
PoolCommitmentEntry.new(
|
|
497
|
+
pool_hash: pc.pool_hash,
|
|
498
|
+
candidates: pc.candidates.map { |c|
|
|
499
|
+
CandidateNodeEntry.new(
|
|
500
|
+
rewards_address: c.rewards_address,
|
|
501
|
+
amount: c.amount
|
|
502
|
+
)
|
|
503
|
+
}
|
|
504
|
+
)
|
|
505
|
+
}
|
|
506
|
+
end
|
|
507
|
+
PrepareUploadResult.new(
|
|
508
|
+
upload_id: resp.upload_id,
|
|
509
|
+
payments: resp.payments.map { |p|
|
|
510
|
+
PaymentInfo.new(
|
|
511
|
+
quote_hash: p.quote_hash,
|
|
512
|
+
rewards_address: p.rewards_address,
|
|
513
|
+
amount: p.amount
|
|
514
|
+
)
|
|
515
|
+
},
|
|
516
|
+
total_amount: resp.total_amount,
|
|
517
|
+
payment_vault_address: resp.payment_vault_address,
|
|
518
|
+
payment_token_address: resp.payment_token_address,
|
|
519
|
+
rpc_url: resp.rpc_url,
|
|
520
|
+
payment_type: resp.payment_type,
|
|
521
|
+
depth: is_merkle ? resp.depth : nil,
|
|
522
|
+
pool_commitments: pool_commitments,
|
|
523
|
+
merkle_payment_timestamp: is_merkle ? resp.merkle_payment_timestamp.to_i : nil
|
|
524
|
+
)
|
|
525
|
+
end
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
# Executes a gRPC call and translates errors to Antd error types.
|
|
529
|
+
def grpc_call
|
|
530
|
+
yield
|
|
531
|
+
rescue GRPC::InvalidArgument => e
|
|
532
|
+
raise BadRequestError, e.message
|
|
533
|
+
rescue GRPC::NotFound => e
|
|
534
|
+
raise NotFoundError, e.message
|
|
535
|
+
rescue GRPC::AlreadyExists => e
|
|
536
|
+
raise AlreadyExistsError, e.message
|
|
537
|
+
rescue GRPC::ResourceExhausted => e
|
|
538
|
+
raise TooLargeError, e.message
|
|
539
|
+
rescue GRPC::Internal => e
|
|
540
|
+
raise InternalError, e.message
|
|
541
|
+
rescue GRPC::Unavailable => e
|
|
542
|
+
raise NetworkError, e.message
|
|
543
|
+
rescue GRPC::FailedPrecondition => e
|
|
544
|
+
raise PaymentError, e.message
|
|
545
|
+
rescue GRPC::BadStatus => e
|
|
546
|
+
raise AntdError.new(e.message, status_code: e.code)
|
|
547
|
+
end
|
|
548
|
+
end
|
|
549
|
+
end
|