digitalbits-base 0.27.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|