digitalbits-base 0.27.1
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 +202 -0
- data/README.md +84 -0
- data/generated/digitalbits-base-generated.rb +228 -0
- data/generated/digitalbits/account_entry.rb +55 -0
- data/generated/digitalbits/account_entry/ext.rb +28 -0
- data/generated/digitalbits/account_entry_extension_v1.rb +32 -0
- data/generated/digitalbits/account_entry_extension_v1/ext.rb +28 -0
- data/generated/digitalbits/account_entry_extension_v2.rb +34 -0
- data/generated/digitalbits/account_entry_extension_v2/ext.rb +24 -0
- data/generated/digitalbits/account_flags.rb +31 -0
- data/generated/digitalbits/account_merge_result.rb +26 -0
- data/generated/digitalbits/account_merge_result_code.rb +37 -0
- data/generated/digitalbits/allow_trust_op.rb +39 -0
- data/generated/digitalbits/allow_trust_op/asset.rb +33 -0
- data/generated/digitalbits/allow_trust_result.rb +25 -0
- data/generated/digitalbits/allow_trust_result_code.rb +33 -0
- data/generated/digitalbits/asset.rb +47 -0
- data/generated/digitalbits/asset/alpha_num12.rb +22 -0
- data/generated/digitalbits/asset/alpha_num4.rb +22 -0
- data/generated/digitalbits/asset_type.rb +24 -0
- data/generated/digitalbits/auth.rb +20 -0
- data/generated/digitalbits/auth_cert.rb +22 -0
- data/generated/digitalbits/authenticated_message.rb +32 -0
- data/generated/digitalbits/authenticated_message/v0.rb +24 -0
- data/generated/digitalbits/begin_sponsoring_future_reserves_op.rb +18 -0
- data/generated/digitalbits/begin_sponsoring_future_reserves_result.rb +25 -0
- data/generated/digitalbits/begin_sponsoring_future_reserves_result_code.rb +29 -0
- data/generated/digitalbits/bucket_entry.rb +34 -0
- data/generated/digitalbits/bucket_entry_type.rb +28 -0
- data/generated/digitalbits/bucket_metadata.rb +32 -0
- data/generated/digitalbits/bucket_metadata/ext.rb +24 -0
- data/generated/digitalbits/bump_sequence_op.rb +18 -0
- data/generated/digitalbits/bump_sequence_result.rb +25 -0
- data/generated/digitalbits/bump_sequence_result_code.rb +24 -0
- data/generated/digitalbits/change_trust_op.rb +22 -0
- data/generated/digitalbits/change_trust_result.rb +25 -0
- data/generated/digitalbits/change_trust_result_code.rb +34 -0
- data/generated/digitalbits/claim_claimable_balance_op.rb +18 -0
- data/generated/digitalbits/claim_claimable_balance_result.rb +25 -0
- data/generated/digitalbits/claim_claimable_balance_result_code.rb +31 -0
- data/generated/digitalbits/claim_offer_atom.rb +33 -0
- data/generated/digitalbits/claim_predicate.rb +43 -0
- data/generated/digitalbits/claim_predicate_type.rb +30 -0
- data/generated/digitalbits/claimable_balance_entry.rb +44 -0
- data/generated/digitalbits/claimable_balance_entry/ext.rb +24 -0
- data/generated/digitalbits/claimable_balance_id.rb +23 -0
- data/generated/digitalbits/claimable_balance_id_type.rb +20 -0
- data/generated/digitalbits/claimant.rb +31 -0
- data/generated/digitalbits/claimant/v0.rb +22 -0
- data/generated/digitalbits/claimant_type.rb +20 -0
- data/generated/digitalbits/create_account_op.rb +20 -0
- data/generated/digitalbits/create_account_result.rb +25 -0
- data/generated/digitalbits/create_account_result_code.rb +32 -0
- data/generated/digitalbits/create_claimable_balance_op.rb +22 -0
- data/generated/digitalbits/create_claimable_balance_result.rb +27 -0
- data/generated/digitalbits/create_claimable_balance_result_code.rb +30 -0
- data/generated/digitalbits/create_passive_sell_offer_op.rb +24 -0
- data/generated/digitalbits/crypto_key_type.rb +28 -0
- data/generated/digitalbits/curve25519_public.rb +18 -0
- data/generated/digitalbits/curve25519_secret.rb +18 -0
- data/generated/digitalbits/data_entry.rb +35 -0
- data/generated/digitalbits/data_entry/ext.rb +24 -0
- data/generated/digitalbits/decorated_signature.rb +20 -0
- data/generated/digitalbits/digital_bits_message.rb +84 -0
- data/generated/digitalbits/digital_bits_value.rb +43 -0
- data/generated/digitalbits/digital_bits_value/ext.rb +28 -0
- data/generated/digitalbits/digital_bits_value_type.rb +22 -0
- data/generated/digitalbits/dont_have.rb +20 -0
- data/generated/digitalbits/end_sponsoring_future_reserves_result.rb +25 -0
- data/generated/digitalbits/end_sponsoring_future_reserves_result_code.rb +25 -0
- data/generated/digitalbits/envelope_type.rb +32 -0
- data/generated/digitalbits/error.rb +20 -0
- data/generated/digitalbits/error_code.rb +28 -0
- data/generated/digitalbits/fee_bump_transaction.rb +39 -0
- data/generated/digitalbits/fee_bump_transaction/ext.rb +24 -0
- data/generated/digitalbits/fee_bump_transaction/inner_tx.rb +25 -0
- data/generated/digitalbits/fee_bump_transaction_envelope.rb +22 -0
- data/generated/digitalbits/hello.rb +34 -0
- data/generated/digitalbits/hmac_sha256_key.rb +18 -0
- data/generated/digitalbits/hmac_sha256_mac.rb +18 -0
- data/generated/digitalbits/inflation_payout.rb +20 -0
- data/generated/digitalbits/inflation_result.rb +26 -0
- data/generated/digitalbits/inflation_result_code.rb +24 -0
- data/generated/digitalbits/inner_transaction_result.rb +57 -0
- data/generated/digitalbits/inner_transaction_result/ext.rb +24 -0
- data/generated/digitalbits/inner_transaction_result/result.rb +54 -0
- data/generated/digitalbits/inner_transaction_result_pair.rb +20 -0
- data/generated/digitalbits/ip_addr_type.rb +22 -0
- data/generated/digitalbits/ledger_close_meta.rb +23 -0
- data/generated/digitalbits/ledger_close_meta_v0.rb +35 -0
- data/generated/digitalbits/ledger_close_value_signature.rb +20 -0
- data/generated/digitalbits/ledger_entry.rb +50 -0
- data/generated/digitalbits/ledger_entry/data.rb +41 -0
- data/generated/digitalbits/ledger_entry/ext.rb +28 -0
- data/generated/digitalbits/ledger_entry_change.rb +35 -0
- data/generated/digitalbits/ledger_entry_change_type.rb +26 -0
- data/generated/digitalbits/ledger_entry_extension_v1.rb +30 -0
- data/generated/digitalbits/ledger_entry_extension_v1/ext.rb +24 -0
- data/generated/digitalbits/ledger_entry_type.rb +28 -0
- data/generated/digitalbits/ledger_header.rb +69 -0
- data/generated/digitalbits/ledger_header/ext.rb +24 -0
- data/generated/digitalbits/ledger_header_history_entry.rb +33 -0
- data/generated/digitalbits/ledger_header_history_entry/ext.rb +24 -0
- data/generated/digitalbits/ledger_key.rb +69 -0
- data/generated/digitalbits/ledger_key/account.rb +20 -0
- data/generated/digitalbits/ledger_key/claimable_balance.rb +20 -0
- data/generated/digitalbits/ledger_key/data.rb +22 -0
- data/generated/digitalbits/ledger_key/offer.rb +22 -0
- data/generated/digitalbits/ledger_key/trust_line.rb +22 -0
- data/generated/digitalbits/ledger_scp_messages.rb +20 -0
- data/generated/digitalbits/ledger_upgrade.rb +35 -0
- data/generated/digitalbits/ledger_upgrade_type.rb +26 -0
- data/generated/digitalbits/liabilities.rb +20 -0
- data/generated/digitalbits/manage_buy_offer_op.rb +29 -0
- data/generated/digitalbits/manage_buy_offer_result.rb +26 -0
- data/generated/digitalbits/manage_buy_offer_result_code.rb +51 -0
- data/generated/digitalbits/manage_data_op.rb +20 -0
- data/generated/digitalbits/manage_data_result.rb +25 -0
- data/generated/digitalbits/manage_data_result_code.rb +32 -0
- data/generated/digitalbits/manage_offer_effect.rb +24 -0
- data/generated/digitalbits/manage_offer_success_result.rb +34 -0
- data/generated/digitalbits/manage_offer_success_result/offer.rb +30 -0
- data/generated/digitalbits/manage_sell_offer_op.rb +28 -0
- data/generated/digitalbits/manage_sell_offer_result.rb +26 -0
- data/generated/digitalbits/manage_sell_offer_result_code.rb +54 -0
- data/generated/digitalbits/memo.rb +38 -0
- data/generated/digitalbits/memo_type.rb +28 -0
- data/generated/digitalbits/message_type.rb +56 -0
- data/generated/digitalbits/muxed_account.rb +35 -0
- data/generated/digitalbits/muxed_account/med25519.rb +22 -0
- data/generated/digitalbits/offer_entry.rb +49 -0
- data/generated/digitalbits/offer_entry/ext.rb +24 -0
- data/generated/digitalbits/offer_entry_flags.rb +21 -0
- data/generated/digitalbits/operation.rb +69 -0
- data/generated/digitalbits/operation/body.rb +95 -0
- data/generated/digitalbits/operation_id.rb +32 -0
- data/generated/digitalbits/operation_id/id.rb +24 -0
- data/generated/digitalbits/operation_meta.rb +18 -0
- data/generated/digitalbits/operation_result.rb +71 -0
- data/generated/digitalbits/operation_result/tr.rb +97 -0
- data/generated/digitalbits/operation_result_code.rb +33 -0
- data/generated/digitalbits/operation_type.rb +56 -0
- data/generated/digitalbits/path_payment_strict_receive_op.rb +32 -0
- data/generated/digitalbits/path_payment_strict_receive_result.rb +39 -0
- data/generated/digitalbits/path_payment_strict_receive_result/success.rb +22 -0
- data/generated/digitalbits/path_payment_strict_receive_result_code.rb +56 -0
- data/generated/digitalbits/path_payment_strict_send_op.rb +32 -0
- data/generated/digitalbits/path_payment_strict_send_result.rb +38 -0
- data/generated/digitalbits/path_payment_strict_send_result/success.rb +22 -0
- data/generated/digitalbits/path_payment_strict_send_result_code.rb +55 -0
- data/generated/digitalbits/payment_op.rb +22 -0
- data/generated/digitalbits/payment_result.rb +25 -0
- data/generated/digitalbits/payment_result_code.rb +41 -0
- data/generated/digitalbits/peer_address.rb +33 -0
- data/generated/digitalbits/peer_address/ip.rb +29 -0
- data/generated/digitalbits/peer_stats.rb +48 -0
- data/generated/digitalbits/price.rb +20 -0
- data/generated/digitalbits/public_key.rb +23 -0
- data/generated/digitalbits/public_key_type.rb +20 -0
- data/generated/digitalbits/revoke_sponsorship_op.rb +36 -0
- data/generated/digitalbits/revoke_sponsorship_op/signer.rb +22 -0
- data/generated/digitalbits/revoke_sponsorship_result.rb +25 -0
- data/generated/digitalbits/revoke_sponsorship_result_code.rb +31 -0
- data/generated/digitalbits/revoke_sponsorship_type.rb +22 -0
- data/generated/digitalbits/scp_ballot.rb +20 -0
- data/generated/digitalbits/scp_envelope.rb +20 -0
- data/generated/digitalbits/scp_history_entry.rb +23 -0
- data/generated/digitalbits/scp_history_entry_v0.rb +20 -0
- data/generated/digitalbits/scp_nomination.rb +22 -0
- data/generated/digitalbits/scp_quorum_set.rb +22 -0
- data/generated/digitalbits/scp_statement.rb +58 -0
- data/generated/digitalbits/scp_statement/pledges.rb +63 -0
- data/generated/digitalbits/scp_statement/pledges/confirm.rb +30 -0
- data/generated/digitalbits/scp_statement/pledges/externalize.rb +26 -0
- data/generated/digitalbits/scp_statement/pledges/prepare.rb +32 -0
- data/generated/digitalbits/scp_statement_type.rb +26 -0
- data/generated/digitalbits/set_options_op.rb +41 -0
- data/generated/digitalbits/set_options_result.rb +25 -0
- data/generated/digitalbits/set_options_result_code.rb +40 -0
- data/generated/digitalbits/signed_survey_request_message.rb +20 -0
- data/generated/digitalbits/signed_survey_response_message.rb +20 -0
- data/generated/digitalbits/signer.rb +20 -0
- data/generated/digitalbits/signer_key.rb +33 -0
- data/generated/digitalbits/signer_key_type.rb +24 -0
- data/generated/digitalbits/simple_payment_result.rb +22 -0
- data/generated/digitalbits/survey_message_command_type.rb +20 -0
- data/generated/digitalbits/survey_request_message.rb +26 -0
- data/generated/digitalbits/survey_response_body.rb +23 -0
- data/generated/digitalbits/survey_response_message.rb +26 -0
- data/generated/digitalbits/threshold_indexes.rb +26 -0
- data/generated/digitalbits/time_bounds.rb +20 -0
- data/generated/digitalbits/topology_response_body.rb +25 -0
- data/generated/digitalbits/transaction.rb +50 -0
- data/generated/digitalbits/transaction/ext.rb +24 -0
- data/generated/digitalbits/transaction_envelope.rb +31 -0
- data/generated/digitalbits/transaction_history_entry.rb +33 -0
- data/generated/digitalbits/transaction_history_entry/ext.rb +24 -0
- data/generated/digitalbits/transaction_history_result_entry.rb +33 -0
- data/generated/digitalbits/transaction_history_result_entry/ext.rb +24 -0
- data/generated/digitalbits/transaction_meta.rb +31 -0
- data/generated/digitalbits/transaction_meta_v1.rb +20 -0
- data/generated/digitalbits/transaction_meta_v2.rb +24 -0
- data/generated/digitalbits/transaction_result.rb +46 -0
- data/generated/digitalbits/transaction_result/ext.rb +24 -0
- data/generated/digitalbits/transaction_result/result.rb +36 -0
- data/generated/digitalbits/transaction_result_code.rb +54 -0
- data/generated/digitalbits/transaction_result_meta.rb +22 -0
- data/generated/digitalbits/transaction_result_pair.rb +20 -0
- data/generated/digitalbits/transaction_result_set.rb +18 -0
- data/generated/digitalbits/transaction_set.rb +20 -0
- data/generated/digitalbits/transaction_signature_payload.rb +32 -0
- data/generated/digitalbits/transaction_signature_payload/tagged_transaction.rb +30 -0
- data/generated/digitalbits/transaction_v0.rb +39 -0
- data/generated/digitalbits/transaction_v0/ext.rb +24 -0
- data/generated/digitalbits/transaction_v0_envelope.rb +22 -0
- data/generated/digitalbits/transaction_v1_envelope.rb +22 -0
- data/generated/digitalbits/trust_line_entry.rb +53 -0
- data/generated/digitalbits/trust_line_entry/ext.rb +42 -0
- data/generated/digitalbits/trust_line_entry/ext/v1.rb +34 -0
- data/generated/digitalbits/trust_line_entry/ext/v1/ext.rb +28 -0
- data/generated/digitalbits/trust_line_flags.rb +25 -0
- data/generated/digitalbits/upgrade_entry_meta.rb +20 -0
- data/lib/digitalbits-base.rb +51 -0
- data/lib/digitalbits/account_flags.rb +26 -0
- data/lib/digitalbits/asset.rb +81 -0
- data/lib/digitalbits/base.rb +1 -0
- data/lib/digitalbits/claim_predicate.rb +197 -0
- data/lib/digitalbits/compat.rb +9 -0
- data/lib/digitalbits/concerns/transaction.rb +50 -0
- data/lib/digitalbits/convert.rb +32 -0
- data/lib/digitalbits/dsl.rb +93 -0
- data/lib/digitalbits/ext/xdr.rb +50 -0
- data/lib/digitalbits/factories.rb +59 -0
- data/lib/digitalbits/fee_bump_transaction.rb +21 -0
- data/lib/digitalbits/key_pair.rb +126 -0
- data/lib/digitalbits/ledger_key.rb +32 -0
- data/lib/digitalbits/muxed_account.rb +16 -0
- data/lib/digitalbits/networks.rb +43 -0
- data/lib/digitalbits/operation.rb +603 -0
- data/lib/digitalbits/path_payment_strict_receive_result.rb +16 -0
- data/lib/digitalbits/price.rb +39 -0
- data/lib/digitalbits/signer_key.rb +46 -0
- data/lib/digitalbits/thresholds.rb +37 -0
- data/lib/digitalbits/transaction.rb +37 -0
- data/lib/digitalbits/transaction_builder.rb +166 -0
- data/lib/digitalbits/transaction_envelope.rb +35 -0
- data/lib/digitalbits/transaction_v0.rb +43 -0
- data/lib/digitalbits/trust_line_flags.rb +53 -0
- data/lib/digitalbits/util/strkey.rb +70 -0
- data/lib/digitalbits/version.rb +3 -0
- metadata +459 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module DigitalBits
|
|
2
|
+
class PathPaymentStrictReceiveResult
|
|
3
|
+
# send_amount returns the actual amount paid for the corresponding
|
|
4
|
+
# PathPaymentOp to this result.
|
|
5
|
+
#
|
|
6
|
+
def send_amount
|
|
7
|
+
s = success!
|
|
8
|
+
return s.last.amount if s.offers.blank?
|
|
9
|
+
|
|
10
|
+
source_asset = s.offers.first.asset_bought
|
|
11
|
+
source_offers = s.offers.take_while { |o| o.asset_bought == source_asset }
|
|
12
|
+
|
|
13
|
+
source_offers.map(&:amount_bought).sum
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module DigitalBits
|
|
2
|
+
# reopen class
|
|
3
|
+
class Price
|
|
4
|
+
MAX_PRECISION = (2**31) - 1
|
|
5
|
+
|
|
6
|
+
def self.from_f(number)
|
|
7
|
+
best_r = number.to_r.rationalize(1.0e-7)
|
|
8
|
+
|
|
9
|
+
if best_r.numerator > MAX_PRECISION || best_r.denominator > MAX_PRECISION
|
|
10
|
+
raise ArgumentError("Couldn't find price approximation")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
new({
|
|
14
|
+
n: best_r.numerator,
|
|
15
|
+
d: best_r.denominator
|
|
16
|
+
})
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def invert
|
|
20
|
+
self.class.new(n: d, d: n)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def to_d
|
|
24
|
+
n.to_d / d
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def to_f
|
|
28
|
+
n.to_f / d
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def to_s
|
|
32
|
+
"#{n} / #{d}"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def inspect
|
|
36
|
+
"#<DigitalBits::Price #{self}>"
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
module DigitalBits
|
|
2
|
+
class SignerKey
|
|
3
|
+
PREIMAGE_LENGTH = 32
|
|
4
|
+
|
|
5
|
+
def self.ed25519(keypair)
|
|
6
|
+
raise ArgumentError, "Bad keypair" unless keypair.is_a?(KeyPair)
|
|
7
|
+
new(:signer_key_type_ed25519, keypair.raw_public_key)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.preauthorized_transaction(tx)
|
|
11
|
+
new(:signer_key_type_pre_auth_tx, tx.hash)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.hash_x(preimage)
|
|
15
|
+
raise ArgumentError, "Must be string" unless preimage.is_a?(String)
|
|
16
|
+
raise ArgumentError, "Must be 32 bytes" unless preimage.bytesize == PREIMAGE_LENGTH
|
|
17
|
+
|
|
18
|
+
hash_x = Digest::SHA256.digest(preimage)
|
|
19
|
+
new(:signer_key_type_hash_x, hash_x)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def to_s
|
|
23
|
+
case switch
|
|
24
|
+
when SignerKeyType.signer_key_type_ed25519
|
|
25
|
+
address = DigitalBits::Convert.pk_to_address(self)
|
|
26
|
+
"ed25519: #{address}"
|
|
27
|
+
when SignerKeyType.signer_key_type_pre_auth_tx
|
|
28
|
+
tx = DigitalBits::Convert.to_hex(pre_auth_tx!)
|
|
29
|
+
"pre_auth_tx: #{tx}"
|
|
30
|
+
when SignerKeyType.signer_key_type_hash_x
|
|
31
|
+
hx = DigitalBits::Convert.to_hex(hash_x!)
|
|
32
|
+
"hash_x: #{hx}"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def inspect
|
|
37
|
+
# label = switch.to_s
|
|
38
|
+
"#<DigitalBits::SignerKey #{self}>"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def signature_hint
|
|
42
|
+
# take last 4 bytes
|
|
43
|
+
value.to_xdr.slice(-4, 4)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module DigitalBits
|
|
2
|
+
class << Thresholds
|
|
3
|
+
COMPONENTS = [:master_weight, :low, :medium, :high]
|
|
4
|
+
VALID_RANGE = 0..255
|
|
5
|
+
|
|
6
|
+
def make(thresholds = {})
|
|
7
|
+
# error if any of the needed components are not provided
|
|
8
|
+
if COMPONENTS.any? { |c| thresholds[c].blank? }
|
|
9
|
+
raise ArgumentError, "invalid thresholds hash, must have #{COMPONENTS.inspect} keys, had: #{thresholds.keys.inspect}"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# error if any of the needed components are not numbers 0 <= N <= 255
|
|
13
|
+
COMPONENTS.each do |c|
|
|
14
|
+
good = true
|
|
15
|
+
|
|
16
|
+
good &&= thresholds[c].is_a?(Integer)
|
|
17
|
+
good &&= VALID_RANGE.include? thresholds[c]
|
|
18
|
+
|
|
19
|
+
unless good
|
|
20
|
+
raise ArgumentError, "invalid #{c.inspect}, must be number in (0..255), got #{thresholds[c].inspect}"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
thresholds.values_at(*COMPONENTS).pack("C*")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def parse(combined)
|
|
28
|
+
master_weight, low, medium, high = combined.unpack("C*")
|
|
29
|
+
{
|
|
30
|
+
master_weight: master_weight,
|
|
31
|
+
low: low,
|
|
32
|
+
medium: medium,
|
|
33
|
+
high: high
|
|
34
|
+
}
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module DigitalBits
|
|
2
|
+
class Transaction
|
|
3
|
+
include DigitalBits::Concerns::Transaction
|
|
4
|
+
|
|
5
|
+
def to_v0
|
|
6
|
+
ed25519 = if source_account.switch == DigitalBits::CryptoKeyType.key_type_ed25519
|
|
7
|
+
source_account.ed25519!
|
|
8
|
+
else
|
|
9
|
+
source_account.med25519!.ed25519
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
TransactionV0.new(
|
|
13
|
+
source_account_ed25519: ed25519,
|
|
14
|
+
seq_num: seq_num,
|
|
15
|
+
operations: operations,
|
|
16
|
+
fee: fee,
|
|
17
|
+
memo: memo,
|
|
18
|
+
time_bounds: time_bounds,
|
|
19
|
+
ext: ext
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def signature_base
|
|
24
|
+
tagged_tx = DigitalBits::TransactionSignaturePayload::TaggedTransaction.new(:envelope_type_tx, self)
|
|
25
|
+
DigitalBits::TransactionSignaturePayload.new(
|
|
26
|
+
network_id: DigitalBits.current_network_id,
|
|
27
|
+
tagged_transaction: tagged_tx
|
|
28
|
+
).to_xdr
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def to_envelope(*key_pairs)
|
|
32
|
+
signatures = key_pairs.map(&method(:sign_decorated))
|
|
33
|
+
|
|
34
|
+
TransactionEnvelope.v1(signatures: signatures, tx: self)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
module DigitalBits
|
|
2
|
+
class TransactionBuilder
|
|
3
|
+
attr_reader :source_account, :sequence_number, :base_fee, :time_bounds, :memo, :operations
|
|
4
|
+
|
|
5
|
+
class << self
|
|
6
|
+
# This enable user to call shortcut methods, like
|
|
7
|
+
# TransactionBuilder.payment(...),
|
|
8
|
+
# TransactionBuilder.manage_data(...) and etc.
|
|
9
|
+
# It reduces the boilerplate, when you just need to
|
|
10
|
+
# shoot a single operation in transaction
|
|
11
|
+
def method_missing(method_name, *args, **kwargs)
|
|
12
|
+
unless DigitalBits::Operation.respond_to?(method_name)
|
|
13
|
+
return super
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
op = DigitalBits::Operation.send(method_name, **kwargs)
|
|
17
|
+
|
|
18
|
+
new(**kwargs).add_operation(op).build
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def respond_to_missing?(method_name, include_private = false)
|
|
22
|
+
DigitalBits::Operation.respond_to?(method_name) || super
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def initialize(
|
|
27
|
+
source_account:,
|
|
28
|
+
sequence_number:,
|
|
29
|
+
base_fee: 100,
|
|
30
|
+
time_bounds: nil,
|
|
31
|
+
memo: nil,
|
|
32
|
+
**_ # ignore any additional parameters without errors
|
|
33
|
+
)
|
|
34
|
+
raise ArgumentError, "Bad :source_account" unless source_account.is_a?(DigitalBits::KeyPair)
|
|
35
|
+
raise ArgumentError, "Bad :sequence_number" unless sequence_number.is_a?(Integer) && sequence_number >= 0
|
|
36
|
+
raise ArgumentError, "Bad :time_bounds" unless time_bounds.is_a?(DigitalBits::TimeBounds) || time_bounds.nil?
|
|
37
|
+
raise ArgumentError, "Bad :base_fee" unless base_fee.is_a?(Integer) && base_fee >= 100
|
|
38
|
+
|
|
39
|
+
@source_account = source_account
|
|
40
|
+
@sequence_number = sequence_number
|
|
41
|
+
@base_fee = base_fee
|
|
42
|
+
@time_bounds = time_bounds
|
|
43
|
+
|
|
44
|
+
if time_bounds.nil?
|
|
45
|
+
set_timeout(0)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
@memo = make_memo(memo)
|
|
49
|
+
@operations = []
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def build
|
|
53
|
+
if @time_bounds.nil?
|
|
54
|
+
raise "TransactionBuilder.time_bounds must be set during initialization or by calling set_timeout"
|
|
55
|
+
elsif !@time_bounds.min_time.is_a?(Integer) || !@time_bounds.max_time.is_a?(Integer)
|
|
56
|
+
raise "TimeBounds.min_time and max_time must be Integers"
|
|
57
|
+
elsif @time_bounds.max_time != 0 && @time_bounds.min_time > @time_bounds.max_time
|
|
58
|
+
raise "Timebounds.max_time must be greater than min_time"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
attrs = {
|
|
62
|
+
source_account: @source_account.muxed_account,
|
|
63
|
+
fee: @base_fee * @operations.length,
|
|
64
|
+
seq_num: @sequence_number,
|
|
65
|
+
time_bounds: @time_bounds,
|
|
66
|
+
memo: @memo,
|
|
67
|
+
operations: @operations,
|
|
68
|
+
ext: DigitalBits::Transaction::Ext.new(0)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@sequence_number += 1
|
|
72
|
+
|
|
73
|
+
DigitalBits::Transaction.new(attrs)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def build_fee_bump(inner_txe:)
|
|
77
|
+
if inner_txe.switch == DigitalBits::EnvelopeType.envelope_type_tx_v0
|
|
78
|
+
inner_txe = DigitalBits::TransactionEnvelope.v1(tx: inner_txe.tx.to_v1, signatures: inner_txe.signatures)
|
|
79
|
+
elsif inner_txe.switch != DigitalBits::EnvelopeType.envelope_type_tx
|
|
80
|
+
raise ArgumentError, "Invalid inner transaction type #{inner_txe.switch}"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
inner_tx = inner_txe.tx
|
|
84
|
+
inner_ops = inner_tx.operations
|
|
85
|
+
inner_base_fee_rate = inner_tx.fee.fdiv(inner_ops.length)
|
|
86
|
+
|
|
87
|
+
# The fee rate for fee bump is at least the fee rate of the inner transaction
|
|
88
|
+
if @base_fee < inner_base_fee_rate
|
|
89
|
+
raise "Insufficient base_fee, it should be at least #{inner_base_fee_rate} stroops."
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
DigitalBits::FeeBumpTransaction.new(
|
|
93
|
+
fee_source: @source_account.muxed_account,
|
|
94
|
+
fee: @base_fee * (inner_ops.length + 1),
|
|
95
|
+
inner_tx: DigitalBits::FeeBumpTransaction::InnerTx.new(:envelope_type_tx, inner_txe.v1!),
|
|
96
|
+
ext: DigitalBits::FeeBumpTransaction::Ext.new(0)
|
|
97
|
+
)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def add_operation(operation)
|
|
101
|
+
raise ArgumentError, "Bad operation" unless operation.is_a? DigitalBits::Operation
|
|
102
|
+
@operations.push(operation)
|
|
103
|
+
self
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def clear_operations
|
|
107
|
+
@operations.clear
|
|
108
|
+
self
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def set_source_account(account_kp)
|
|
112
|
+
raise ArgumentError, "Bad source account" unless account_kp.is_a?(DigitalBits::KeyPair)
|
|
113
|
+
@source_account = account_kp
|
|
114
|
+
self
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def set_sequence_number(seq_num)
|
|
118
|
+
raise ArgumentError, "Bad sequence number" unless seq_num.is_a?(Integer) && seq_num >= 0
|
|
119
|
+
@sequence_number = seq_num
|
|
120
|
+
self
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def set_timeout(timeout)
|
|
124
|
+
if !timeout.is_a?(Integer) || timeout < 0
|
|
125
|
+
raise ArgumentError, "Timeout must be a non-negative integer"
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
if @time_bounds.nil?
|
|
129
|
+
@time_bounds = DigitalBits::TimeBounds.new(min_time: 0, max_time: nil)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
@time_bounds.max_time = timeout == 0 ? timeout : Time.now.to_i + timeout
|
|
133
|
+
|
|
134
|
+
self
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def set_memo(memo)
|
|
138
|
+
@memo = make_memo(memo)
|
|
139
|
+
self
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def set_base_fee(base_fee)
|
|
143
|
+
raise ArgumentError, "Bad base fee" unless base_fee.is_a?(Integer) && base_fee >= 100
|
|
144
|
+
@base_fee = base_fee
|
|
145
|
+
self
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def make_memo(memo)
|
|
149
|
+
case memo
|
|
150
|
+
when DigitalBits::Memo
|
|
151
|
+
memo
|
|
152
|
+
when nil
|
|
153
|
+
Memo.new(:memo_none)
|
|
154
|
+
when Integer
|
|
155
|
+
Memo.new(:memo_id, memo)
|
|
156
|
+
when String
|
|
157
|
+
Memo.new(:memo_text, memo)
|
|
158
|
+
when Array
|
|
159
|
+
t, val = *memo
|
|
160
|
+
Memo.new(:"memo_#{t}", val)
|
|
161
|
+
else
|
|
162
|
+
raise ArgumentError, "Bad :memo"
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module DigitalBits
|
|
2
|
+
class TransactionEnvelope
|
|
3
|
+
delegate :tx, :signatures, to: :value
|
|
4
|
+
delegate :hash, to: :tx
|
|
5
|
+
|
|
6
|
+
# Checks to ensure that every signature for the envelope is
|
|
7
|
+
# a valid signature of one of the provided `key_pairs`
|
|
8
|
+
#
|
|
9
|
+
# NOTE: this does not do any authorization checks, which requires access to
|
|
10
|
+
# the current ledger state.
|
|
11
|
+
#
|
|
12
|
+
# @param key_pairs [Array<DigitalBits::KeyPair>] The key pairs to check the envelopes signatures against
|
|
13
|
+
#
|
|
14
|
+
# @return [Boolean] true if all signatures are from the provided key_pairs and validly sign the tx's hash
|
|
15
|
+
def signed_correctly?(*key_pairs)
|
|
16
|
+
return false if signatures.empty?
|
|
17
|
+
|
|
18
|
+
tx_hash = tx.hash
|
|
19
|
+
keys_by_hint = key_pairs.index_by(&:signature_hint)
|
|
20
|
+
|
|
21
|
+
signatures.all? do |sig|
|
|
22
|
+
key_pair = keys_by_hint[sig.hint]
|
|
23
|
+
break false if key_pair.nil?
|
|
24
|
+
|
|
25
|
+
key_pair.verify(sig.signature, tx_hash)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def merge(other)
|
|
30
|
+
merged_tx = tx.merge(other.tx)
|
|
31
|
+
merged_tx.signatures = [signatures, other.signatures]
|
|
32
|
+
merged_tx
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module DigitalBits
|
|
2
|
+
class TransactionV0
|
|
3
|
+
include DigitalBits::Concerns::Transaction
|
|
4
|
+
|
|
5
|
+
def to_v1
|
|
6
|
+
Transaction.new(**attributes.except(:source_account_ed25519), source_account: source_account)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def to_envelope(*key_pairs)
|
|
10
|
+
signatures = (key_pairs || []).map(&method(:sign_decorated))
|
|
11
|
+
|
|
12
|
+
TransactionEnvelope.v0(signatures: signatures, tx: self)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def signature_base_prefix
|
|
16
|
+
val = DigitalBits::EnvelopeType.envelope_type_tx_v0
|
|
17
|
+
|
|
18
|
+
DigitalBits.current_network_id + DigitalBits::EnvelopeType.to_xdr(val)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Backwards Compatibility: Use ENVELOPE_TYPE_TX to sign ENVELOPE_TYPE_TX_V0
|
|
22
|
+
# we need a Transaction to generate the signature base
|
|
23
|
+
def signature_base
|
|
24
|
+
tx = DigitalBits::Transaction.from_xdr(
|
|
25
|
+
# TransactionV0 is a transaction with the AccountID discriminant
|
|
26
|
+
# stripped off, we need to put it back to build a valid transaction
|
|
27
|
+
# which we can use to build a TransactionSignaturePayloadTaggedTransaction
|
|
28
|
+
DigitalBits::PublicKeyType.to_xdr(DigitalBits::PublicKeyType.public_key_type_ed25519) + to_xdr
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
tagged_tx = DigitalBits::TransactionSignaturePayload::TaggedTransaction.new(:envelope_type_tx, tx)
|
|
32
|
+
|
|
33
|
+
DigitalBits::TransactionSignaturePayload.new(
|
|
34
|
+
network_id: DigitalBits.current_network_id,
|
|
35
|
+
tagged_transaction: tagged_tx
|
|
36
|
+
).to_xdr
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def source_account
|
|
40
|
+
DigitalBits::MuxedAccount.ed25519(source_account_ed25519)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module DigitalBits
|
|
2
|
+
class TrustLineFlags
|
|
3
|
+
# Converts an array of DigitalBits::TrustLineFlags members into
|
|
4
|
+
# an integers suitable for use in in a SetTrustLineFlagsOp.
|
|
5
|
+
#
|
|
6
|
+
# @param flags [Array<DigitalBits::TrustLineFlags>] the flags to combine
|
|
7
|
+
#
|
|
8
|
+
# @return [Fixnum] the combined result
|
|
9
|
+
def self.make_mask(flags)
|
|
10
|
+
normalize(flags).map(&:value).inject(&:|) || 0
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Converts an integer used in SetTrustLineFlagsOp on the set/clear flag options
|
|
14
|
+
# into an array of DigitalBits::TrustLineFlags members
|
|
15
|
+
#
|
|
16
|
+
# @param combined [Fixnum]
|
|
17
|
+
# @return [Array<DigitalBits::AccountFlags>]
|
|
18
|
+
def self.parse_mask(combined)
|
|
19
|
+
members.values.select { |m| (m.value & combined) != 0 }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Converts each element of the input array to DigitalBits::TrustLineFlags instance.
|
|
23
|
+
#
|
|
24
|
+
# @param [Array<DigitalBits::TrustLineFlags,Symbol,#to_s>] input
|
|
25
|
+
# @return [Array<DigitalBits::TrustLineFlags>]
|
|
26
|
+
# @raise [TypeError] if any element of the input cannot be converted
|
|
27
|
+
def self.normalize(input)
|
|
28
|
+
input.map do |val|
|
|
29
|
+
case val
|
|
30
|
+
when DigitalBits::TrustLineFlags
|
|
31
|
+
val
|
|
32
|
+
when ->(_) { members.key?(val.to_s) }
|
|
33
|
+
from_name(val.to_s)
|
|
34
|
+
when ->(_) { members.key?("#{val}_flag") }
|
|
35
|
+
from_name("#{val}_flag")
|
|
36
|
+
else
|
|
37
|
+
raise TypeError, "unknown trustline flag: #{val}"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.set_clear_masks(flags)
|
|
43
|
+
set_flags = []
|
|
44
|
+
clear_flags = []
|
|
45
|
+
|
|
46
|
+
Hash(flags).each do |flag, value|
|
|
47
|
+
value.present? ? set_flags.push(flag) : clear_flags.push(flag)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
{set_flags: make_mask(set_flags), clear_flags: make_mask(clear_flags)}
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|