diff --git a/test/e2e/Gemfile b/test/e2e/Gemfile index fc6bcae454c..e53ff51dccd 100644 --- a/test/e2e/Gemfile +++ b/test/e2e/Gemfile @@ -2,7 +2,7 @@ source 'https://rubygems.org' -gem 'cardano_wallet', '~> 0.3.27' +gem 'cardano_wallet', '~> 0.4.0' # gem 'cardano_wallet', path: "~/wb/cardano_wallet" gem 'blake2b', '0.10.0' gem 'cbor', '0.5.9.6' diff --git a/test/e2e/Gemfile.lock b/test/e2e/Gemfile.lock index e7c1648baac..99d20ea4074 100644 --- a/test/e2e/Gemfile.lock +++ b/test/e2e/Gemfile.lock @@ -3,7 +3,7 @@ GEM specs: bip_mnemonic (0.0.4) blake2b (0.10.0) - cardano_wallet (0.3.27) + cardano_wallet (0.4.0) bip_mnemonic (~> 0.0.4) httparty (~> 0.18.0) cbor (0.5.9.6) @@ -36,7 +36,7 @@ PLATFORMS DEPENDENCIES blake2b (= 0.10.0) - cardano_wallet (~> 0.3.27) + cardano_wallet (~> 0.4.0) cbor (= 0.5.9.6) mustache (= 1.1.1) rake (= 12.3.3) diff --git a/test/e2e/Rakefile b/test/e2e/Rakefile index c51668e71b7..16f5f5357c6 100644 --- a/test/e2e/Rakefile +++ b/test/e2e/Rakefile @@ -50,30 +50,30 @@ task :fixture_wallets_template do log ">> Creating #{FIXTURES_FILE}" utils = CardanoWallet.new.utils fixture_wallets = { linux: { - fixture: { shelley: utils.mnemonic_sentence(24), - icarus: utils.mnemonic_sentence(15), - random: utils.mnemonic_sentence(12), - shelley_light: utils.mnemonic_sentence(24) }, - target: { shelley: utils.mnemonic_sentence(24), - shared: utils.mnemonic_sentence(24) } + fixture: { shelley: { mnemonics: utils.mnemonic_sentence(24) }, + icarus: { mnemonics: utils.mnemonic_sentence(24) }, + random: { mnemonics: utils.mnemonic_sentence(24) }, + shared: { mnemonics: utils.mnemonic_sentence(24) }, + shared2: { mnemonics: utils.mnemonic_sentence(24) } }, + target: { shelley: { mnemonics: utils.mnemonic_sentence(24) } } }, macos: { - fixture: { shelley: utils.mnemonic_sentence(24), - icarus: utils.mnemonic_sentence(15), - random: utils.mnemonic_sentence(12), - shelley_light: utils.mnemonic_sentence(24) }, - target: { shelley: utils.mnemonic_sentence(24), - shared: utils.mnemonic_sentence(24) } + fixture: { shelley: { mnemonics: utils.mnemonic_sentence(24) }, + icarus: { mnemonics: utils.mnemonic_sentence(24) }, + random: { mnemonics: utils.mnemonic_sentence(24) }, + shared: { mnemonics: utils.mnemonic_sentence(24) }, + shared2: { mnemonics: utils.mnemonic_sentence(24) } }, + target: { shelley: { mnemonics: utils.mnemonic_sentence(24) } } }, windows: { - fixture: { shelley: utils.mnemonic_sentence(24), - icarus: utils.mnemonic_sentence(15), - random: utils.mnemonic_sentence(12), - shelley_light: utils.mnemonic_sentence(24) }, - target: { shelley: utils.mnemonic_sentence(24), - shared: utils.mnemonic_sentence(24) } + fixture: { shelley: { mnemonics: utils.mnemonic_sentence(24) }, + icarus: { mnemonics: utils.mnemonic_sentence(24) }, + random: { mnemonics: utils.mnemonic_sentence(24) }, + shared: { mnemonics: utils.mnemonic_sentence(24) }, + shared2: { mnemonics: utils.mnemonic_sentence(24) } }, + target: { shelley: { mnemonics: utils.mnemonic_sentence(24) } } }, - currency_contract_wallet: utils.mnemonic_sentence(24) } + currency_contract_wallet: { mnemonics: utils.mnemonic_sentence(24) } } if File.exist?(FIXTURES_FILE) err = " File #{FIXTURES_FILE} already exists! diff --git a/test/e2e/fixtures/fixture_wallets.json.gpg b/test/e2e/fixtures/fixture_wallets.json.gpg index b4b14a1edcf..4ffeb068e98 100644 Binary files a/test/e2e/fixtures/fixture_wallets.json.gpg and b/test/e2e/fixtures/fixture_wallets.json.gpg differ diff --git a/test/e2e/gemset.nix b/test/e2e/gemset.nix index dfbc03d4a17..fea62f8bfcb 100644 --- a/test/e2e/gemset.nix +++ b/test/e2e/gemset.nix @@ -25,10 +25,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1ay11nh7wcri87zzvn4i3n9lx0wnv2d5wfknk5nx8zyvlk8305r7"; + sha256 = "1az3d89mlkvy53mfdaxd73y91m1v9z96zsilvkdgagfcf21ywisj"; type = "gem"; }; - version = "0.3.27"; + version = "0.4.0"; }; cbor = { groups = ["default"]; @@ -45,10 +45,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0m925b8xc6kbpnif9dldna24q1szg4mk0fvszrki837pfn46afmz"; + sha256 = "0rwvjahnp7cpmracd8x732rjgnilqv2sx7d1gfrysslc3h039fa9"; type = "gem"; }; - version = "1.4.4"; + version = "1.5.0"; }; httparty = { dependencies = ["mime-types" "multi_xml"]; @@ -118,10 +118,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1dwai7jnwmdmd7ajbi2q0k0lx1dh88knv5wl7c34wjmf94yv8w5q"; + sha256 = "19dyb6rcvgi9j2mksd29wfdhfdyzqk7yjhy1ai77559hbhpg61w9"; type = "gem"; }; - version = "3.10.0"; + version = "3.11.0"; }; rspec-core = { dependencies = ["rspec-support"]; @@ -129,10 +129,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "0wwnfhxxvrlxlk1a3yxlb82k2f9lm0yn0598x7lk8fksaz4vv6mc"; + sha256 = "118hkfw9b11hvvalr7qlylwal5h8dihagm9xg7k4gskg7587hca6"; type = "gem"; }; - version = "3.10.1"; + version = "3.11.0"; }; rspec-expectations = { dependencies = ["diff-lcs" "rspec-support"]; @@ -140,10 +140,10 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1sz9bj4ri28adsklnh257pnbq4r5ayziw02qf67wry0kvzazbb17"; + sha256 = "0l1bzk6a68i1b2qix83vs40r0pbjawv67hixiq2qxsja19bbq3bc"; type = "gem"; }; - version = "3.10.1"; + version = "3.11.1"; }; rspec-mocks = { dependencies = ["diff-lcs" "rspec-support"]; @@ -151,19 +151,19 @@ platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "1d13g6kipqqc9lmwz5b244pdwc97z15vcbnbq6n9rlf32bipdz4k"; + sha256 = "07vagjxdm5a6s103y8zkcnja6avpl8r196hrpiffmg7sk83dqdsm"; type = "gem"; }; - version = "3.10.2"; + version = "3.11.1"; }; rspec-support = { groups = ["default"]; platforms = []; source = { remotes = ["https://rubygems.org"]; - sha256 = "15j52parvb8cgvl6s0pbxi2ywxrv6x0764g222kz5flz0s4mycbl"; + sha256 = "1c01iicvrjk6vv744jgh0y4kk9d0kg2rd2ihdyzvg5p06xm2fpzq"; type = "gem"; }; - version = "3.10.2"; + version = "3.11.1"; }; } diff --git a/test/e2e/helpers/utils.rb b/test/e2e/helpers/utils.rb index 33a9150c928..475d449e6a1 100644 --- a/test/e2e/helpers/utils.rb +++ b/test/e2e/helpers/utils.rb @@ -76,27 +76,30 @@ def absolute_path(path) end end - # Get wallet mnemonics from fixures file + # Get wallet mnemonics/payment template/delegation template from fixures file # @param kind [Symbol] :fixture or :target (fixture wallet with funds or target wallet) - # @param type [Symbol] wallet type = :shelley, :shared, :icarus, :random - def get_fixture_wallet_mnemonics(kind, type) + # @param wallet_type [Symbol] wallet type = :shelley, :shared, :icarus, :random + # @param info_type [Symbol] wallet type = :mnemonics, :payment_template, :delegation_template + def get_fixture_wallet(kind, wallet_type, info_type = :mnemonics) fixture = ENV.fetch('TESTS_E2E_FIXTURES_FILE', nil) raise "File #{fixture} does not exist! (Hint: Template fixture file can be created with 'rake fixture_wallets_template'). Make sure to feed it with mnemonics of wallets with funds and assets." unless File.exist? fixture - wallets = JSON.parse File.read(fixture) - k = kind.to_s - t = type.to_s + wallets = from_json(fixture) if linux? - wallets['linux'][k][t] + wallets[:linux][kind][wallet_type][info_type] elsif mac? - wallets['macos'][k][t] + wallets[:macos][kind][wallet_type][info_type] elsif win? - wallets['windows'][k][t] + wallets[:windows][kind][wallet_type][info_type] else raise 'Unsupported platform!' end end + def from_json(file) + JSON.parse(File.read(file), { symbolize_names: true }) + end + def wget(url, file = nil) file ||= File.basename(url) resp = HTTParty.get(url) diff --git a/test/e2e/spec/e2e_shared_spec.rb b/test/e2e/spec/e2e_shared_spec.rb new file mode 100644 index 00000000000..d9c8bc62063 --- /dev/null +++ b/test/e2e/spec/e2e_shared_spec.rb @@ -0,0 +1,1371 @@ +# frozen_string_literal: true + +RSpec.describe 'Cardano Wallet E2E tests - Shared wallets', :all, :e2e, :shared do + before(:all) do + # shelley wallets + @wid = create_fixture_wallet(:shelley) + @target_id = create_target_wallet(:shelley) + + # shared wallets + @wid_sha = create_fixture_wallet(:shared, :payment_cosigner0_all0, :delegation_cosigner0_all0) + @wid_sha_cos0_all = create_fixture_wallet(:shared, :payment_cosigner0_all, :delegation_cosigner0_all) + @wid_sha_cos1_all = create_fixture_wallet(:shared2, :payment_cosigner1_all, :delegation_cosigner1_all) + @wid_sha_cos0_any = create_fixture_wallet(:shared, :payment_cosigner0_any, :delegation_cosigner0_any) + cos0 = shared_acc_pubkey(@wid_sha_cos0_all) + cos1 = shared_acc_pubkey(@wid_sha_cos1_all) + patch_if_incomplete(@wid_sha_cos0_all, { 'cosigner#1' => cos1 }, { 'cosigner#1' => cos1 }) + patch_if_incomplete(@wid_sha_cos1_all, { 'cosigner#0' => cos0 }, { 'cosigner#0' => cos0 }) + patch_if_incomplete(@wid_sha_cos0_any, { 'cosigner#1' => cos1 }, { 'cosigner#1' => cos1 }) + + @nightly_shared_wallets = [@wid_sha, @wid_sha_cos0_all, @wid_sha_cos1_all, @wid_sha_cos0_any] + @nightly_shelley_wallets = [@wid, @target_id] + wait_for_all_shelley_wallets(@nightly_shelley_wallets) + wait_for_all_shared_wallets(@nightly_shared_wallets) + end + + after(:each) do + teardown + end + + after(:all) do + SHELLEY.stake_pools.quit(@target_id, PASS) + end + + describe 'E2E Shared' do + describe 'E2E Construct -> Sign -> Submit - multi signers' do + it 'Cannot submit if partially signed - one cosigner, all' do + amt = MIN_UTXO_VALUE_PURE_ADA * 2 + src_wid = @wid_sha_cos0_all + target_wid = @target_id + address = SHELLEY.addresses.list(target_wid)[1]['id'] + + tx_constructed = SHARED.transactions.construct(src_wid, payment_payload(amt, address)) + expect(tx_constructed).to be_correct_and_respond 202 + expected_fee = tx_constructed['fee']['quantity'] + + # Can be decoded + tx_decoded = SHARED.transactions.decode(src_wid, tx_constructed['transaction']) + expect(tx_decoded).to be_correct_and_respond 202 + + expect(tx_decoded['id'].size).to be 64 + decoded_fee = tx_decoded['fee']['quantity'] + expect(expected_fee).to eq decoded_fee + + # cosigner0 signs + tx_signed1 = SHARED.transactions.sign(src_wid, PASS, tx_constructed['transaction']) + expect(tx_signed1).to be_correct_and_respond 202 + + # cosigner0 submits + tx_submitted = SHARED.transactions.submit(src_wid, tx_signed1['transaction']) + expect(tx_submitted).to be_correct_and_respond 403 + expect(tx_submitted['code']).to eq 'missing_witnesses_in_transaction' + end + + it 'Cannot submit if tx is foreign - two cosigners, all' do + amt = MIN_UTXO_VALUE_PURE_ADA * 2 + src_wid = @wid_sha_cos0_all + cosigner_wid = @wid_sha_cos1_all + foreign_wid = @wid_sha + target_wid = @target_id + address = SHELLEY.addresses.list(target_wid)[1]['id'] + + tx_constructed = SHARED.transactions.construct(src_wid, payment_payload(amt, address)) + expect(tx_constructed).to be_correct_and_respond 202 + expected_fee = tx_constructed['fee']['quantity'] + + # Can be decoded + tx_decoded = SHARED.transactions.decode(src_wid, tx_constructed['transaction']) + expect(tx_decoded).to be_correct_and_respond 202 + + expect(tx_decoded['id'].size).to be 64 + decoded_fee = tx_decoded['fee']['quantity'] + expect(expected_fee).to eq decoded_fee + + # cosigner0 signs + tx_signed1 = SHARED.transactions.sign(src_wid, PASS, tx_constructed['transaction']) + expect(tx_signed1).to be_correct_and_respond 202 + + # cosigner1 signs + tx_signed = SHARED.transactions.sign(cosigner_wid, PASS, tx_constructed['transaction']) + expect(tx_signed).to be_correct_and_respond 202 + + # foreign submits + tx_submitted = SHARED.transactions.submit(foreign_wid, tx_signed['transaction']) + expect(tx_submitted).to be_correct_and_respond 403 + expect(tx_submitted['code']).to eq 'foreign_transaction' + end + + it 'Single output transaction - two cosigners, all' do + amt = MIN_UTXO_VALUE_PURE_ADA * 2 + src_wid = @wid_sha_cos0_all + cosigner_wid = @wid_sha_cos1_all + target_wid = @target_id + address = SHELLEY.addresses.list(target_wid)[1]['id'] + target_before = get_shelley_balances(target_wid) + src_before = get_shared_balances(src_wid) + + tx_constructed = SHARED.transactions.construct(src_wid, payment_payload(amt, address)) + expect(tx_constructed).to be_correct_and_respond 202 + expected_fee = tx_constructed['fee']['quantity'] + + # Can be decoded + tx_decoded = SHARED.transactions.decode(src_wid, tx_constructed['transaction']) + expect(tx_decoded).to be_correct_and_respond 202 + + expect(tx_decoded['id'].size).to be 64 + decoded_fee = tx_decoded['fee']['quantity'] + expect(expected_fee).to eq decoded_fee + + # cosigner0 signs + tx_signed1 = SHARED.transactions.sign(src_wid, PASS, tx_constructed['transaction']) + expect(tx_signed1).to be_correct_and_respond 202 + + # cosigner1 signs + tx_signed = SHARED.transactions.sign(cosigner_wid, PASS, tx_signed1['transaction']) + expect(tx_signed).to be_correct_and_respond 202 + + # cosigner0 submits + tx_submitted = SHARED.transactions.submit(src_wid, tx_signed['transaction']) + expect(tx_submitted).to be_correct_and_respond 202 + + tx_id = tx_submitted['id'] + wait_for_tx_in_ledger(src_wid, tx_id, SHARED) + + target_after = get_shelley_balances(target_wid) + src_after = get_shared_balances(src_wid) + + verify_ada_balance(src_after, src_before, + target_after, target_before, + amt, expected_fee) + # tx history + # on src wallet + tx = SHARED.transactions.get(src_wid, tx_id) + tx_amount(tx, amt + expected_fee) + tx_fee(tx, expected_fee) + tx_inputs(tx, present: true) + tx_outputs(tx, present: true) + tx_direction(tx, 'outgoing') + tx_script_validity(tx, 'valid') + tx_status(tx, 'in_ledger') + tx_collateral(tx, present: false) + tx_collateral_outputs(tx, present: false) + tx_metadata(tx, nil) + tx_deposits(tx, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(tx, present: false) + tx_mint_burn(tx, mint: [], burn: []) + tx_extra_signatures(tx, present: false) + tx_script_integrity(tx, present: false) + tx_validity_interval_default(tx) + tx_certificates(tx, present: false) + + # on co-signer wid + tx = SHARED.transactions.get(cosigner_wid, tx_id) + tx_amount(tx, amt + expected_fee) + tx_fee(tx, expected_fee) + tx_inputs(tx, present: true) + tx_outputs(tx, present: true) + tx_direction(tx, 'outgoing') + tx_script_validity(tx, 'valid') + tx_status(tx, 'in_ledger') + tx_collateral(tx, present: false) + tx_collateral_outputs(tx, present: false) + tx_metadata(tx, nil) + tx_deposits(tx, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(tx, present: false) + tx_mint_burn(tx, mint: [], burn: []) + tx_extra_signatures(tx, present: false) + tx_script_integrity(tx, present: false) + tx_validity_interval_default(tx) + tx_certificates(tx, present: false) + + # on target wallet + txt = SHELLEY.transactions.get(target_wid, tx_id) + tx_amount(txt, amt) + tx_fee(txt, 0) + tx_inputs(txt, present: true) + tx_outputs(txt, present: true) + tx_direction(txt, 'incoming') + tx_script_validity(txt, 'valid') + tx_status(txt, 'in_ledger') + tx_collateral(txt, present: false) + tx_collateral_outputs(txt, present: false) + tx_metadata(txt, nil) + tx_deposits(txt, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(txt, present: false) + tx_mint_burn(txt, mint: [], burn: []) + tx_extra_signatures(txt, present: false) + tx_script_integrity(txt, present: false) + tx_validity_interval_default(txt) + tx_certificates(txt, present: false) + end + + it 'Multi output transaction - two cosigners, all' do + amt = MIN_UTXO_VALUE_PURE_ADA + src_wid = @wid_sha_cos0_all + cosigner_wid = @wid_sha_cos1_all + target_wid = @target_id + address = SHELLEY.addresses.list(target_wid)[1]['id'] + target_before = get_shelley_balances(target_wid) + src_before = get_shared_balances(src_wid) + payment = [{ address: address, + amount: { quantity: amt, + unit: 'lovelace' } }, + { address: address, + amount: { quantity: amt, + unit: 'lovelace' } }] + + tx_constructed = SHARED.transactions.construct(src_wid, payment) + expect(tx_constructed).to be_correct_and_respond 202 + expected_fee = tx_constructed['fee']['quantity'] + + # Can be decoded + tx_decoded = SHARED.transactions.decode(src_wid, tx_constructed['transaction']) + expect(tx_decoded).to be_correct_and_respond 202 + + expect(tx_decoded['id'].size).to be 64 + decoded_fee = tx_decoded['fee']['quantity'] + expect(expected_fee).to eq decoded_fee + + # cosigner0 signs + tx_signed1 = SHARED.transactions.sign(src_wid, PASS, tx_constructed['transaction']) + expect(tx_signed1).to be_correct_and_respond 202 + + # cosigner1 signs + tx_signed = SHARED.transactions.sign(cosigner_wid, PASS, tx_signed1['transaction']) + expect(tx_signed).to be_correct_and_respond 202 + + # cosigner1 submits + tx_submitted = SHARED.transactions.submit(cosigner_wid, tx_signed['transaction']) + expect(tx_submitted).to be_correct_and_respond 202 + + tx_id = tx_submitted['id'] + wait_for_tx_in_ledger(src_wid, tx_id, SHARED) + + target_after = get_shelley_balances(target_wid) + src_after = get_shared_balances(src_wid) + + verify_ada_balance(src_after, src_before, + target_after, target_before, + amt * 2, expected_fee) + # tx history + # on src wallet + tx = SHARED.transactions.get(src_wid, tx_id) + tx_amount(tx, (amt * 2) + expected_fee) + tx_fee(tx, expected_fee) + tx_inputs(tx, present: true) + tx_outputs(tx, present: true) + tx_direction(tx, 'outgoing') + tx_script_validity(tx, 'valid') + tx_status(tx, 'in_ledger') + tx_collateral(tx, present: false) + tx_collateral_outputs(tx, present: false) + tx_metadata(tx, nil) + tx_deposits(tx, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(tx, present: false) + tx_mint_burn(tx, mint: [], burn: []) + tx_extra_signatures(tx, present: false) + tx_script_integrity(tx, present: false) + tx_validity_interval_default(tx) + tx_certificates(tx, present: false) + + # on co-signer wid + tx = SHARED.transactions.get(cosigner_wid, tx_id) + tx_amount(tx, (amt * 2) + expected_fee) + tx_fee(tx, expected_fee) + tx_inputs(tx, present: true) + tx_outputs(tx, present: true) + tx_direction(tx, 'outgoing') + tx_script_validity(tx, 'valid') + tx_status(tx, 'in_ledger') + tx_collateral(tx, present: false) + tx_collateral_outputs(tx, present: false) + tx_metadata(tx, nil) + tx_deposits(tx, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(tx, present: false) + tx_mint_burn(tx, mint: [], burn: []) + tx_extra_signatures(tx, present: false) + tx_script_integrity(tx, present: false) + tx_validity_interval_default(tx) + tx_certificates(tx, present: false) + + # on target wallet + txt = SHELLEY.transactions.get(target_wid, tx_id) + tx_amount(txt, amt * 2) + tx_fee(txt, 0) + tx_inputs(txt, present: true) + tx_outputs(txt, present: true) + tx_direction(txt, 'incoming') + tx_script_validity(txt, 'valid') + tx_status(txt, 'in_ledger') + tx_collateral(txt, present: false) + tx_collateral_outputs(txt, present: false) + tx_metadata(txt, nil) + tx_deposits(txt, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(txt, present: false) + tx_mint_burn(txt, mint: [], burn: []) + tx_extra_signatures(txt, present: false) + tx_script_integrity(txt, present: false) + tx_validity_interval_default(txt) + tx_certificates(txt, present: false) + end + + it 'Multi-assets transaction - two cosigners, all' do + amt = 1 + amt_ada = 1_600_000 + src_wid = @wid_sha_cos0_all + cosigner_wid = @wid_sha_cos1_all + target_wid = @target_id + address = SHELLEY.addresses.list(target_wid)[1]['id'] + target_before = get_shelley_balances(target_wid) + src_before = get_shared_balances(src_wid) + payment = [{ 'address' => address, + 'amount' => { 'quantity' => amt_ada, 'unit' => 'lovelace' }, + 'assets' => [{ 'policy_id' => ASSETS[0]['policy_id'], + 'asset_name' => ASSETS[0]['asset_name'], + 'quantity' => amt }, + { 'policy_id' => ASSETS[1]['policy_id'], + 'asset_name' => ASSETS[1]['asset_name'], + 'quantity' => amt }] }] + + tx_constructed = SHARED.transactions.construct(src_wid, payment) + expect(tx_constructed).to be_correct_and_respond 202 + expected_fee = tx_constructed['fee']['quantity'] + + # Can be decoded + tx_decoded = SHARED.transactions.decode(src_wid, tx_constructed['transaction']) + expect(tx_decoded).to be_correct_and_respond 202 + + expect(tx_decoded['id'].size).to be 64 + decoded_fee = tx_decoded['fee']['quantity'] + expect(expected_fee).to eq decoded_fee + + # cosigner0 signs + tx_signed1 = SHARED.transactions.sign(src_wid, PASS, tx_constructed['transaction']) + expect(tx_signed1).to be_correct_and_respond 202 + + # cosigner1 signs + tx_signed = SHARED.transactions.sign(cosigner_wid, PASS, tx_signed1['transaction']) + expect(tx_signed).to be_correct_and_respond 202 + + # cosigner0 submits + tx_submitted = SHARED.transactions.submit(src_wid, tx_signed['transaction']) + expect(tx_submitted).to be_correct_and_respond 202 + + tx_id = tx_submitted['id'] + wait_for_tx_in_ledger(src_wid, tx_id, SHARED) + + target_after = get_shelley_balances(target_wid) + src_after = get_shared_balances(src_wid) + + verify_ada_balance(src_after, src_before, + target_after, target_before, + amt_ada, expected_fee) + # tx history + # on src wallet + tx = SHARED.transactions.get(src_wid, tx_id) + tx_amount(tx, amt_ada + expected_fee) + tx_fee(tx, expected_fee) + tx_inputs(tx, present: true) + tx_outputs(tx, present: true) + tx_direction(tx, 'outgoing') + tx_script_validity(tx, 'valid') + tx_status(tx, 'in_ledger') + tx_collateral(tx, present: false) + tx_collateral_outputs(tx, present: false) + tx_metadata(tx, nil) + tx_deposits(tx, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(tx, present: false) + tx_mint_burn(tx, mint: [], burn: []) + tx_extra_signatures(tx, present: false) + tx_script_integrity(tx, present: false) + tx_validity_interval_default(tx) + tx_certificates(tx, present: false) + + # on co-signer wid + tx = SHARED.transactions.get(cosigner_wid, tx_id) + tx_amount(tx, amt_ada + expected_fee) + tx_fee(tx, expected_fee) + tx_inputs(tx, present: true) + tx_outputs(tx, present: true) + tx_direction(tx, 'outgoing') + tx_script_validity(tx, 'valid') + tx_status(tx, 'in_ledger') + tx_collateral(tx, present: false) + tx_collateral_outputs(tx, present: false) + tx_metadata(tx, nil) + tx_deposits(tx, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(tx, present: false) + tx_mint_burn(tx, mint: [], burn: []) + tx_extra_signatures(tx, present: false) + tx_script_integrity(tx, present: false) + tx_validity_interval_default(tx) + tx_certificates(tx, present: false) + + # on target wallet + txt = SHELLEY.transactions.get(target_wid, tx_id) + tx_amount(txt, amt_ada) + tx_fee(txt, 0) + tx_inputs(txt, present: true) + tx_outputs(txt, present: true) + tx_direction(txt, 'incoming') + tx_script_validity(txt, 'valid') + tx_status(txt, 'in_ledger') + tx_collateral(txt, present: false) + tx_collateral_outputs(txt, present: false) + tx_metadata(txt, nil) + tx_deposits(txt, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(txt, present: false) + tx_mint_burn(txt, mint: [], burn: []) + tx_extra_signatures(txt, present: false) + tx_script_integrity(txt, present: false) + tx_validity_interval_default(txt) + tx_certificates(txt, present: false) + end + + it 'Validity intervals - two cosigners, all' do + amt = MIN_UTXO_VALUE_PURE_ADA + src_wid = @wid_sha_cos0_all + cosigner_wid = @wid_sha_cos1_all + target_wid = @target_id + address = SHELLEY.addresses.list(target_wid)[1]['id'] + target_before = get_shelley_balances(target_wid) + src_before = get_shared_balances(src_wid) + inv_before = 500 + inv_hereafter = 5_000_000_000 + validity_interval = { 'invalid_before' => { 'quantity' => inv_before, 'unit' => 'slot' }, + 'invalid_hereafter' => { 'quantity' => inv_hereafter, 'unit' => 'slot' } } + tx_constructed = SHARED.transactions.construct(cosigner_wid, + payment_payload(amt, address), + nil, # withdrawal + nil, # metadata + nil, # delegations + nil, # mint_burn + validity_interval) + expect(tx_constructed).to be_correct_and_respond 202 + expected_fee = tx_constructed['fee']['quantity'] + + # Can be decoded + tx_decoded = SHARED.transactions.decode(src_wid, tx_constructed['transaction']) + expect(tx_decoded).to be_correct_and_respond 202 + + expect(tx_decoded['id'].size).to be 64 + decoded_fee = tx_decoded['fee']['quantity'] + expect(expected_fee).to eq decoded_fee + + # cosigner0 signs + tx_signed1 = SHARED.transactions.sign(src_wid, PASS, tx_constructed['transaction']) + expect(tx_signed1).to be_correct_and_respond 202 + + # cosigner1 signs + tx_signed = SHARED.transactions.sign(cosigner_wid, PASS, tx_signed1['transaction']) + expect(tx_signed).to be_correct_and_respond 202 + + # cosigner0 submits + tx_submitted = SHARED.transactions.submit(src_wid, tx_signed['transaction']) + expect(tx_submitted).to be_correct_and_respond 202 + + tx_id = tx_submitted['id'] + wait_for_tx_in_ledger(src_wid, tx_id, SHARED) + + target_after = get_shelley_balances(target_wid) + src_after = get_shared_balances(src_wid) + + verify_ada_balance(src_after, src_before, + target_after, target_before, + amt, expected_fee) + # tx history + # on src wallet + tx = SHARED.transactions.get(src_wid, tx_id) + tx_amount(tx, amt + expected_fee) + tx_fee(tx, expected_fee) + tx_inputs(tx, present: true) + tx_outputs(tx, present: true) + tx_direction(tx, 'outgoing') + tx_script_validity(tx, 'valid') + tx_status(tx, 'in_ledger') + tx_collateral(tx, present: false) + tx_collateral_outputs(tx, present: false) + tx_metadata(tx, nil) + tx_deposits(tx, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(tx, present: false) + tx_mint_burn(tx, mint: [], burn: []) + tx_extra_signatures(tx, present: false) + tx_script_integrity(tx, present: false) + tx_validity_interval(tx, invalid_before: inv_before, invalid_hereafter: inv_hereafter) + tx_certificates(tx, present: false) + + # on co-signer wid + tx = SHARED.transactions.get(cosigner_wid, tx_id) + tx_amount(tx, amt + expected_fee) + tx_fee(tx, expected_fee) + tx_inputs(tx, present: true) + tx_outputs(tx, present: true) + tx_direction(tx, 'outgoing') + tx_script_validity(tx, 'valid') + tx_status(tx, 'in_ledger') + tx_collateral(tx, present: false) + tx_collateral_outputs(tx, present: false) + tx_metadata(tx, nil) + tx_deposits(tx, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(tx, present: false) + tx_mint_burn(tx, mint: [], burn: []) + tx_extra_signatures(tx, present: false) + tx_script_integrity(tx, present: false) + tx_validity_interval(tx, invalid_before: inv_before, invalid_hereafter: inv_hereafter) + tx_certificates(tx, present: false) + + # on target wallet + txt = SHELLEY.transactions.get(target_wid, tx_id) + tx_amount(txt, amt) + tx_fee(txt, 0) + tx_inputs(txt, present: true) + tx_outputs(txt, present: true) + tx_direction(txt, 'incoming') + tx_script_validity(txt, 'valid') + tx_status(txt, 'in_ledger') + tx_collateral(txt, present: false) + tx_collateral_outputs(txt, present: false) + tx_metadata(txt, nil) + tx_deposits(txt, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(txt, present: false) + tx_mint_burn(txt, mint: [], burn: []) + tx_extra_signatures(txt, present: false) + tx_script_integrity(txt, present: false) + tx_validity_interval(txt, invalid_before: inv_before, invalid_hereafter: inv_hereafter) + tx_certificates(txt, present: false) + end + + it 'Only metadata - two cosigners, all' do + src_wid = @wid_sha_cos0_all + cosigner_wid = @wid_sha_cos1_all + metadata = METADATA + balance = get_shared_balances(src_wid) + + tx_constructed = SHARED.transactions.construct(src_wid, + nil, # payments + nil, # withdrawal + metadata) + expect(tx_constructed).to be_correct_and_respond 202 + expected_fee = tx_constructed['fee']['quantity'] + + # Can be decoded + tx_decoded = SHARED.transactions.decode(src_wid, tx_constructed['transaction']) + expect(tx_decoded).to be_correct_and_respond 202 + + expect(tx_decoded['id'].size).to be 64 + decoded_fee = tx_decoded['fee']['quantity'] + expect(expected_fee).to eq decoded_fee + + # cosigner0 signs + tx_signed1 = SHARED.transactions.sign(src_wid, PASS, tx_constructed['transaction']) + expect(tx_signed1).to be_correct_and_respond 202 + + # cosigner1 signs + tx_signed = SHARED.transactions.sign(cosigner_wid, PASS, tx_signed1['transaction']) + expect(tx_signed).to be_correct_and_respond 202 + + # cosigner0 submits + tx_submitted = SHARED.transactions.submit(src_wid, tx_signed['transaction']) + expect(tx_submitted).to be_correct_and_respond 202 + + tx_id = tx_submitted['id'] + wait_for_tx_in_ledger(src_wid, tx_id, SHARED) + + # examine the tx in history + # on src wallet + tx = SHARED.transactions.get(src_wid, tx_id) + tx_amount(tx, expected_fee) + tx_fee(tx, expected_fee) + tx_inputs(tx, present: true) + tx_outputs(tx, present: true) + tx_direction(tx, 'outgoing') + tx_script_validity(tx, 'valid') + tx_status(tx, 'in_ledger') + tx_collateral(tx, present: false) + tx_collateral_outputs(tx, present: false) + tx_metadata(tx, metadata) + tx_deposits(tx, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(tx, present: false) + tx_mint_burn(tx, mint: [], burn: []) + tx_extra_signatures(tx, present: false) + tx_script_integrity(tx, present: false) + tx_validity_interval_default(tx) + tx_certificates(tx, present: false) + + # verify balance is as expected + new_balance = get_shared_balances(src_wid) + expect(new_balance['available']).to eq(balance['available'] - expected_fee) + expect(new_balance['total']).to eq(balance['total'] - expected_fee) + end + + it 'Single output transaction - one cosigner, any' do + amt = MIN_UTXO_VALUE_PURE_ADA * 2 + src_wid = @wid_sha_cos0_any + target_wid = @target_id + address = SHELLEY.addresses.list(target_wid)[1]['id'] + target_before = get_shelley_balances(target_wid) + src_before = get_shared_balances(src_wid) + + tx_constructed = SHARED.transactions.construct(src_wid, payment_payload(amt, address)) + expect(tx_constructed).to be_correct_and_respond 202 + expected_fee = tx_constructed['fee']['quantity'] + + # Can be decoded + tx_decoded = SHARED.transactions.decode(src_wid, tx_constructed['transaction']) + expect(tx_decoded).to be_correct_and_respond 202 + + expect(tx_decoded['id'].size).to be 64 + decoded_fee = tx_decoded['fee']['quantity'] + expect(expected_fee).to eq decoded_fee + + # cosigner0 signs + tx_signed = SHARED.transactions.sign(src_wid, PASS, tx_constructed['transaction']) + expect(tx_signed).to be_correct_and_respond 202 + + # cosigner0 submits + tx_submitted = SHARED.transactions.submit(src_wid, tx_signed['transaction']) + expect(tx_submitted).to be_correct_and_respond 202 + + tx_id = tx_submitted['id'] + wait_for_tx_in_ledger(src_wid, tx_id, SHARED) + + target_after = get_shelley_balances(target_wid) + src_after = get_shared_balances(src_wid) + + verify_ada_balance(src_after, src_before, + target_after, target_before, + amt, expected_fee) + # tx history + # on src wallet + tx = SHARED.transactions.get(src_wid, tx_id) + tx_amount(tx, amt + expected_fee) + tx_fee(tx, expected_fee) + tx_inputs(tx, present: true) + tx_outputs(tx, present: true) + tx_direction(tx, 'outgoing') + tx_script_validity(tx, 'valid') + tx_status(tx, 'in_ledger') + tx_collateral(tx, present: false) + tx_collateral_outputs(tx, present: false) + tx_metadata(tx, nil) + tx_deposits(tx, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(tx, present: false) + tx_mint_burn(tx, mint: [], burn: []) + tx_extra_signatures(tx, present: false) + tx_script_integrity(tx, present: false) + tx_validity_interval_default(tx) + tx_certificates(tx, present: false) + + # on target wallet + txt = SHELLEY.transactions.get(target_wid, tx_id) + tx_amount(txt, amt) + tx_fee(txt, 0) + tx_inputs(txt, present: true) + tx_outputs(txt, present: true) + tx_direction(txt, 'incoming') + tx_script_validity(txt, 'valid') + tx_status(txt, 'in_ledger') + tx_collateral(txt, present: false) + tx_collateral_outputs(txt, present: false) + tx_metadata(txt, nil) + tx_deposits(txt, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(txt, present: false) + tx_mint_burn(txt, mint: [], burn: []) + tx_extra_signatures(txt, present: false) + tx_script_integrity(txt, present: false) + tx_validity_interval_default(txt) + tx_certificates(txt, present: false) + end + end + describe 'E2E Construct -> Sign -> Submit - single signer' do + it 'I can get min_utxo_value when contructing tx' do + amt = 1 + tx_constructed = SHARED.transactions.construct(@wid_sha, payment_payload(amt)) + expect(tx_constructed.code).to eq 403 + expect(tx_constructed['code']).to eq 'utxo_too_small' + required_minimum = tx_constructed['info']['tx_output_lovelace_required_minimum']['quantity'] + + tx_constructed = SHARED.transactions.construct(@wid_sha, payment_payload(required_minimum)) + expect(tx_constructed).to be_correct_and_respond 202 + end + + it 'Single output transaction' do + amt = MIN_UTXO_VALUE_PURE_ADA * 2 + address = SHELLEY.addresses.list(@target_id)[1]['id'] + target_before = get_shelley_balances(@target_id) + src_before = get_shared_balances(@wid_sha) + + tx_constructed = SHARED.transactions.construct(@wid_sha, payment_payload(amt, address)) + expect(tx_constructed).to be_correct_and_respond 202 + expected_fee = tx_constructed['fee']['quantity'] + + # Can be decoded + tx_decoded = SHARED.transactions.decode(@wid_sha, tx_constructed['transaction']) + expect(tx_decoded).to be_correct_and_respond 202 + + expect(tx_decoded['id'].size).to be 64 + decoded_fee = tx_decoded['fee']['quantity'] + expect(expected_fee).to eq decoded_fee + # inputs are ours + expect(tx_decoded['inputs'].to_s).to include 'address' + expect(tx_decoded['inputs'].to_s).to include 'amount' + expect(tx_decoded['outputs']).not_to eq [] + expect(tx_decoded['script_validity']).to eq 'valid' + expect(tx_decoded['validity_interval']['invalid_before']).to eq({ 'quantity' => 0, 'unit' => 'slot' }) + expect(tx_decoded['validity_interval']['invalid_hereafter']['quantity']).to be > 0 + expect(tx_decoded['collateral']).to eq [] + expect(tx_decoded['collateral_outputs']).to eq [] + expect(tx_decoded['metadata']).to eq nil + expect(tx_decoded['deposits_taken']).to eq [] + expect(tx_decoded['deposits_returned']).to eq [] + expect(tx_decoded['withdrawals']).to eq [] + expect(tx_decoded['mint']).to eq({ 'tokens' => [] }) + expect(tx_decoded['burn']).to eq({ 'tokens' => [] }) + expect(tx_decoded['certificates']).to eq [] + + tx_signed = SHARED.transactions.sign(@wid_sha, PASS, tx_constructed['transaction']) + expect(tx_signed).to be_correct_and_respond 202 + + tx_submitted = SHARED.transactions.submit(@wid_sha, tx_signed['transaction']) + expect(tx_submitted).to be_correct_and_respond 202 + + tx_id = tx_submitted['id'] + wait_for_tx_in_ledger(@wid_sha, tx_id, SHARED) + + target_after = get_shelley_balances(@target_id) + src_after = get_shared_balances(@wid_sha) + + verify_ada_balance(src_after, src_before, + target_after, target_before, + amt, expected_fee) + # tx history + # on src wallet + tx = SHARED.transactions.get(@wid_sha, tx_id) + tx_amount(tx, amt + expected_fee) + tx_fee(tx, expected_fee) + tx_inputs(tx, present: true) + tx_outputs(tx, present: true) + tx_direction(tx, 'outgoing') + tx_script_validity(tx, 'valid') + tx_status(tx, 'in_ledger') + tx_collateral(tx, present: false) + tx_collateral_outputs(tx, present: false) + tx_metadata(tx, nil) + tx_deposits(tx, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(tx, present: false) + tx_mint_burn(tx, mint: [], burn: []) + tx_extra_signatures(tx, present: false) + tx_script_integrity(tx, present: false) + tx_validity_interval_default(tx) + tx_certificates(tx, present: false) + + # on target wallet + txt = SHELLEY.transactions.get(@target_id, tx_id) + tx_amount(txt, amt) + tx_fee(txt, 0) + tx_inputs(txt, present: true) + tx_outputs(txt, present: true) + tx_direction(txt, 'incoming') + tx_script_validity(txt, 'valid') + tx_status(txt, 'in_ledger') + tx_collateral(txt, present: false) + tx_collateral_outputs(txt, present: false) + tx_metadata(txt, nil) + tx_deposits(txt, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(txt, present: false) + tx_mint_burn(txt, mint: [], burn: []) + tx_extra_signatures(txt, present: false) + tx_script_integrity(txt, present: false) + tx_validity_interval_default(txt) + tx_certificates(txt, present: false) + end + + it 'Multi output transaction' do + amt = MIN_UTXO_VALUE_PURE_ADA + address = SHELLEY.addresses.list(@target_id)[1]['id'] + target_before = get_shelley_balances(@target_id) + src_before = get_shared_balances(@wid_sha) + + payment = [{ address: address, + amount: { quantity: amt, + unit: 'lovelace' } }, + { address: address, + amount: { quantity: amt, + unit: 'lovelace' } }] + tx_constructed = SHARED.transactions.construct(@wid_sha, payment) + expect(tx_constructed).to be_correct_and_respond 202 + expected_fee = tx_constructed['fee']['quantity'] + + # Can be decoded + tx_decoded = SHARED.transactions.decode(@wid_sha, tx_constructed['transaction']) + expect(tx_decoded).to be_correct_and_respond 202 + + expect(tx_decoded['id'].size).to be 64 + decoded_fee = tx_decoded['fee']['quantity'] + expect(expected_fee).to eq decoded_fee + # inputs are ours + expect(tx_decoded['inputs'].to_s).to include 'address' + expect(tx_decoded['inputs'].to_s).to include 'amount' + expect(tx_decoded['outputs']).not_to eq [] + expect(tx_decoded['script_validity']).to eq 'valid' + expect(tx_decoded['validity_interval']['invalid_before']).to eq({ 'quantity' => 0, 'unit' => 'slot' }) + expect(tx_decoded['validity_interval']['invalid_hereafter']['quantity']).to be > 0 + expect(tx_decoded['collateral']).to eq [] + expect(tx_decoded['collateral_outputs']).to eq [] + expect(tx_decoded['metadata']).to eq nil + expect(tx_decoded['deposits_taken']).to eq [] + expect(tx_decoded['deposits_returned']).to eq [] + expect(tx_decoded['withdrawals']).to eq [] + expect(tx_decoded['mint']).to eq({ 'tokens' => [] }) + expect(tx_decoded['burn']).to eq({ 'tokens' => [] }) + expect(tx_decoded['certificates']).to eq [] + + tx_signed = SHARED.transactions.sign(@wid_sha, PASS, tx_constructed['transaction']) + expect(tx_signed).to be_correct_and_respond 202 + + tx_submitted = SHARED.transactions.submit(@wid_sha, tx_signed['transaction']) + expect(tx_submitted).to be_correct_and_respond 202 + + tx_id = tx_submitted['id'] + wait_for_tx_in_ledger(@wid_sha, tx_id, SHARED) + + target_after = get_shelley_balances(@target_id) + src_after = get_shared_balances(@wid_sha) + + verify_ada_balance(src_after, src_before, + target_after, target_before, + amt * 2, expected_fee) + # tx history + # on src wallet + tx = SHARED.transactions.get(@wid_sha, tx_id) + tx_amount(tx, (amt * 2) + expected_fee) + tx_fee(tx, expected_fee) + tx_inputs(tx, present: true) + tx_outputs(tx, present: true) + tx_direction(tx, 'outgoing') + tx_script_validity(tx, 'valid') + tx_status(tx, 'in_ledger') + tx_collateral(tx, present: false) + tx_collateral_outputs(tx, present: false) + tx_metadata(tx, nil) + tx_deposits(tx, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(tx, present: false) + tx_mint_burn(tx, mint: [], burn: []) + tx_extra_signatures(tx, present: false) + tx_script_integrity(tx, present: false) + tx_validity_interval_default(tx) + tx_certificates(tx, present: false) + + # on target wallet + txt = SHELLEY.transactions.get(@target_id, tx_id) + tx_amount(txt, amt * 2) + tx_fee(txt, 0) + tx_inputs(txt, present: true) + tx_outputs(txt, present: true) + tx_direction(txt, 'incoming') + tx_script_validity(txt, 'valid') + tx_status(txt, 'in_ledger') + tx_collateral(txt, present: false) + tx_collateral_outputs(txt, present: false) + tx_metadata(txt, nil) + tx_deposits(txt, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(txt, present: false) + tx_mint_burn(txt, mint: [], burn: []) + tx_extra_signatures(txt, present: false) + tx_script_integrity(txt, present: false) + tx_validity_interval_default(txt) + tx_certificates(txt, present: false) + end + + it 'Multi-assets transaction' do + amt = 1 + amt_ada = 1_600_000 + address = SHELLEY.addresses.list(@target_id)[1]['id'] + target_before = get_shelley_balances(@target_id) + src_before = get_shared_balances(@wid_sha) + + payment = [{ 'address' => address, + 'amount' => { 'quantity' => amt_ada, 'unit' => 'lovelace' }, + 'assets' => [{ 'policy_id' => ASSETS[0]['policy_id'], + 'asset_name' => ASSETS[0]['asset_name'], + 'quantity' => amt }, + { 'policy_id' => ASSETS[1]['policy_id'], + 'asset_name' => ASSETS[1]['asset_name'], + 'quantity' => amt }] }] + tx_constructed = SHARED.transactions.construct(@wid_sha, payment) + expect(tx_constructed).to be_correct_and_respond 202 + expected_fee = tx_constructed['fee']['quantity'] + + # Can be decoded + tx_decoded = SHARED.transactions.decode(@wid_sha, tx_constructed['transaction']) + expect(tx_decoded).to be_correct_and_respond 202 + + expect(tx_decoded['id'].size).to be 64 + decoded_fee = tx_decoded['fee']['quantity'] + expect(expected_fee).to eq decoded_fee + # inputs are ours + expect(tx_decoded['inputs'].to_s).to include 'address' + expect(tx_decoded['inputs'].to_s).to include 'amount' + expect(tx_decoded['outputs']).not_to eq [] + expect(tx_decoded['script_validity']).to eq 'valid' + expect(tx_decoded['validity_interval']['invalid_before']).to eq({ 'quantity' => 0, 'unit' => 'slot' }) + expect(tx_decoded['validity_interval']['invalid_hereafter']['quantity']).to be > 0 + expect(tx_decoded['collateral']).to eq [] + expect(tx_decoded['collateral_outputs']).to eq [] + expect(tx_decoded['metadata']).to eq nil + expect(tx_decoded['deposits_taken']).to eq [] + expect(tx_decoded['deposits_returned']).to eq [] + expect(tx_decoded['withdrawals']).to eq [] + expect(tx_decoded['mint']).to eq({ 'tokens' => [] }) + expect(tx_decoded['burn']).to eq({ 'tokens' => [] }) + expect(tx_decoded['certificates']).to eq [] + + tx_signed = SHARED.transactions.sign(@wid_sha, PASS, tx_constructed['transaction']) + expect(tx_signed).to be_correct_and_respond 202 + + tx_submitted = SHARED.transactions.submit(@wid_sha, tx_signed['transaction']) + expect(tx_submitted).to be_correct_and_respond 202 + + tx_id = tx_submitted['id'] + wait_for_tx_in_ledger(@wid_sha, tx_id, SHARED) + + target_after = get_shelley_balances(@target_id) + src_after = get_shared_balances(@wid_sha) + + verify_ada_balance(src_after, src_before, + target_after, target_before, + amt_ada, expected_fee) + + verify_asset_balance(src_after, src_before, + target_after, target_before, + amt) + # tx history + # on src wallet + tx = SHARED.transactions.get(@wid_sha, tx_id) + tx_amount(tx, amt_ada + expected_fee) + tx_fee(tx, expected_fee) + tx_inputs(tx, present: true) + tx_outputs(tx, present: true) + tx_direction(tx, 'outgoing') + tx_script_validity(tx, 'valid') + tx_status(tx, 'in_ledger') + tx_collateral(tx, present: false) + tx_collateral_outputs(tx, present: false) + tx_metadata(tx, nil) + tx_deposits(tx, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(tx, present: false) + tx_mint_burn(tx, mint: [], burn: []) + tx_extra_signatures(tx, present: false) + tx_script_integrity(tx, present: false) + tx_validity_interval_default(tx) + tx_certificates(tx, present: false) + + # on target wallet + txt = SHELLEY.transactions.get(@target_id, tx_id) + tx_amount(txt, amt_ada) + tx_fee(txt, 0) + tx_inputs(txt, present: true) + tx_outputs(txt, present: true) + tx_direction(txt, 'incoming') + tx_script_validity(txt, 'valid') + tx_status(txt, 'in_ledger') + tx_collateral(txt, present: false) + tx_collateral_outputs(txt, present: false) + tx_metadata(txt, nil) + tx_deposits(txt, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(txt, present: false) + tx_mint_burn(txt, mint: [], burn: []) + tx_extra_signatures(txt, present: false) + tx_script_integrity(txt, present: false) + tx_validity_interval_default(txt) + tx_certificates(txt, present: false) + end + + it 'Validity intervals' do + amt = MIN_UTXO_VALUE_PURE_ADA + address = SHELLEY.addresses.list(@target_id)[1]['id'] + target_before = get_shelley_balances(@target_id) + src_before = get_shared_balances(@wid_sha) + inv_before = 500 + inv_hereafter = 5_000_000_000 + validity_interval = { 'invalid_before' => { 'quantity' => inv_before, 'unit' => 'slot' }, + 'invalid_hereafter' => { 'quantity' => inv_hereafter, 'unit' => 'slot' } } + tx_constructed = SHARED.transactions.construct(@wid_sha, + payment_payload(amt, address), + nil, # withdrawal + nil, # metadata + nil, # delegations + nil, # mint_burn + validity_interval) + expect(tx_constructed).to be_correct_and_respond 202 + expected_fee = tx_constructed['fee']['quantity'] + + # Can be decoded + tx_decoded = SHARED.transactions.decode(@wid_sha, tx_constructed['transaction']) + expect(tx_decoded).to be_correct_and_respond 202 + + expect(tx_decoded['id'].size).to be 64 + decoded_fee = tx_decoded['fee']['quantity'] + expect(expected_fee).to eq decoded_fee + # inputs are ours + expect(tx_decoded['inputs'].to_s).to include 'address' + expect(tx_decoded['inputs'].to_s).to include 'amount' + expect(tx_decoded['outputs']).not_to eq [] + expect(tx_decoded['script_validity']).to eq 'valid' + expect(tx_decoded['validity_interval']['invalid_before']).to eq validity_interval['invalid_before'] + expect(tx_decoded['validity_interval']['invalid_hereafter']).to eq validity_interval['invalid_hereafter'] + expect(tx_decoded['collateral']).to eq [] + expect(tx_decoded['collateral_outputs']).to eq [] + expect(tx_decoded['metadata']).to eq nil + expect(tx_decoded['deposits_taken']).to eq [] + expect(tx_decoded['deposits_returned']).to eq [] + expect(tx_decoded['withdrawals']).to eq [] + expect(tx_decoded['mint']).to eq({ 'tokens' => [] }) + expect(tx_decoded['burn']).to eq({ 'tokens' => [] }) + expect(tx_decoded['certificates']).to eq [] + + tx_signed = SHARED.transactions.sign(@wid_sha, PASS, tx_constructed['transaction']) + expect(tx_signed).to be_correct_and_respond 202 + + tx_submitted = SHARED.transactions.submit(@wid_sha, tx_signed['transaction']) + expect(tx_submitted).to be_correct_and_respond 202 + + tx_id = tx_submitted['id'] + wait_for_tx_in_ledger(@wid_sha, tx_id, SHARED) + + target_after = get_shelley_balances(@target_id) + src_after = get_shared_balances(@wid_sha) + + verify_ada_balance(src_after, src_before, + target_after, target_before, + amt, expected_fee) + # tx history + # on src wallet + tx = SHARED.transactions.get(@wid_sha, tx_id) + tx_amount(tx, amt + expected_fee) + tx_fee(tx, expected_fee) + tx_inputs(tx, present: true) + tx_outputs(tx, present: true) + tx_direction(tx, 'outgoing') + tx_script_validity(tx, 'valid') + tx_status(tx, 'in_ledger') + tx_collateral(tx, present: false) + tx_collateral_outputs(tx, present: false) + tx_metadata(tx, nil) + tx_deposits(tx, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(tx, present: false) + tx_mint_burn(tx, mint: [], burn: []) + tx_extra_signatures(tx, present: false) + tx_script_integrity(tx, present: false) + tx_validity_interval(tx, invalid_before: inv_before, invalid_hereafter: inv_hereafter) + tx_certificates(tx, present: false) + + # on target wallet + txt = SHELLEY.transactions.get(@target_id, tx_id) + tx_amount(txt, amt) + tx_fee(txt, 0) + tx_inputs(txt, present: true) + tx_outputs(txt, present: true) + tx_direction(txt, 'incoming') + tx_script_validity(txt, 'valid') + tx_status(txt, 'in_ledger') + tx_collateral(txt, present: false) + tx_collateral_outputs(txt, present: false) + tx_metadata(txt, nil) + tx_deposits(txt, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(txt, present: false) + tx_mint_burn(txt, mint: [], burn: []) + tx_extra_signatures(txt, present: false) + tx_script_integrity(txt, present: false) + tx_validity_interval(txt, invalid_before: inv_before, invalid_hereafter: inv_hereafter) + tx_certificates(txt, present: false) + end + + it 'Only metadata' do + metadata = METADATA + balance = get_shared_balances(@wid_sha) + tx_constructed = SHARED.transactions.construct(@wid_sha, + nil, # payments + nil, # withdrawal + metadata) + expect(tx_constructed).to be_correct_and_respond 202 + expected_fee = tx_constructed['fee']['quantity'] + + # Can be decoded + tx_decoded = SHARED.transactions.decode(@wid_sha, tx_constructed['transaction']) + expect(tx_decoded).to be_correct_and_respond 202 + + expect(tx_decoded['id'].size).to be 64 + decoded_fee = tx_decoded['fee']['quantity'] + expect(expected_fee).to eq decoded_fee + # inputs are ours + expect(tx_decoded['inputs'].to_s).to include 'address' + expect(tx_decoded['inputs'].to_s).to include 'amount' + expect(tx_decoded['outputs']).not_to eq [] + expect(tx_decoded['script_validity']).to eq 'valid' + expect(tx_decoded['validity_interval']['invalid_before']).to eq({ 'quantity' => 0, 'unit' => 'slot' }) + expect(tx_decoded['validity_interval']['invalid_hereafter']['quantity']).to be > 0 + expect(tx_decoded['collateral']).to eq [] + expect(tx_decoded['collateral_outputs']).to eq [] + expect(tx_decoded['metadata']).to eq metadata + expect(tx_decoded['deposits_taken']).to eq [] + expect(tx_decoded['deposits_returned']).to eq [] + expect(tx_decoded['withdrawals']).to eq [] + expect(tx_decoded['mint']).to eq({ 'tokens' => [] }) + expect(tx_decoded['burn']).to eq({ 'tokens' => [] }) + expect(tx_decoded['certificates']).to eq [] + + tx_signed = SHARED.transactions.sign(@wid_sha, PASS, tx_constructed['transaction']) + expect(tx_signed).to be_correct_and_respond 202 + + tx_submitted = SHARED.transactions.submit(@wid_sha, tx_signed['transaction']) + expect(tx_submitted).to be_correct_and_respond 202 + signed_decoded = SHARED.transactions.decode(@wid_sha, tx_signed['transaction']) + expect(signed_decoded['witness_count']['verification_key']).to be >= 1 + expect(expected_fee).to eq signed_decoded['fee']['quantity'] + + tx_id = tx_submitted['id'] + wait_for_tx_in_ledger(@wid_sha, tx_id, SHARED) + + # examine the tx in history + # on src wallet + tx = SHARED.transactions.get(@wid_sha, tx_id) + tx_amount(tx, expected_fee) + tx_fee(tx, expected_fee) + tx_inputs(tx, present: true) + tx_outputs(tx, present: true) + tx_direction(tx, 'outgoing') + tx_script_validity(tx, 'valid') + tx_status(tx, 'in_ledger') + tx_collateral(tx, present: false) + tx_collateral_outputs(tx, present: false) + tx_metadata(tx, metadata) + tx_deposits(tx, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(tx, present: false) + tx_mint_burn(tx, mint: [], burn: []) + tx_extra_signatures(tx, present: false) + tx_script_integrity(tx, present: false) + tx_validity_interval_default(tx) + tx_certificates(tx, present: false) + + # verify balance is as expected + new_balance = get_shared_balances(@wid_sha) + expect(new_balance['available']).to eq(balance['available'] - expected_fee) + expect(new_balance['total']).to eq(balance['total'] - expected_fee) + end + + it 'Delegation (without submitting)' do + # Delegation not yet implemented, only construct and sign in this tc + # balance = get_shared_balances(@wid_sha) + expected_deposit = CARDANO_CLI.protocol_params['stakeAddressDeposit'] + puts "Expected deposit #{expected_deposit}" + + # Pick up pool id to join + pools = SHELLEY.stake_pools + pool_id = pools.list({ stake: 1000 }).sample['id'] + + # Join pool + delegation = [{ + 'join' => { + 'pool' => pool_id, + 'stake_key_index' => '0H' + } + }] + + tx_constructed = SHARED.transactions.construct(@wid_sha, + nil, # payment + nil, # withdrawal + nil, # metadata + delegation, + nil, # mint_burn + nil) # validity_interval + # Check fee and deposit on joining + tx_decoded = SHARED.transactions.decode(@wid_sha, tx_constructed['transaction']) + expect(tx_decoded).to be_correct_and_respond 202 + + # TODO: although you can construct and decode delegation, deposit_taken /deposit_returned are not shown atm + # deposit_taken = tx_constructed['coin_selection']['deposits_taken'].first['quantity'] + # decoded_deposit_taken = tx_decoded['deposits_taken'].first['quantity'] + # expect(deposit_taken).to eq decoded_deposit_taken + # expect(deposit_taken).to eq expected_deposit + + expected_fee = tx_constructed['fee']['quantity'] + decoded_fee = tx_decoded['fee']['quantity'] + expect(decoded_fee).to eq expected_fee + # inputs are ours + expect(tx_decoded['inputs'].to_s).to include 'address' + expect(tx_decoded['inputs'].to_s).to include 'amount' + expect(tx_decoded['outputs']).not_to eq [] + expect(tx_decoded['script_validity']).to eq 'valid' + expect(tx_decoded['validity_interval']['invalid_before']).to eq({ 'quantity' => 0, 'unit' => 'slot' }) + expect(tx_decoded['validity_interval']['invalid_hereafter']['quantity']).to be > 0 + expect(tx_decoded['collateral']).to eq [] + expect(tx_decoded['collateral_outputs']).to eq [] + expect(tx_decoded['metadata']).to eq nil + expect(tx_decoded['deposits_taken']).to eq [] + expect(tx_decoded['deposits_returned']).to eq [] + expect(tx_decoded['withdrawals']).to eq [] + expect(tx_decoded['mint']).to eq({ 'tokens' => [] }) + expect(tx_decoded['burn']).to eq({ 'tokens' => [] }) + expect(tx_decoded['certificates']).to eq [] + + tx_signed = SHARED.transactions.sign(@wid_sha, PASS, tx_constructed['transaction']) + expect(tx_signed).to be_correct_and_respond 202 + end + + describe 'Minting and Burning' do + it 'Can mint and then burn (without submitting)' do + # Minting and Burning not yet implemented, only construct and sign in this tc + # src_before = get_shared_balances(@wid_sha) + policy_script1 = 'cosigner#0' + policy_script2 = { 'all' => ['cosigner#0'] } + policy_script3 = { 'any' => ['cosigner#0'] } + + # Minting: + mint = [mint(asset_name('Token1'), 1000, policy_script1), + mint(asset_name('Token2'), 1000, policy_script2), + mint('', 1000, policy_script3)] + + tx_constructed = SHARED.transactions.construct(@wid_sha, + nil, # payment + nil, # withdrawal + nil, # metadata + nil, # delegation + mint) + expect(tx_constructed).to be_correct_and_respond 202 + + tx_decoded = SHARED.transactions.decode(@wid_sha, tx_constructed['transaction']) + expect(tx_decoded).to be_correct_and_respond 202 + + expected_fee = tx_constructed['fee']['quantity'] + decoded_fee = tx_decoded['fee']['quantity'] + expect(expected_fee).to eq decoded_fee + # inputs are ours + expect(tx_decoded['inputs'].to_s).to include 'address' + expect(tx_decoded['inputs'].to_s).to include 'amount' + expect(tx_decoded['outputs']).not_to eq [] + expect(tx_decoded['script_validity']).to eq 'valid' + expect(tx_decoded['validity_interval']['invalid_before']).to eq({ 'quantity' => 0, 'unit' => 'slot' }) + expect(tx_decoded['validity_interval']['invalid_hereafter']['quantity']).to be > 0 + expect(tx_decoded['collateral']).to eq [] + expect(tx_decoded['collateral_outputs']).to eq [] + expect(tx_decoded['metadata']).to eq nil + expect(tx_decoded['deposits_taken']).to eq [] + expect(tx_decoded['deposits_returned']).to eq [] + expect(tx_decoded['withdrawals']).to eq [] + # TODO: mint / burn currently not decoded + expect(tx_decoded['mint']).to eq({ 'tokens' => [] }) + expect(tx_decoded['burn']).to eq({ 'tokens' => [] }) + expect(tx_decoded['certificates']).to eq [] + + tx_signed = SHARED.transactions.sign(@wid_sha, PASS, tx_constructed['transaction']) + expect(tx_signed).to be_correct_and_respond 202 + end + end + end + + it 'I can receive transaction to shared wallet' do + amt = 1 + amt_ada = 3_000_000 + address = SHARED.addresses.list(@wid_sha)[1]['id'] + target_before = get_shared_balances(@wid_sha) + src_before = get_shelley_balances(@wid) + + payload = [{ 'address' => address, + 'amount' => { 'quantity' => amt_ada, 'unit' => 'lovelace' }, + 'assets' => [{ 'policy_id' => ASSETS[0]['policy_id'], + 'asset_name' => ASSETS[0]['asset_name'], + 'quantity' => amt }, + { 'policy_id' => ASSETS[1]['policy_id'], + 'asset_name' => ASSETS[1]['asset_name'], + 'quantity' => amt }] }] + + tx_sent = SHELLEY.transactions.create(@wid, PASS, payload) + + expect(tx_sent).to be_correct_and_respond 202 + expect(tx_sent.to_s).to include 'pending' + wait_for_tx_in_ledger(@wid, tx_sent['id']) + + target_after = get_shared_balances(@wid_sha) + src_after = get_shelley_balances(@wid) + fee = SHELLEY.transactions.get(@wid, tx_sent['id'])['fee']['quantity'] + + verify_ada_balance(src_after, src_before, + target_after, target_before, + amt_ada, fee) + + verify_asset_balance(src_after, src_before, + target_after, target_before, + amt) + end + end + + describe 'E2E Migration' do + it 'I can migrate all funds back to fixture shared wallet' do + address = SHARED.addresses.list(@wid_sha)[0]['id'] + src_before = get_shelley_balances(@target_id) + target_before = get_shared_balances(@wid_sha) + + migration = SHELLEY.migrations.migrate(@target_id, PASS, [address]) + tx_ids = migration.map { |m| m['id'] } + fees = migration.map { |m| m['fee']['quantity'] }.sum + amounts = migration.map { |m| m['amount']['quantity'] }.sum - fees + tx_ids.each do |tx_id| + wait_for_tx_in_ledger(@target_id, tx_id) + end + src_after = get_shelley_balances(@target_id) + target_after = get_shared_balances(@wid_sha) + expected_src_balance = { 'total' => 0, + 'available' => 0, + 'rewards' => 0, + 'assets_total' => [], + 'assets_available' => [] } + + expect(src_after).to eq expected_src_balance + + verify_ada_balance(src_after, src_before, + target_after, target_before, + amounts, fees) + + tx_ids.each do |tx_id| + # examine the tx in history + # on src wallet + tx = SHELLEY.transactions.get(@target_id, tx_id) + tx_inputs(tx, present: true) + tx_outputs(tx, present: true) + tx_direction(tx, 'outgoing') + tx_script_validity(tx, 'valid') + tx_status(tx, 'in_ledger') + tx_collateral(tx, present: false) + tx_collateral_outputs(tx, present: false) + tx_metadata(tx, nil) + tx_deposits(tx, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(tx, present: false) + tx_mint_burn(tx, mint: [], burn: []) + tx_extra_signatures(tx, present: false) + tx_script_integrity(tx, present: false) + tx_validity_interval_default(tx) + tx_certificates(tx, present: false) + + # on target wallet + txt = SHARED.transactions.get(@wid_sha, tx_id) + tx_fee(txt, 0) + tx_inputs(txt, present: true) + tx_outputs(txt, present: true) + tx_direction(txt, 'incoming') + tx_script_validity(txt, 'valid') + tx_status(txt, 'in_ledger') + tx_collateral(txt, present: false) + tx_collateral_outputs(txt, present: false) + tx_metadata(txt, nil) + tx_deposits(txt, deposit_taken: 0, deposit_returned: 0) + tx_withdrawals(txt, present: false) + tx_mint_burn(txt, mint: [], burn: []) + tx_extra_signatures(txt, present: false) + tx_script_integrity(txt, present: false) + tx_validity_interval_default(txt) + tx_certificates(txt, present: false) + end + end + end +end diff --git a/test/e2e/spec/e2e_spec.rb b/test/e2e/spec/e2e_spec.rb index 9c9394f6654..a225e81d31a 100644 --- a/test/e2e/spec/e2e_spec.rb +++ b/test/e2e/spec/e2e_spec.rb @@ -10,14 +10,9 @@ @wid_rnd = create_fixture_wallet(:random) @wid_ic = create_fixture_wallet(:icarus) - # shared wallets - @wid_sha = create_target_wallet(:shared) - - @nightly_shared_wallets = [@wid_sha] @nighly_byron_wallets = [@wid_rnd, @wid_ic] @nightly_shelley_wallets = [@wid, @target_id] wait_for_all_shelley_wallets(@nightly_shelley_wallets) - wait_for_all_shared_wallets(@nightly_shared_wallets) wait_for_all_byron_wallets(@nighly_byron_wallets) end @@ -2191,556 +2186,6 @@ def fingerprint end end - describe 'E2E Shared' do - describe 'E2E Construct -> Sign -> Submit', :shared do - it 'I can get min_utxo_value when contructing tx' do - amt = 1 - tx_constructed = SHARED.transactions.construct(@wid_sha, payment_payload(amt)) - expect(tx_constructed.code).to eq 403 - expect(tx_constructed['code']).to eq 'utxo_too_small' - required_minimum = tx_constructed['info']['tx_output_lovelace_required_minimum']['quantity'] - - tx_constructed = SHARED.transactions.construct(@wid_sha, payment_payload(required_minimum)) - expect(tx_constructed).to be_correct_and_respond 202 - end - - it 'Single output transaction' do - amt = MIN_UTXO_VALUE_PURE_ADA - address = SHELLEY.addresses.list(@target_id)[1]['id'] - target_before = get_shelley_balances(@target_id) - src_before = get_shared_balances(@wid_sha) - - tx_constructed = SHARED.transactions.construct(@wid_sha, payment_payload(amt, address)) - expect(tx_constructed).to be_correct_and_respond 202 - expected_fee = tx_constructed['fee']['quantity'] - - # Can be decoded - tx_decoded = SHARED.transactions.decode(@wid_sha, tx_constructed['transaction']) - expect(tx_decoded).to be_correct_and_respond 202 - - expect(tx_decoded['id'].size).to be 64 - decoded_fee = tx_decoded['fee']['quantity'] - expect(expected_fee).to eq decoded_fee - # inputs are ours - expect(tx_decoded['inputs'].to_s).to include 'address' - expect(tx_decoded['inputs'].to_s).to include 'amount' - expect(tx_decoded['outputs']).not_to eq [] - expect(tx_decoded['script_validity']).to eq 'valid' - expect(tx_decoded['validity_interval']['invalid_before']).to eq({ 'quantity' => 0, 'unit' => 'slot' }) - expect(tx_decoded['validity_interval']['invalid_hereafter']['quantity']).to be > 0 - expect(tx_decoded['collateral']).to eq [] - expect(tx_decoded['collateral_outputs']).to eq [] - expect(tx_decoded['metadata']).to eq nil - expect(tx_decoded['deposits_taken']).to eq [] - expect(tx_decoded['deposits_returned']).to eq [] - expect(tx_decoded['withdrawals']).to eq [] - expect(tx_decoded['mint']).to eq({ 'tokens' => [] }) - expect(tx_decoded['burn']).to eq({ 'tokens' => [] }) - expect(tx_decoded['certificates']).to eq [] - - tx_signed = SHARED.transactions.sign(@wid_sha, PASS, tx_constructed['transaction']) - expect(tx_signed).to be_correct_and_respond 202 - - tx_submitted = SHARED.transactions.submit(@wid_sha, tx_signed['transaction']) - expect(tx_submitted).to be_correct_and_respond 202 - - tx_id = tx_submitted['id'] - # TODO: ADP-2224: change to wait_for_tx_in_ledger(@wid_sha, tx_id) - eventually "Funds are on target wallet: #{@target_id}" do - available = SHELLEY.wallets.get(@target_id)['balance']['available']['quantity'] - total = SHELLEY.wallets.get(@target_id)['balance']['total']['quantity'] - (available == amt + target_before['available']) && - (total == amt + target_before['total']) - end - - target_after = get_shelley_balances(@target_id) - src_after = get_shared_balances(@wid_sha) - - verify_ada_balance(src_after, src_before, - target_after, target_before, - amt, expected_fee) - # tx history - # TODO ADP-2224: check tx history on src wallet - # on target wallet - txt = SHELLEY.transactions.get(@target_id, tx_id) - tx_amount(txt, amt) - tx_fee(txt, 0) - tx_inputs(txt, present: true) - tx_outputs(txt, present: true) - tx_direction(txt, 'incoming') - tx_script_validity(txt, 'valid') - tx_status(txt, 'in_ledger') - tx_collateral(txt, present: false) - tx_collateral_outputs(txt, present: false) - tx_metadata(txt, nil) - tx_deposits(txt, deposit_taken: 0, deposit_returned: 0) - tx_withdrawals(txt, present: false) - tx_mint_burn(txt, mint: [], burn: []) - tx_extra_signatures(txt, present: false) - tx_script_integrity(txt, present: false) - tx_validity_interval_default(txt) - tx_certificates(txt, present: false) - end - - it 'Multi output transaction' do - amt = MIN_UTXO_VALUE_PURE_ADA - address = SHELLEY.addresses.list(@target_id)[1]['id'] - target_before = get_shelley_balances(@target_id) - src_before = get_shared_balances(@wid_sha) - - payment = [{ address: address, - amount: { quantity: amt, - unit: 'lovelace' } }, - { address: address, - amount: { quantity: amt, - unit: 'lovelace' } }] - tx_constructed = SHARED.transactions.construct(@wid_sha, payment) - expect(tx_constructed).to be_correct_and_respond 202 - expected_fee = tx_constructed['fee']['quantity'] - - # Can be decoded - tx_decoded = SHARED.transactions.decode(@wid_sha, tx_constructed['transaction']) - expect(tx_decoded).to be_correct_and_respond 202 - - expect(tx_decoded['id'].size).to be 64 - decoded_fee = tx_decoded['fee']['quantity'] - expect(expected_fee).to eq decoded_fee - # inputs are ours - expect(tx_decoded['inputs'].to_s).to include 'address' - expect(tx_decoded['inputs'].to_s).to include 'amount' - expect(tx_decoded['outputs']).not_to eq [] - expect(tx_decoded['script_validity']).to eq 'valid' - expect(tx_decoded['validity_interval']['invalid_before']).to eq({ 'quantity' => 0, 'unit' => 'slot' }) - expect(tx_decoded['validity_interval']['invalid_hereafter']['quantity']).to be > 0 - expect(tx_decoded['collateral']).to eq [] - expect(tx_decoded['collateral_outputs']).to eq [] - expect(tx_decoded['metadata']).to eq nil - expect(tx_decoded['deposits_taken']).to eq [] - expect(tx_decoded['deposits_returned']).to eq [] - expect(tx_decoded['withdrawals']).to eq [] - expect(tx_decoded['mint']).to eq({ 'tokens' => [] }) - expect(tx_decoded['burn']).to eq({ 'tokens' => [] }) - expect(tx_decoded['certificates']).to eq [] - - tx_signed = SHARED.transactions.sign(@wid_sha, PASS, tx_constructed['transaction']) - expect(tx_signed).to be_correct_and_respond 202 - - tx_submitted = SHARED.transactions.submit(@wid_sha, tx_signed['transaction']) - expect(tx_submitted).to be_correct_and_respond 202 - - tx_id = tx_submitted['id'] - # TODO: ADP-2224: change to wait_for_tx_in_ledger(@wid_sha, tx_id) - eventually "Funds are on target wallet: #{@target_id}" do - available = SHELLEY.wallets.get(@target_id)['balance']['available']['quantity'] - total = SHELLEY.wallets.get(@target_id)['balance']['total']['quantity'] - (available == (amt * 2) + target_before['available']) && - (total == (amt * 2) + target_before['total']) - end - - target_after = get_shelley_balances(@target_id) - src_after = get_shared_balances(@wid_sha) - - verify_ada_balance(src_after, src_before, - target_after, target_before, - amt * 2, expected_fee) - # tx history - # TODO ADP-2224: check tx history on src wallet - # on target wallet - txt = SHELLEY.transactions.get(@target_id, tx_id) - tx_amount(txt, amt * 2) - tx_fee(txt, 0) - tx_inputs(txt, present: true) - tx_outputs(txt, present: true) - tx_direction(txt, 'incoming') - tx_script_validity(txt, 'valid') - tx_status(txt, 'in_ledger') - tx_collateral(txt, present: false) - tx_collateral_outputs(txt, present: false) - tx_metadata(txt, nil) - tx_deposits(txt, deposit_taken: 0, deposit_returned: 0) - tx_withdrawals(txt, present: false) - tx_mint_burn(txt, mint: [], burn: []) - tx_extra_signatures(txt, present: false) - tx_script_integrity(txt, present: false) - tx_validity_interval_default(txt) - tx_certificates(txt, present: false) - end - - it 'Multi-assets transaction' do - amt = 1 - amt_ada = 1_600_000 - address = SHELLEY.addresses.list(@target_id)[1]['id'] - target_before = get_shelley_balances(@target_id) - src_before = get_shared_balances(@wid_sha) - - payment = [{ 'address' => address, - 'amount' => { 'quantity' => amt_ada, 'unit' => 'lovelace' }, - 'assets' => [{ 'policy_id' => ASSETS[0]['policy_id'], - 'asset_name' => ASSETS[0]['asset_name'], - 'quantity' => amt }, - { 'policy_id' => ASSETS[1]['policy_id'], - 'asset_name' => ASSETS[1]['asset_name'], - 'quantity' => amt }] }] - tx_constructed = SHARED.transactions.construct(@wid_sha, payment) - expect(tx_constructed).to be_correct_and_respond 202 - expected_fee = tx_constructed['fee']['quantity'] - - # Can be decoded - tx_decoded = SHARED.transactions.decode(@wid_sha, tx_constructed['transaction']) - expect(tx_decoded).to be_correct_and_respond 202 - - expect(tx_decoded['id'].size).to be 64 - decoded_fee = tx_decoded['fee']['quantity'] - expect(expected_fee).to eq decoded_fee - # inputs are ours - expect(tx_decoded['inputs'].to_s).to include 'address' - expect(tx_decoded['inputs'].to_s).to include 'amount' - expect(tx_decoded['outputs']).not_to eq [] - expect(tx_decoded['script_validity']).to eq 'valid' - expect(tx_decoded['validity_interval']['invalid_before']).to eq({ 'quantity' => 0, 'unit' => 'slot' }) - expect(tx_decoded['validity_interval']['invalid_hereafter']['quantity']).to be > 0 - expect(tx_decoded['collateral']).to eq [] - expect(tx_decoded['collateral_outputs']).to eq [] - expect(tx_decoded['metadata']).to eq nil - expect(tx_decoded['deposits_taken']).to eq [] - expect(tx_decoded['deposits_returned']).to eq [] - expect(tx_decoded['withdrawals']).to eq [] - expect(tx_decoded['mint']).to eq({ 'tokens' => [] }) - expect(tx_decoded['burn']).to eq({ 'tokens' => [] }) - expect(tx_decoded['certificates']).to eq [] - - tx_signed = SHARED.transactions.sign(@wid_sha, PASS, tx_constructed['transaction']) - expect(tx_signed).to be_correct_and_respond 202 - - # ADP-2221 [SharedWallets] FeeTooSmallUTxO when submitting transaction from Shared wallet - tx_submitted = SHARED.transactions.submit(@wid_sha, tx_signed['transaction']) - expect(tx_submitted).to be_correct_and_respond 202 - - tx_id = tx_submitted['id'] - # TODO: ADP-2224: change to wait_for_tx_in_ledger(@wid_sha, tx_id) - eventually "Funds are on target wallet: #{@target_id}" do - available = SHELLEY.wallets.get(@target_id)['balance']['available']['quantity'] - total = SHELLEY.wallets.get(@target_id)['balance']['total']['quantity'] - (available == amt_ada + target_before['available']) && - (total == amt_ada + target_before['total']) - end - - target_after = get_shelley_balances(@target_id) - src_after = get_shared_balances(@wid_sha) - - verify_ada_balance(src_after, src_before, - target_after, target_before, - amt_ada, expected_fee) - - verify_asset_balance(src_after, src_before, - target_after, target_before, - amt) - # tx history - # TODO ADP-2224: check tx history on src wallet - # on target wallet - txt = SHELLEY.transactions.get(@target_id, tx_id) - tx_amount(txt, amt_ada) - tx_fee(txt, 0) - tx_inputs(txt, present: true) - tx_outputs(txt, present: true) - tx_direction(txt, 'incoming') - tx_script_validity(txt, 'valid') - tx_status(txt, 'in_ledger') - tx_collateral(txt, present: false) - tx_collateral_outputs(txt, present: false) - tx_metadata(txt, nil) - tx_deposits(txt, deposit_taken: 0, deposit_returned: 0) - tx_withdrawals(txt, present: false) - tx_mint_burn(txt, mint: [], burn: []) - tx_extra_signatures(txt, present: false) - tx_script_integrity(txt, present: false) - tx_validity_interval_default(txt) - tx_certificates(txt, present: false) - end - - it 'Validity intervals' do - amt = MIN_UTXO_VALUE_PURE_ADA - address = SHELLEY.addresses.list(@target_id)[1]['id'] - target_before = get_shelley_balances(@target_id) - src_before = get_shared_balances(@wid_sha) - inv_before = 500 - inv_hereafter = 5_000_000_000 - validity_interval = { 'invalid_before' => { 'quantity' => inv_before, 'unit' => 'slot' }, - 'invalid_hereafter' => { 'quantity' => inv_hereafter, 'unit' => 'slot' } } - tx_constructed = SHARED.transactions.construct(@wid_sha, - payment_payload(amt, address), - nil, # withdrawal - nil, # metadata - nil, # delegations - nil, # mint_burn - validity_interval) - expect(tx_constructed).to be_correct_and_respond 202 - expected_fee = tx_constructed['fee']['quantity'] - - # Can be decoded - tx_decoded = SHARED.transactions.decode(@wid_sha, tx_constructed['transaction']) - expect(tx_decoded).to be_correct_and_respond 202 - - expect(tx_decoded['id'].size).to be 64 - decoded_fee = tx_decoded['fee']['quantity'] - expect(expected_fee).to eq decoded_fee - # inputs are ours - expect(tx_decoded['inputs'].to_s).to include 'address' - expect(tx_decoded['inputs'].to_s).to include 'amount' - expect(tx_decoded['outputs']).not_to eq [] - expect(tx_decoded['script_validity']).to eq 'valid' - expect(tx_decoded['validity_interval']['invalid_before']).to eq validity_interval['invalid_before'] - expect(tx_decoded['validity_interval']['invalid_hereafter']).to eq validity_interval['invalid_hereafter'] - expect(tx_decoded['collateral']).to eq [] - expect(tx_decoded['collateral_outputs']).to eq [] - expect(tx_decoded['metadata']).to eq nil - expect(tx_decoded['deposits_taken']).to eq [] - expect(tx_decoded['deposits_returned']).to eq [] - expect(tx_decoded['withdrawals']).to eq [] - expect(tx_decoded['mint']).to eq({ 'tokens' => [] }) - expect(tx_decoded['burn']).to eq({ 'tokens' => [] }) - expect(tx_decoded['certificates']).to eq [] - - tx_signed = SHARED.transactions.sign(@wid_sha, PASS, tx_constructed['transaction']) - expect(tx_signed).to be_correct_and_respond 202 - - # ADP-2221 [SharedWallets] FeeTooSmallUTxO when submitting transaction from Shared wallet - tx_submitted = SHARED.transactions.submit(@wid_sha, tx_signed['transaction']) - expect(tx_submitted).to be_correct_and_respond 202 - - tx_id = tx_submitted['id'] - # TODO: ADP-2224: change to wait_for_tx_in_ledger(@wid_sha, tx_id) - eventually "Funds are on target wallet: #{@target_id}" do - available = SHELLEY.wallets.get(@target_id)['balance']['available']['quantity'] - total = SHELLEY.wallets.get(@target_id)['balance']['total']['quantity'] - (available == amt + target_before['available']) && - (total == amt + target_before['total']) - end - - target_after = get_shelley_balances(@target_id) - src_after = get_shared_balances(@wid_sha) - - verify_ada_balance(src_after, src_before, - target_after, target_before, - amt, expected_fee) - # tx history - # TODO ADP-2224: check tx history on src wallet - # on target wallet - txt = SHELLEY.transactions.get(@target_id, tx_id) - tx_amount(txt, amt) - tx_fee(txt, 0) - tx_inputs(txt, present: true) - tx_outputs(txt, present: true) - tx_direction(txt, 'incoming') - tx_script_validity(txt, 'valid') - tx_status(txt, 'in_ledger') - tx_collateral(txt, present: false) - tx_collateral_outputs(txt, present: false) - tx_metadata(txt, nil) - tx_deposits(txt, deposit_taken: 0, deposit_returned: 0) - tx_withdrawals(txt, present: false) - tx_mint_burn(txt, mint: [], burn: []) - tx_extra_signatures(txt, present: false) - tx_script_integrity(txt, present: false) - tx_validity_interval(txt, invalid_before: inv_before, invalid_hereafter: inv_hereafter) - tx_certificates(txt, present: false) - end - - it 'Only metadata (without submitting)' do - # We can submit such tx, but cannot tell when tx is actually in ledger - # (as we cannot get tx history (ADP-2224)) - metadata = METADATA - # balance = get_shared_balances(@wid_sha) - tx_constructed = SHARED.transactions.construct(@wid_sha, - nil, # payments - nil, # withdrawal - metadata) - expect(tx_constructed).to be_correct_and_respond 202 - expected_fee = tx_constructed['fee']['quantity'] - - # Can be decoded - tx_decoded = SHARED.transactions.decode(@wid_sha, tx_constructed['transaction']) - expect(tx_decoded).to be_correct_and_respond 202 - - expect(tx_decoded['id'].size).to be 64 - decoded_fee = tx_decoded['fee']['quantity'] - expect(expected_fee).to eq decoded_fee - # inputs are ours - expect(tx_decoded['inputs'].to_s).to include 'address' - expect(tx_decoded['inputs'].to_s).to include 'amount' - expect(tx_decoded['outputs']).not_to eq [] - expect(tx_decoded['script_validity']).to eq 'valid' - expect(tx_decoded['validity_interval']['invalid_before']).to eq({ 'quantity' => 0, 'unit' => 'slot' }) - expect(tx_decoded['validity_interval']['invalid_hereafter']['quantity']).to be > 0 - expect(tx_decoded['collateral']).to eq [] - expect(tx_decoded['collateral_outputs']).to eq [] - expect(tx_decoded['metadata']).to eq metadata - expect(tx_decoded['deposits_taken']).to eq [] - expect(tx_decoded['deposits_returned']).to eq [] - expect(tx_decoded['withdrawals']).to eq [] - expect(tx_decoded['mint']).to eq({ 'tokens' => [] }) - expect(tx_decoded['burn']).to eq({ 'tokens' => [] }) - expect(tx_decoded['certificates']).to eq [] - - tx_signed = SHARED.transactions.sign(@wid_sha, PASS, tx_constructed['transaction']) - expect(tx_signed).to be_correct_and_respond 202 - - # TODO: ADP-2224: cannot tell when tx is actually in ledger, so this needs - # to be commented for now, because of potential race conditions with subsequent tests - # tx_submitted = SHARED.transactions.submit(@wid_sha, tx_signed["transaction"]) - # expect(tx_submitted).to be_correct_and_respond 202 - # tx_id = tx_submitted['id'] - - # TODO: ADP-2224: change to wait_for_tx_in_ledger(@wid_sha, tx_id) - # TODO ADP-2224: check tx history on src wallet and metadata is there - end - - it 'Delegation (without submitting)' do - # Delegation not yet implemented, only construct and sign in this tc - # balance = get_shared_balances(@wid_sha) - expected_deposit = CARDANO_CLI.protocol_params['stakeAddressDeposit'] - puts "Expected deposit #{expected_deposit}" - - # Pick up pool id to join - pools = SHELLEY.stake_pools - pool_id = pools.list({ stake: 1000 }).sample['id'] - - # Join pool - delegation = [{ - 'join' => { - 'pool' => pool_id, - 'stake_key_index' => '0H' - } - }] - - tx_constructed = SHARED.transactions.construct(@wid_sha, - nil, # payment - nil, # withdrawal - nil, # metadata - delegation, - nil, # mint_burn - nil) # validity_interval - # Check fee and deposit on joining - tx_decoded = SHARED.transactions.decode(@wid_sha, tx_constructed['transaction']) - expect(tx_decoded).to be_correct_and_respond 202 - - # TODO: although you can construct and decode delegation, deposit_taken /deposit_returned are not shown atm - # deposit_taken = tx_constructed['coin_selection']['deposits_taken'].first['quantity'] - # decoded_deposit_taken = tx_decoded['deposits_taken'].first['quantity'] - # expect(deposit_taken).to eq decoded_deposit_taken - # expect(deposit_taken).to eq expected_deposit - - expected_fee = tx_constructed['fee']['quantity'] - decoded_fee = tx_decoded['fee']['quantity'] - expect(decoded_fee).to eq expected_fee - # inputs are ours - expect(tx_decoded['inputs'].to_s).to include 'address' - expect(tx_decoded['inputs'].to_s).to include 'amount' - expect(tx_decoded['outputs']).not_to eq [] - expect(tx_decoded['script_validity']).to eq 'valid' - expect(tx_decoded['validity_interval']['invalid_before']).to eq({ 'quantity' => 0, 'unit' => 'slot' }) - expect(tx_decoded['validity_interval']['invalid_hereafter']['quantity']).to be > 0 - expect(tx_decoded['collateral']).to eq [] - expect(tx_decoded['collateral_outputs']).to eq [] - expect(tx_decoded['metadata']).to eq nil - expect(tx_decoded['deposits_taken']).to eq [] - expect(tx_decoded['deposits_returned']).to eq [] - expect(tx_decoded['withdrawals']).to eq [] - expect(tx_decoded['mint']).to eq({ 'tokens' => [] }) - expect(tx_decoded['burn']).to eq({ 'tokens' => [] }) - expect(tx_decoded['certificates']).to eq [] - - tx_signed = SHARED.transactions.sign(@wid_sha, PASS, tx_constructed['transaction']) - expect(tx_signed).to be_correct_and_respond 202 - end - - describe 'Minting and Burning' do - it 'Can mint and then burn (without submitting)' do - # Minting and Burning not yet implemented, only construct and sign in this tc - # src_before = get_shared_balances(@wid_sha) - policy_script1 = 'cosigner#0' - policy_script2 = { 'all' => ['cosigner#0'] } - policy_script3 = { 'any' => ['cosigner#0'] } - - # Minting: - mint = [mint(asset_name('Token1'), 1000, policy_script1), - mint(asset_name('Token2'), 1000, policy_script2), - mint('', 1000, policy_script3)] - - tx_constructed = SHARED.transactions.construct(@wid_sha, - nil, # payment - nil, # withdrawal - nil, # metadata - nil, # delegation - mint) - expect(tx_constructed).to be_correct_and_respond 202 - - tx_decoded = SHARED.transactions.decode(@wid_sha, tx_constructed['transaction']) - expect(tx_decoded).to be_correct_and_respond 202 - - expected_fee = tx_constructed['fee']['quantity'] - decoded_fee = tx_decoded['fee']['quantity'] - expect(expected_fee).to eq decoded_fee - # inputs are ours - expect(tx_decoded['inputs'].to_s).to include 'address' - expect(tx_decoded['inputs'].to_s).to include 'amount' - expect(tx_decoded['outputs']).not_to eq [] - expect(tx_decoded['script_validity']).to eq 'valid' - expect(tx_decoded['validity_interval']['invalid_before']).to eq({ 'quantity' => 0, 'unit' => 'slot' }) - expect(tx_decoded['validity_interval']['invalid_hereafter']['quantity']).to be > 0 - expect(tx_decoded['collateral']).to eq [] - expect(tx_decoded['collateral_outputs']).to eq [] - expect(tx_decoded['metadata']).to eq nil - expect(tx_decoded['deposits_taken']).to eq [] - expect(tx_decoded['deposits_returned']).to eq [] - expect(tx_decoded['withdrawals']).to eq [] - # TODO: mint / burn currently not decoded - expect(tx_decoded['mint']).to eq({ 'tokens' => [] }) - expect(tx_decoded['burn']).to eq({ 'tokens' => [] }) - expect(tx_decoded['certificates']).to eq [] - - tx_signed = SHARED.transactions.sign(@wid_sha, PASS, tx_constructed['transaction']) - expect(tx_signed).to be_correct_and_respond 202 - end - end - end - - it 'I can receive transaction to shared wallet' do - amt = 1 - amt_ada = 3_000_000 - address = SHARED.addresses.list(@wid_sha)[1]['id'] - target_before = get_shared_balances(@wid_sha) - src_before = get_shelley_balances(@wid) - - payload = [{ 'address' => address, - 'amount' => { 'quantity' => amt_ada, 'unit' => 'lovelace' }, - 'assets' => [{ 'policy_id' => ASSETS[0]['policy_id'], - 'asset_name' => ASSETS[0]['asset_name'], - 'quantity' => amt }, - { 'policy_id' => ASSETS[1]['policy_id'], - 'asset_name' => ASSETS[1]['asset_name'], - 'quantity' => amt }] }] - - tx_sent = SHELLEY.transactions.create(@wid, PASS, payload) - - expect(tx_sent).to be_correct_and_respond 202 - expect(tx_sent.to_s).to include 'pending' - wait_for_tx_in_ledger(@wid, tx_sent['id']) - - target_after = get_shared_balances(@wid_sha) - src_after = get_shelley_balances(@wid) - fee = SHELLEY.transactions.get(@wid, tx_sent['id'])['fee']['quantity'] - - verify_ada_balance(src_after, src_before, - target_after, target_before, - amt_ada, fee) - - verify_asset_balance(src_after, src_before, - target_after, target_before, - amt) - end - end - describe 'E2E Shelley' do describe 'Native Assets' do it 'I can list native assets' do @@ -3383,7 +2828,7 @@ def fingerprint describe 'Update passphrase' do it 'I can update passphrase with mnemonic and the wallet does not have to re-sync' do - mnemonics = get_fixture_wallet_mnemonics(:fixture, :shelley) + mnemonics = get_fixture_wallet(:fixture, :shelley, :mnemonics) upd = SHELLEY.wallets.update_passphrase(@wid, { mnemonic_sentence: mnemonics, new_passphrase: PASS }) expect(upd).to be_correct_and_respond 204 diff --git a/test/e2e/spec/spec_helper.rb b/test/e2e/spec/spec_helper.rb index 544b2f76e58..f30d489321d 100644 --- a/test/e2e/spec/spec_helper.rb +++ b/test/e2e/spec/spec_helper.rb @@ -131,6 +131,11 @@ def create_incomplete_shared_wallet(m, acc_ix, acc_xpub) WalletFactory.create(:shared, payload)['id'] end +def shared_acc_pubkey(wallet_id) + key_bech32 = SHARED.keys.get_acc_public_key(wallet_id, { format: 'extended' }).parsed_response.delete_prefix('"').delete_suffix('"') + bech32_to_base16(key_bech32) +end + def patch_incomplete_shared_wallet(wid, payment_patch, deleg_patch) if payment_patch p_upd = SHARED.wallets.update_payment_script(wid, @@ -147,6 +152,34 @@ def patch_incomplete_shared_wallet(wid, payment_patch, deleg_patch) expect(d_upd).to be_correct_and_respond 200 end +def patch_if_incomplete(wid, payment_patch, deleg_patch) + if payment_patch + p_upd = SHARED.wallets.update_payment_script(wid, + payment_patch.keys.first, + payment_patch.values.first) + case p_upd.code + when 200 + expect(p_upd).to be_correct_and_respond 200 + when 403 + expect(p_upd).to be_correct_and_respond 403 + expect(p_upd.parsed_response['code']).to eq 'shared_wallet_not_pending' + end + end + + return unless deleg_patch + + d_upd = SHARED.wallets.update_delegation_script(wid, + deleg_patch.keys.first, + deleg_patch.values.first) + case d_upd.code + when 200 + expect(d_upd).to be_correct_and_respond 200 + when 403 + expect(d_upd).to be_correct_and_respond 403 + expect(d_upd.parsed_response['code']).to eq 'shared_wallet_not_pending' + end +end + def create_active_shared_wallet(m, acc_ix, acc_xpub) script_template = { 'cosigners' => { 'cosigner#0' => acc_xpub }, @@ -280,23 +313,54 @@ def return_wallet_id(create_wallet_response) ## # create fixture wallet or return it's id if it exists -# @param type [Symbol] :shelley, :shelley_light, :random, :icarus -def create_fixture_wallet(type) - payload = { name: 'Fixture wallet with funds', +# @param type [Symbol] :shelley, :shared, :shared_cosigner_0, :shared_cosigner_1, :random, :icarus +# @param templates [Symbols] ':payment_cosigner{0,1}_{all,any,all0}', :delegation_cosigner{0,1}_{all,any,all0} +# rubocop:disable Metrics/CyclomaticComplexity +def create_fixture_wallet(type, *templates) + payload = { name: "Fixture wallet with funds (#{type}#{" #{templates}" unless templates.empty?}", passphrase: PASS, - mnemonic_sentence: get_fixture_wallet_mnemonics(:fixture, type.to_sym) } + mnemonic_sentence: get_fixture_wallet(:fixture, type.to_sym, :mnemonics) } case type.to_sym - when :shelley, :shelley_light + when :shelley wallet = SHELLEY.wallets.create(payload) return_wallet_id(wallet) when :random, :icarus payload[:style] = type wallet = BYRON.wallets.create(payload) return_wallet_id(wallet) + when :shared, :shared2 + templates.each do |t| + case t + when :payment_cosigner0_all + payload[:payment_script_template] = { 'cosigners' => { 'cosigner#0' => 'self' }, 'template' => { 'all' => ['cosigner#0', 'cosigner#1'] } } + when :delegation_cosigner0_all + payload[:delegation_script_template] = { 'cosigners' => { 'cosigner#0' => 'self' }, 'template' => { 'all' => ['cosigner#0', 'cosigner#1'] } } + when :payment_cosigner1_all + payload[:payment_script_template] = { 'cosigners' => { 'cosigner#1' => 'self' }, 'template' => { 'all' => ['cosigner#0', 'cosigner#1'] } } + when :delegation_cosigner1_all + payload[:delegation_script_template] = { 'cosigners' => { 'cosigner#1' => 'self' }, 'template' => { 'all' => ['cosigner#0', 'cosigner#1'] } } + when :payment_cosigner0_any + payload[:payment_script_template] = { 'cosigners' => { 'cosigner#0' => 'self' }, 'template' => { 'any' => ['cosigner#0', 'cosigner#1'] } } + when :delegation_cosigner0_any + payload[:delegation_script_template] = { 'cosigners' => { 'cosigner#0' => 'self' }, 'template' => { 'any' => ['cosigner#0', 'cosigner#1'] } } + when :payment_cosigner1_any + payload[:payment_script_template] = { 'cosigners' => { 'cosigner#1' => 'self' }, 'template' => { 'any' => ['cosigner#0', 'cosigner#1'] } } + when :delegation_cosigner1_any + payload[:delegation_script_template] = { 'cosigners' => { 'cosigner#1' => 'self' }, 'template' => { 'any' => ['cosigner#0', 'cosigner#1'] } } + when :payment_cosigner0_all0 + payload[:payment_script_template] = { 'cosigners' => { 'cosigner#0' => 'self' }, 'template' => { 'all' => ['cosigner#0'] } } + when :delegation_cosigner0_all0 + payload[:delegation_script_template] = { 'cosigners' => { 'cosigner#0' => 'self' }, 'template' => { 'all' => ['cosigner#0'] } } + end + end + payload[:account_index] = '0H' + wallet = SHARED.wallets.create(payload) + return_wallet_id(wallet) else raise "Unsupported wallet type: #{type}" end end +# rubocop:enable Metrics/CyclomaticComplexity ## # create target wallet or return it's id if it exists @@ -304,22 +368,11 @@ def create_fixture_wallet(type) def create_target_wallet(type) payload = { name: 'Target wallet for txs', passphrase: PASS, - mnemonic_sentence: get_fixture_wallet_mnemonics(:target, type.to_sym) } + mnemonic_sentence: get_fixture_wallet(:target, type.to_sym, :mnemonics) } case type.to_sym when :shelley wallet = SHELLEY.wallets.create(payload) return_wallet_id(wallet) - when :shared - script_template = { 'cosigners' => - { 'cosigner#0' => 'self' }, - 'template' => - { 'all' => - ['cosigner#0'] } } - payload[:account_index] = '0H' - payload[:payment_script_template] = script_template - payload[:delegation_script_template] = script_template - wallet = SHARED.wallets.create(payload) - return_wallet_id(wallet) else raise "Unsupported wallet type: #{type}" end @@ -449,9 +502,9 @@ def verify_asset_balance(src_after, src_before, target_after, target_before, amt expect(src_avail_after).to eq src_avail_expected end -def wait_for_tx_in_ledger(wid, tx_id) +def wait_for_tx_in_ledger(wid, tx_id, wallet_api = SHELLEY) eventually "Tx #{tx_id} is in ledger" do - tx = SHELLEY.transactions.get(wid, tx_id) + tx = wallet_api.transactions.get(wid, tx_id) tx.code == 200 && tx['status'] == 'in_ledger' end end