View on GitHub
File Changes
      if (shouldSendAll) {
        unsignedTxResponse = environment.isShelley()
          ? shelleySendAllUnsignedTx(
-
            receiver,
+
            Buffer.from(
+
              RustModule.WalletV3.Address.from_string(receiver).as_bytes()
+
            ).toString('hex'),
            addressedUtxo
          )
          : byronSendAllUnsignedTx(
        const changeAddr = nextUnusedInternal.addressInfo;
        unsignedTxResponse = environment.isShelley()
          ? shelleyNewAdaUnsignedTx(
-
            receiver,
+
            Buffer.from(
+
              RustModule.WalletV3.Address.from_string(receiver).as_bytes()
+
            ).toString('hex'),
            amount,
            [{
              address: changeAddr.addr.Hash,

                      
import type { CoreAddressT } from '../database/primitives/enums';
import { CoreAddressTypes } from '../database/primitives/enums';
+
import { Bech32Prefix } from '../../../../../config/stringConfig';
import { RustModule } from '../../cardanoCrypto/rustLoader';

                      
export function addressToKind(
    }
  }
}
+

                      
+
export function addressToDisplayString(
+
  address: string
+
): string {
+
  try {
+
    // Need to try parsing as a legacy address first
+
    // Since parsing as bech32 directly may give a wrong result if the address contains a 1
+
    RustModule.WalletV2.Address.from_base58(address);
+
    return address;
+
  } catch (_e1) {
+
    try {
+
      const wasmAddr = RustModule.WalletV3.Address.from_bytes(
+
        Buffer.from(address, 'hex')
+
      );
+
      return wasmAddr.to_string(Bech32Prefix.ADDRESS);
+
    } catch (_e2) {
+
      throw new Error('addressToKind failed to parse address type ' + address);
+
    }
+
  }
+
}

                      
    const unsignedTxResponse = buildUnsignedAccountTx(
      senderKey.to_public(),
-
      'ca1qw8mq0p65pf028qgd32t6szeatfd9epx4jyl5jeuuswtlkyqpdguqeh83d4',
+
      Buffer.from(RustModule.WalletV3.Address.from_string(
+
        'ca1qw8mq0p65pf028qgd32t6szeatfd9epx4jyl5jeuuswtlkyqpdguqeh83d4'
+
      ).as_bytes()).toString('hex'),
      {
        amount: new BigNumber(2000000)
      },

                      
    expect(() => buildUnsignedAccountTx(
      senderKey.to_public(),
-
      'ca1qw8mq0p65pf028qgd32t6szeatfd9epx4jyl5jeuuswtlkyqpdguqeh83d4',
+
      Buffer.from(RustModule.WalletV3.Address.from_string(
+
        'ca1qw8mq0p65pf028qgd32t6szeatfd9epx4jyl5jeuuswtlkyqpdguqeh83d4'
+
      ).as_bytes()).toString('hex'),
      {
        amount: new BigNumber(2000000),
      },

                      
    expect(() => buildUnsignedAccountTx(
      senderKey.to_public(),
-
      'ca1qw8mq0p65pf028qgd32t6szeatfd9epx4jyl5jeuuswtlkyqpdguqeh83d4',
+
      Buffer.from(RustModule.WalletV3.Address.from_string(
+
        'ca1qw8mq0p65pf028qgd32t6szeatfd9epx4jyl5jeuuswtlkyqpdguqeh83d4'
+
      ).as_bytes()).toString('hex'),
      {
        amount: new BigNumber(2000000),
      },
  typeSpecific: SendType,
  accountBalance: BigNumber,
): RustModule.WalletV3.InputOutput {
+
  const wasmReceiver = RustModule.WalletV3.Address.from_bytes(
+
    Buffer.from(receiver, 'hex')
+
  );
  if (typeSpecific.amount != null && typeSpecific.amount.gt(accountBalance)) {
    throw new NotEnoughMoneyToSendError();
  }

                      
    if (typeSpecific.amount != null) {
      fakeTxBuilder.add_output(
-
        RustModule.WalletV3.Address.from_string(receiver),
+
        wasmReceiver,
        // the value we put in here is irrelevant. Just need some value to be able to calculate fee
        RustModule.WalletV3.Value.from_str('1')
      );
  if (typeSpecific.amount != null) {
    const value = RustModule.WalletV3.Value.from_str(typeSpecific.amount.toString());
    ioBuilder.add_output(
-
      RustModule.WalletV3.Address.from_string(receiver),
+
      wasmReceiver,
      value
    );
  }
  stringifyError,
} from '../../../../utils/logging';
import { LOVELACES_PER_ADA } from '../../../../config/numbersConfig';
+
import { Bech32Prefix } from '../../../../config/stringConfig';
import {
  GenerateTransferTxError
} from '../../errors';
      fee: fee.dividedBy(LOVELACES_PER_ADA),
      id: Buffer.from(fragment.id().as_bytes()).toString('hex'),
      encodedTx: fragment.as_bytes(),
+
      // recall: Daedalus addresses all have to be legacy so we don't turn them to bech32
      senders: Object.keys(addressKeys),
-
      receiver: outputAddr,
+
      receiver: RustModule.WalletV3.Address.from_bytes(
+
        Buffer.from(outputAddr, 'hex')
+
      ).to_string(Bech32Prefix.ADDRESS)
    };
  } catch (error) {
    Logger.error(`daedalusTransfer::buildTransferTx ${stringifyError(error)}`);
      fakeIOBuilder.add_input(input);
    }
    fakeIOBuilder.add_output(
-
      RustModule.WalletV3.Address.from_string(receiver),
+
      RustModule.WalletV3.Address.from_bytes(
+
        Buffer.from(receiver, 'hex')
+
      ),
      RustModule.WalletV3.Value.from_str(totalBalance.toString())
    );
    const feeValue = fakeIOBuilder.estimate_fee(

                      
  const ioBuilder = RustModule.WalletV3.InputOutputBuilder.empty();
  ioBuilder.add_output(
-
    RustModule.WalletV3.Address.from_string(receiver),
+
    RustModule.WalletV3.Address.from_bytes(
+
      Buffer.from(receiver, 'hex')
+
    ),
    RustModule.WalletV3.Value.from_str(amount)
  );
  const payload = certificate != null
      payload,
      feeAlgorithm,
      RustModule.WalletV3.OutputPolicy.one(
-
        RustModule.WalletV3.Address.from_string(changeAddr.address)
+
        RustModule.WalletV3.Address.from_bytes(
+
          Buffer.from(changeAddr.address, 'hex')
+
        )
      )
    );
    const addedChange = filterToUsedChange(
  const possibleDuplicates = selectedUtxos.filter(utxo => utxo.receiver === changeAddr.address);

                      
  const change = [];
-
  const changeAddrWasm = RustModule.WalletV3.Address.from_string(changeAddr.address);
+
  const changeAddrWasm = RustModule.WalletV3.Address.from_bytes(
+
    Buffer.from(changeAddr.address, 'hex')
+
  );
  const changeAddrPayload = Buffer.from(changeAddrWasm.as_bytes()).toString('hex');
  for (let i = 0; i < outputs.size(); i++) {
    const output = outputs.get(i);
const keys = [
  {
    legacyAddress: 'Ae2tdPwUPEZKX8N2TjzBXLy5qrecnQUniTd2yxE8mWyrh2djNpUkbAtXtP4',
-
    bechAddress: 'ca1qw8mq0p65pf028qgd32t6szeatfd9epx4jyl5jeuuswtlkyqpdguqeh83d4',
+
    // ca1qw8mq0p65pf028qgd32t6szeatfd9epx4jyl5jeuuswtlkyqpdguqeh83d4
+
    bechAddress: '038fb03c3aa052f51c086c54bd4059ead2d2e426ac89fa4b3ce41cbfd8800b51c0',
    pubKey: '8fb03c3aa052f51c086c54bd4059ead2d2e426ac89fa4b3ce41cbfd8800b51c02623fceb96b07408531a5cb259f53845a38d6b68928e7c0c7e390f07545d0e62',
  },
  {
    legacyAddress: 'Ae2tdPwUPEZ4xAL3nxLq4Py7BfS1D2tJ3u2rxZGnrAXC8TNkWhTaz41J3FN',
-
    bechAddress: 'ca1q0j6cetm7zqsagm5zz5fmav9jg37n4cferj23h370kptrpfj095fxcy43lj',
+
    // ca1q0j6cetm7zqsagm5zz5fmav9jg37n4cferj23h370kptrpfj095fxcy43lj
+
    bechAddress: '03e5ac657bf0810ea37410a89df5859223e9d709c8e4a8de3e7d82b18532796893',
    pubKey: 'e5ac657bf0810ea37410a89df5859223e9d709c8e4a8de3e7d82b185327968939a254def91bb75e94bda9c605f7f87481082742e1e51d8858965c9a40491fc94',
  },
  {
    legacyAddress: 'Ae2tdPwUPEZEtwz7LKtJn9ub8y7ireuj3sq2yUCZ57ccj6ZkJKn7xEiApV9',
-
    bechAddress: 'ca1q0ewtxsk489t9g7vs64prkm0hfvz6aemtvtv57rkfwmxyp3yhtxtwhtm3gd',
+
    // ca1q0ewtxsk489t9g7vs64prkm0hfvz6aemtvtv57rkfwmxyp3yhtxtwhtm3gd
+
    bechAddress: '03f2e59a16a9cab2a3cc86aa11db6fba582d773b5b16ca78764bb6620624baccb7',
    pubKey: 'f2e59a16a9cab2a3cc86aa11db6fba582d773b5b16ca78764bb6620624baccb7c03adf6448459f2b8d5c32033a160de8b5412d1952794190c4fc6b4716a8b8eb',
  }
];

                      
const sampleAdaAddresses: Array<{| ...Address, ...Addressing |}> = [
  {
-
    address: 'ca1q0ewtxsk489t9g7vs64prkm0hfvz6aemtvtv57rkfwmxyp3yhtxtwhtm3gd',
+
    // ca1q0ewtxsk489t9g7vs64prkm0hfvz6aemtvtv57rkfwmxyp3yhtxtwhtm3gd
+
    address: '03f2e59a16a9cab2a3cc86aa11db6fba582d773b5b16ca78764bb6620624baccb7',
    addressing: {
      path: [1, 11],
      startLevel: Bip44DerivationLevels.CHAIN.level,

                      
  it('Transaction with a certificate is also valid', () => {
    const unsignedTxResponse = newAdaUnsignedTx(
-
      'ca1sw8mq0p65pf028qgd32t6szeatfd9epx4jyl5jeuuswtlkyqpdguq9rance',
+
      Buffer.from(RustModule.WalletV3.Address.from_string(
+
        'ca1sw8mq0p65pf028qgd32t6szeatfd9epx4jyl5jeuuswtlkyqpdguq9rance'
+
      ).as_bytes()).toString('hex'),
      '5000', // smaller than input
      [{
-
        address: 'addr1s5quq8utjkrfntnkngjxa9u9mdd8pcprjal2fwzkm7k0y0prx3k276qm0j8',
+
        address: Buffer.from(RustModule.WalletV3.Address.from_string(
+
          'addr1s5quq8utjkrfntnkngjxa9u9mdd8pcprjal2fwzkm7k0y0prx3k276qm0j8'
+
        ).as_bytes()).toString('hex'),
        addressing: {
          path: [1, 0],
          startLevel: Bip44DerivationLevels.CHAIN.level,
        },
      }],
      [{
        amount: '2000000',
-
        receiver: 'ca1ssuvzjs82mshgvyp4r4lmwgknvgjswnm7mpcq3wycjj7v2nk393e6qwqr79etp5e4emf5frwj7zakknsuq3ewl4yhptdlt8j8s3ngm906x2vwl',
+
        receiver: Buffer.from(RustModule.WalletV3.Address.from_string(
+
          'ca1ssuvzjs82mshgvyp4r4lmwgknvgjswnm7mpcq3wycjj7v2nk393e6qwqr79etp5e4emf5frwj7zakknsuq3ewl4yhptdlt8j8s3ngm906x2vwl'
+
        ).as_bytes()).toString('hex'),
        tx_hash: '86e36b6a65d82c9dcc0370b0ee3953aee579db0b837753306405c28a74de5550',
        tx_index: 0,
        utxo_id: '86e36b6a65d82c9dcc0370b0ee3953aee579db0b837753306405c28a74de55500',
  stringifyError,
} from '../../../../utils/logging';
import { LOVELACES_PER_ADA } from '../../../../config/numbersConfig';
+
import { Bech32Prefix } from '../../../../config/stringConfig';
+
import { addressToDisplayString } from '../../lib/storage/bridge/utils';
import {
  GenerateTransferTxError
} from '../../errors';
      true,
    );

                      
+
    const uniqueSenders = Array.from(new Set(senderUtxos.map(utxo => utxo.receiver)));
+

                      
    // return summary of transaction
    return {
      recoveredBalance: totalBalance.dividedBy(LOVELACES_PER_ADA),
      fee: fee.dividedBy(LOVELACES_PER_ADA),
      id: Buffer.from(fragment.id().as_bytes()).toString('hex'),
      encodedTx: fragment.as_bytes(),
-
      // only display unique addresses
-
      senders: Array.from(new Set(senderUtxos.map(utxo => utxo.receiver))),
-
      receiver: outputAddr,
+
      // recall: some addresses may be legacy, some may be Shelley
+
      senders: uniqueSenders.map(addr => addressToDisplayString(addr)),
+
      receiver: RustModule.WalletV3.Address.from_bytes(
+
        Buffer.from(outputAddr, 'hex')
+
      ).to_string(Bech32Prefix.ADDRESS)
    };
  } catch (error) {
    Logger.error(`transfer::buildTransferTx ${stringifyError(error)}`);
    const txId = '915f2e6865fb31cc93410efb6c0e580ca74862374b3da461e20135c01f312e7c';
    const inputAmount = '1000000';
    const txIndex = 0;
-
    const outAddress = RustModule.WalletV3.Address.from_bytes(
-
      Buffer.from('038e2840fed90d2138761d8a14a4cbed08ed00cf908b07f94ec5fa9db6f4d7e74f', 'hex')
-
    ).to_string('addr');
+
    const bech32Addr = 'addr1qw8zss87myxjzwrkrk9pffxta5yw6qx0jz9s072wchafmdh56ln5704fx9z';
+
    const outAddress = Buffer.from(RustModule.WalletV3.Address.from_string(
+
      bech32Addr
+
    ).as_bytes()).toString('hex');

                      
    const daedalusWallet = getCryptoDaedalusWalletFromMnemonics(words);
    const checker = RustModule.WalletV2.DaedalusAddressChecker.new(daedalusWallet);
    expect(transferInfo.fee.toString()).toBe('0.155383');
    expect(transferInfo.recoveredBalance.toString()).toBe('1');
    expect(transferInfo.senders).toEqual([address]);
-
    expect(transferInfo.receiver).toBe(outAddress);
+
    expect(transferInfo.receiver).toBe(bech32Addr);

                      
    // check tx itself
    const fragment = RustModule.WalletV3.Fragment.from_bytes(transferInfo.encodedTx);
    const outputs = signedTx.outputs();
    expect(outputs.size()).toEqual(1);
    const output = outputs.get(0);
-
    expect(output.address().to_string('addr')).toEqual(outAddress);
+
    expect(output.address().to_string('addr')).toEqual(bech32Addr);
    expect(output.value().to_str()).toEqual('844617');

                      
    const witnesses = signedTx.witnesses();
    const txId = '915f2e6865fb31cc93410efb6c0e580ca74862374b3da461e20135c01f312e7c';
    const inputAmount = '1000';
    const txIndex = 0;
-
    const outAddress = RustModule.WalletV3.Address.from_bytes(
-
      Buffer.from('038e2840fed90d2138761d8a14a4cbed08ed00cf908b07f94ec5fa9db6f4d7e74f', 'hex')
-
    ).to_string('addr');
+
    const outAddress = '038e2840fed90d2138761d8a14a4cbed08ed00cf908b07f94ec5fa9db6f4d7e74f';

                      
    const daedalusWallet = getCryptoDaedalusWalletFromMnemonics(words);
    const checker = RustModule.WalletV2.DaedalusAddressChecker.new(daedalusWallet);
    const txId = '915f2e6865fb31cc93410efb6c0e580ca74862374b3da461e20135c01f312e7c';
    const inputAmount = '1000001';
    const txIndex = 0;
-
    const outAddress = RustModule.WalletV3.Address.from_bytes(
-
      Buffer.from('038e2840fed90d2138761d8a14a4cbed08ed00cf908b07f94ec5fa9db6f4d7e74f', 'hex')
-
    ).to_string('addr');
+
    const bech32Addr = 'addr1qw8zss87myxjzwrkrk9pffxta5yw6qx0jz9s072wchafmdh56ln5704fx9z';
+
    const outAddress = Buffer.from(RustModule.WalletV3.Address.from_string(
+
      bech32Addr
+
    ).as_bytes()).toString('hex');

                      
    const daedalusWallet = getCryptoDaedalusWalletFromMnemonics(words);
    const checker = RustModule.WalletV2.DaedalusAddressChecker.new(daedalusWallet);
    expect(transferInfo.fee.toString()).toBe('0.155482');
    expect(transferInfo.recoveredBalance.toString()).toBe('100.0001');
    expect(transferInfo.senders).toEqual([address]);
-
    expect(transferInfo.receiver).toBe(outAddress);
+
    expect(transferInfo.receiver).toBe(bech32Addr);

                      
    // check tx itself
    const fragment = RustModule.WalletV3.Fragment.from_bytes(transferInfo.encodedTx);
    const outputs = signedTx.outputs();
    expect(outputs.size()).toEqual(1);
    const output = outputs.get(0);
-
    expect(output.address().to_string('addr')).toEqual(outAddress);
+
    expect(output.address().to_string('addr')).toEqual(bech32Addr);
    expect(output.value().to_str()).toEqual('99844618');

                      
    const witnesses = signedTx.witnesses();
import {
  ChainDerivations,
} from '../../../../config/numbersConfig';
+
import { Bech32Prefix } from '../../../../config/stringConfig';

                      
import {
  loadLovefieldDB,
    RustModule.WalletV3.AddressDiscrimination.Production
  );
  return {
-
    address: addr.to_string('addr'),
+
    address: Buffer.from(addr.as_bytes()).toString('hex'),
    addressing: {
      path: [ChainDerivations.EXTERNAL, derivationId],
      startLevel: Bip44DerivationLevels.CHAIN.level,
    const txId = '915f2e6865fb31cc93410efb6c0e580ca74862374b3da461e20135c01f312e7c';
    const inputAmount = '1000000';
    const txIndex = 0;
-
    const outAddress = RustModule.WalletV3.Address.from_bytes(
-
      Buffer.from('038e2840fed90d2138761d8a14a4cbed08ed00cf908b07f94ec5fa9db6f4d7e74f', 'hex')
-
    ).to_string('addr');
+
    const bech32Addr = 'addr1qw8zss87myxjzwrkrk9pffxta5yw6qx0jz9s072wchafmdh56ln5704fx9z';
+
    const outAddress = Buffer.from(RustModule.WalletV3.Address.from_string(
+
      bech32Addr
+
    ).as_bytes()).toString('hex');

                      
    const accountPrivateKey = RustModule.WalletV3.Bip32PrivateKey.from_bytes(
      Buffer.from(

                      
    expect(transferInfo.fee.toString()).toBe('0.155383');
    expect(transferInfo.recoveredBalance.toString()).toBe('1');
-
    expect(transferInfo.senders).toEqual([addr1.address]);
-
    expect(transferInfo.receiver).toBe(outAddress);
+
    expect(transferInfo.senders).toEqual([
+
      RustModule.WalletV3.Address.from_bytes(
+
        Buffer.from(addr1.address, 'hex')
+
      ).to_string(Bech32Prefix.ADDRESS)
+
    ]);
+
    expect(transferInfo.receiver).toBe(bech32Addr);

                      
    // check tx itself
    const fragment = RustModule.WalletV3.Fragment.from_bytes(transferInfo.encodedTx);
    const outputs = signedTx.outputs();
    expect(outputs.size()).toEqual(1);
    const output = outputs.get(0);
-
    expect(output.address().to_string('addr')).toEqual(outAddress);
+
    expect(output.address().to_string('addr')).toEqual(bech32Addr);
    expect(output.value().to_str()).toEqual('844617');

                      
    const witnesses = signedTx.witnesses();
    "txsBodiesRequestSize": 150
  },
  "genesis": {
-
    "block0_date": 0,
-
    "slots_per_epoch": 21600,
-
    "slot_duration": 20,
+
    "block0_date": 1575295549000,
+
    "slots_per_epoch": 5000,
+
    "slot_duration": 10,
    "linearFee": {
-
      "constant": "2",
-
      "coefficient": "1",
-
      "certificate": "4"
+
      "constant": "10",
+
      "coefficient": "0",
+
      "certificate": "0"
    },
-
    "genesisHash": "todo"
+
    "genesisHash": "4d8b8ff16ce86f9436ac7c4b5ce454f3aaa3477c43b360c0646a258ab230b83e"
  }
}