Skip to content

Commit

Permalink
Use build-raw instead of build
Browse files Browse the repository at this point in the history
`cardano-cli transaction build` was supposed to abstract all the
low level building of ``cardano-cli transaction build-raw`,
however it does not support balancing NFTs. Therefore, we currently
need to revert back to using `cardano-cli transaction build-raw`
and manually calculate the fees and balance the change address.

See issue: IntersectMBO/cardano-node#3068
  • Loading branch information
philipqnguyen committed Apr 20, 2022
1 parent e6ba417 commit 0a3c99f
Showing 1 changed file with 82 additions and 15 deletions.
97 changes: 82 additions & 15 deletions lib/cnifty/nft.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ class Nft
:image,
:policy,
:era,
:chain
:chain,
:protocol

def initialize(destination_address:,
change_address:,
Expand All @@ -37,7 +38,10 @@ def mint
write_policy_file
write_policy_skey_file
write_payment_address_skey_file
write_protocol_file
execute_raw_transaction_command
fee = execute_calculate_min_fee_command
execute_raw_transaction_with_fees_command(fee)
execute_sign_raw_transaction_command
execute_submit_command
execute_read_transaction_id
Expand Down Expand Up @@ -88,6 +92,14 @@ def payment_address_skey_file
@payment_address_skey_file ||= Tempfile.new "payment_#{seed}.skey"
end

def protocol_file
@protocol_file ||= Tempfile.new "protocol_#{seed}.json"
end

def write_protocol_file
File.write protocol_file, protocol.to_s
end

def write_payment_address_skey_file
File.write payment_address_skey_file, payment_address.skey
end
Expand Down Expand Up @@ -116,21 +128,54 @@ def metadata

def execute_raw_transaction_command
cmd = """
cardano-cli transaction build \
cardano-cli transaction build-raw \
--invalid-hereafter #{policy.before_slot} \
--#{era} \
--#{chain} \
#{tx_ins} \
--tx-out #{destination_tx_out} \
--change-address #{change_address} \
--fee 0 \
#{tx_ins_str} \
--tx-out #{tx_out} \
--tx-out #{change_tx_out(fee: 0)} \
#{mints} \
--minting-script-file #{policy_file.path} \
--metadata-json-file #{metadata_file.path} \
--out-file #{transaction_file_raw.path}
"""
stdout, stderr, status = Open3.capture3(cmd.strip)
raise CardanoNodeError, stderr if !stderr.empty? || status.exitstatus !=0
true
end

def execute_calculate_min_fee_command
cmd = """
cardano-cli transaction calculate-min-fee \
--tx-body-file #{transaction_file_raw.path} \
--tx-in-count #{tx_ins.count} \
--tx-out-count 2 \
--witness-count 2 \
--#{chain} \
--protocol-params-file #{protocol_file.path}
"""
stdout, stderr, status = Open3.capture3(cmd.strip)
raise CardanoNodeError, stderr if !stderr.empty? || status.exitstatus !=0
stdout.strip.split(' ').first
end

def execute_raw_transaction_with_fees_command(fee)
cmd = """
cardano-cli transaction build-raw \
--invalid-hereafter #{policy.before_slot} \
--witness-override 2 \
--#{era} \
--fee #{fee} \
#{tx_ins_str} \
--tx-out #{tx_out} \
--tx-out #{change_tx_out(fee: fee)} \
#{mints} \
--minting-script-file #{policy_file.path} \
--metadata-json-file #{metadata_file.path} \
--out-file #{transaction_file_raw.path}
"""
stdout, stderr, status = Open3.capture3(cmd.strip)
raise CardanoNodeError, stderr if !stderr.empty? || status.exitstatus != 0
raise CardanoNodeError, stderr if !stderr.empty? || status.exitstatus !=0
true
end

Expand Down Expand Up @@ -168,17 +213,25 @@ def execute_read_transaction_id
stdout
end

def tx_ins_str
tx_ins.map { |utxo| "--tx-in #{utxo.tx_hash}##{utxo.tx_ix}" }.join(" ")
end

def tx_ins
total = 0
utxos = payment_address.utxos.sort_by(&:ada).map do |utxo|
break if total >= (min_ada + 1_000_000)
total += utxo.ada.to_i
utxo
@tx_ins ||= begin
total = 0
utxos = []
payment_address.utxos.sort_by(&:ada).each do |utxo|
break if total >= min_ada + 1_000_000
total += utxo.ada.to_i
utxos << utxo
utxo
end
utxos
end
utxos.map { |utxo| "--tx-in #{utxo.tx_hash}##{utxo.tx_ix}" }.join(" ")
end

def destination_tx_out
def tx_out
"#{destination_address}+#{min_ada}+\"1 #{policy.id}.#{hex_name}\""
end

Expand All @@ -200,5 +253,19 @@ def mints
end.join(" + ")
"--mint=\"#{args}\""
end

def change_tx_out(fee: 0)
amount = tx_ins.sum {|tx_in| tx_in.ada.to_i}
remaining_lovelace = amount - min_ada - fee.to_i
tokens = tx_ins.map(&:tokens).flatten
if tokens.any?
token_args = tokens.map do |token|
"\"#{token.amount} #{token.policy_id}.#{token.hex_name}\""
end.join('+')
"#{change_address}+#{remaining_lovelace}+#{token_args}"
else
"#{change_address}+#{remaining_lovelace}"
end
end
end
end

0 comments on commit 0a3c99f

Please sign in to comment.