Giter VIP home page Giter VIP logo

cardanosharp-wallet's People

Contributors

daniel-schaeferj avatar eddex avatar lilpaul avatar mercurial avatar nicholasmaselli avatar nothingalike avatar pszeder avatar safestak-keith avatar sarmaad avatar tweakch avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cardanosharp-wallet's Issues

Using paymentPub and paymentPrv key values as VKey and SKey values throws System.ArgumentException in Chaos.NaCl.Ed26519.Sign during witness creation

Following the readme assigned to this project, the witness creation process states the following...

new VKeyWitness() { VKey = paymentPub.Key, SKey = paymentPrv.Key }

However, reviewing the documentation on the following page...
developers.cardano.org
shows the following...

new VKeyWitness() { VKey = paymentPub, SKey = paymentPrv }

The original Github readme gives the impression that you should be able to pass the publicKey.key and privateKey.key values for VKey and SKey, however, the developer.cardano.org link gives the impression that you need to pass the chaincode as well and generate the Tuple assigning them to the VKey and SKey values.

Can you clarify?

How to differentiate Testenet from Mainnet?

When using the C# SDK. They can help where we can insert in the code the creation of addresses for Testenet and Mainnet. And any transaction or functionality. From what I've seen it only works on Node Mainnet. Correct?

thanks

Address constructor input validation

When creating a new Address object, the public Address(string address) constructor only checks if the address is not null or whitespace. It seems that parsing and validation is implemented in Bech32.Decode(...) which is called within a try-catch block.

As a result, we can have Address objects that are invalid and do not represent any Cardano address. Furthermore, no exceptions are thrown when creating a transaction using such an invalid Address.

The generated CBOR will have null for the address field when used as an output. That is actually not a valid CBOR as per the specification and will likely result in an invalid CBOR/input exception when used with other software - Nami wallet in our case.

I would suggest that an Address should only be constructed if it is valid. That would be 'fail fast' and save people time and headaches.

CborObject.GetTransaction: requiredSigners are not deserialized correctly

When creating a transaction via the Cardano Serialization Lib which contains one or more additional required signers, these are not correctly parsed when deserializing the CBOR via CardanoSharp.Wallet.

However, when the same transaction is build via the Cardano Serialization Lib without the additional required signers, everything works as expected.

Example (not working as expected, with required signers)

Having the following CBOR constructed by the CSL containing required signers set via CSL's method add_required_signer:

84a700818258207043c6744f9c699e2e5f43df08ffc3dbb259a89383a4023d133cc3b8bc5b5bae0101838258390005acdfa65952ac8a7b0cf168d4912535b117f5998967ee742644dcc405bc59d947656b4167d84497085d372b58f74b2057c8c542a11c22be1a001e848082583900c010c94c93bbe65283293a9946719b9277b325a0ab07e787b78572bac151e09314abc3031eae0f450ac4f3bbac851b9947ab4651433d47a81a003d0900825839001bcb60012703fcb4d6c97f1a177163e1797133b859a2b4feed0635657bcba45a50d5547e72cbad7a330c051a14b410a08dca551ed40e998d821a0048d9a3a1581c373b7956817434b15b87717075359307b1f1f6911ee03c4cb2004eb3a1581c6f636361656361746943686965664d6f62696c6974794f726368657301021a0003719d031a00bc177f0758206d600030ef909d098d217e07f0f34efee88a9b67740ad747a2833ec06cb091ae09a1581c373b7956817434b15b87717075359307b1f1f6911ee03c4cb2004eb3a1581c6f636361656361746943686965664d6f62696c6974794f7263686573010e82581c25ab8e56be62c4bf8a22db139f2c6a90793d21c17b99b9aaebf5f5f2581c20763045c339d6f996e02a0a81ca5f41aa3898e964fd3206caf12f75a101818201818200581c20763045c339d6f996e02a0a81ca5f41aa3898e964fd3206caf12f75f5f6

When this CBOR is deserialized by this library into an instance of Transaction and then serialized back to CBOR, the resulting CBOR is not identical to the one created by the CSL:

Code to deserialize/serialize:

var cborToSign = "84a7008182...2f75f5f6";
var cbor = CBORObject.DecodeFromBytes(Convert.FromHexString(cborToSign), new CBOREncodeOptions("keepkeyorder=true"));

var transaction = cbor.GetTransaction();

var cborOut = Convert.ToHexString(transaction.GetCBOR().EncodeToBytes()).ToLowerInvariant();

The CBOR constructed by this library after deserialization/serialization is different than the original CSL cbor most likely lacking the required signers being deserialized.

84a600818258207043c6744f9c699e2e5f43df08ffc3dbb259a89383a4023d133cc3b8bc5b5bae0101838258390005acdfa65952ac8a7b0cf168d4912535b117f5998967ee742644dcc405bc59d947656b4167d84497085d372b58f74b2057c8c542a11c22be1a001e848082583900c010c94c93bbe65283293a9946719b9277b325a0ab07e787b78572bac151e09314abc3031eae0f450ac4f3bbac851b9947ab4651433d47a81a003d0900825839001bcb60012703fcb4d6c97f1a177163e1797133b859a2b4feed0635657bcba45a50d5547e72cbad7a330c051a14b410a08dca551ed40e998d821a0048d9a3a1581c373b7956817434b15b87717075359307b1f1f6911ee03c4cb2004eb3a1581c6f636361656361746943686965664d6f62696c6974794f726368657301021a0003719d031a00bc177f0758206d600030ef909d098d217e07f0f34efee88a9b67740ad747a2833ec06cb091ae09a1581c373b7956817434b15b87717075359307b1f1f6911ee03c4cb2004eb3a1581c6f636361656361746943686965664d6f62696c6974794f726368657301a101818201818200581c20763045c339d6f996e02a0a81ca5f41aa3898e964fd3206caf12f75f5f6

Example (working as expected, no required signers)

When the CBOR constructed by the CSL does not contain additional required signers, everything works as expected.

Original CSL CBOR:

84a600818258207043c6744f9c699e2e5f43df08ffc3dbb259a89383a4023d133cc3b8bc5b5bae0101838258390005acdfa65952ac8a7b0cf168d4912535b117f5998967ee742644dcc405bc59d947656b4167d84497085d372b58f74b2057c8c542a11c22be1a001e848082583900c010c94c93bbe65283293a9946719b9277b325a0ab07e787b78572bac151e09314abc3031eae0f450ac4f3bbac851b9947ab4651433d47a81a003d0900825839001bcb60012703fcb4d6c97f1a177163e1797133b859a2b4feed0635657bcba45a50d5547e72cbad7a330c051a14b410a08dca551ed40e998d821a0048ea23a1581c373b7956817434b15b87717075359307b1f1f6911ee03c4cb2004eb3a1581c6f6d6e697350726f647563745365637572697479526570726573656e01021a0003611d031a00bc1a200758200a175108e98a082f86696662c3cbf4ea588edf60a09831ccc0be04279de4886d09a1581c373b7956817434b15b87717075359307b1f1f6911ee03c4cb2004eb3a1581c6f6d6e697350726f647563745365637572697479526570726573656e01a101818201818200581c20763045c339d6f996e02a0a81ca5f41aa3898e964fd3206caf12f75f5f6

Deserialized => Serialized CBOR via this library (identical to the original one):

84a600818258207043c6744f9c699e2e5f43df08ffc3dbb259a89383a4023d133cc3b8bc5b5bae0101838258390005acdfa65952ac8a7b0cf168d4912535b117f5998967ee742644dcc405bc59d947656b4167d84497085d372b58f74b2057c8c542a11c22be1a001e848082583900c010c94c93bbe65283293a9946719b9277b325a0ab07e787b78572bac151e09314abc3031eae0f450ac4f3bbac851b9947ab4651433d47a81a003d0900825839001bcb60012703fcb4d6c97f1a177163e1797133b859a2b4feed0635657bcba45a50d5547e72cbad7a330c051a14b410a08dca551ed40e998d821a0048ea23a1581c373b7956817434b15b87717075359307b1f1f6911ee03c4cb2004eb3a1581c6f6d6e697350726f647563745365637572697479526570726573656e01021a0003611d031a00bc1a200758200a175108e98a082f86696662c3cbf4ea588edf60a09831ccc0be04279de4886d09a1581c373b7956817434b15b87717075359307b1f1f6911ee03c4cb2004eb3a1581c6f6d6e697350726f647563745365637572697479526570726573656e01a101818201818200581c20763045c339d6f996e02a0a81ca5f41aa3898e964fd3206caf12f75f5f6

Address validity

Is there are any way to check address validity?
Something like


public static bool IsValid(string address){
....
}

Fee Calculation higher than expected

We are calculating the fee based on the length of the hexadecimal string (see ToStringHex()) below instead of the byte length.

public static uint CalculateFee(this Transaction transaction, uint? a = null, uint? b = null)
{
    if (!a.HasValue) a = FeeStructure.Coefficient;
    if (!b.HasValue) b = FeeStructure.Constant;

    return ((uint)transaction.Serialize().ToStringHex().Length * a.Value) + b.Value;
}

However removing the ToStringHex() (see solution below) calculates a fee 132 lovelaces less than it should be, and given a value of 44 for a, suggests we are off by a factor of three bytes. This potentially highlights either a missing field, an incorrect data type, or a bug in CBOR generation when serialising the transaction using the rules defined in the CDDL

Solution

public static uint CalculateFee(this Transaction transaction, uint? a = null, uint? b = null)
{
    if (!a.HasValue) a = FeeStructure.Coefficient;
    if (!b.HasValue) b = FeeStructure.Constant;

    return ((uint)transaction.Serialize().Length * a.Value) + b.Value;
}

Stake/Reward Address returning the payment address instead

AddressService GetAddress is returning the payment address instead of the stake/reward address. This is due to the same code being executed for both Enterprise and Reward addresses using the payment public key AddressService:38

            byte[] addressArray;
            switch (addressType)
            {
                case AddressType.Base:
                    addressArray = new byte[1 + paymentEncoded.Length + stakeEncoded.Length];
                    addressArray[0] = header;
                    Buffer.BlockCopy(paymentEncoded, 0, addressArray, 1, paymentEncoded.Length);
                    Buffer.BlockCopy(stakeEncoded, 0, addressArray, paymentEncoded.Length + 1, stakeEncoded.Length);
                    break;
                case AddressType.Enterprise:
                case AddressType.Reward:
                    addressArray = new byte[1 + paymentEncoded.Length];
                    addressArray[0] = header;
                    Buffer.BlockCopy(paymentEncoded, 0, addressArray, 1, paymentEncoded.Length);
                    break;
                default:
                    throw new Exception("Unknown address type");
            }

It should also still be valid with a null payment public key parameter which will currently throw an exception. Following from that, generating an enterprise address should also work with a null stake public key parameter. An easy fix can be applied with some null friendly args but perhaps a discussion is warranted - should we have SDK methods per address type? e.g. GetBaseAddress(PublicKey payment, PublicKey stake, NetworkType networkType); GetEnterpriseAddress(PublicKey payment, NetworkType networkType); GetRewardAddress(PublicKey stake, NetworkType networkType); this should save our SDK consumers from any unexpected behaviour and make things explicit.

WordList lookup for pre-loading allWords

Currently file IO to load all available words for a word list happens every time the KeyService BIP39 methods are called (Generate/Restore).

Since they are immutable arrays can we pre-load these upon initialisation of the KeyService instance? Perhaps even initialised instance variables aren't required and a static readonly IDictionary<WordLists, string[]> master-lookup using an approach like https://github.com/realindiahotel/BIP39.NET/tree/master/BIP39.NET/BIP39.NET/Wordlists could work?

Improve Performance of CBORObject ByteString Decoding

Currently ByteString type CBORObjects are decoded to byte[] using the long form expression

var byteArray = ((string)cborObject.DecodeValueByCborType()).HexToByteArray();

Where DecodeValueByCborType() exists in CBORExtensions.cs as

public static object DecodeValueByCborType(this CBORObject cborObject)
{
    object result = new object();
    switch (cborObject.Type)
    {
      case CBORType.ByteString:
          result = cborObject.ToString().Replace("h", "").Replace("'", "");
          break;
    }
}

This approach is found in hot paths for Transaction CBOR deserialization:
image

For the CardanoSharp.Wallet SDK to be used in performance-oriented applications we should use the simpler form which doesn't incur additional computation or allocation overhead yet returns same result.

var byteArray = cborObject.GetByteString();

Test to validate equivalence of the approaches

  [Fact]
  public void GetByteStringEquivalence()
  {
      var bytes = new byte[]
          {
             0x01, 0x01, 0x06, 0x00, 0x00, 0x00, 0x3d, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
             0x00, 0x0b, 0x82, 0x01, 0xfc, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          };
      var cborBytestring = CBORObject.FromObject(bytes);
      var decodedFromStringHex = ((string)cborBytestring.DecodeValueByCborType()).HexToByteArray();
      var decodedByteString = cborBytestring.GetByteString();
      Assert.Equal(decodedFromStringHex.Length, decodedByteString.Length);
      for (int i = 0; i < bytes.Length; i++)
      {
          Assert.Equal(bytes[i], decodedFromStringHex[i]);
          Assert.Equal(bytes[i], decodedByteString[i]);
      }
  }

uint max value is not enough for transaction outputs

TransactionOutputValue uses uint type for output coins.
In c# uint refers to UInt32 type with max value of 4294967295
Cardano has divisibility of 6 places so, 4294967295 lovelace is 4294.967295 ADA.
Today's cardano price in USD is 2.28 so maximum amount to send is only 9792 USD.
It's not enough to cover all needs.
My suggestion is to use ulong type for output coins and fees.

How to generate skey compatible with cardano-cli

Wanted to ask if it is possible to generate skey that would be compatible with cardano-cli
In cli we can create skey using this command
cardano-cli address key-gen
--verification-key-file payment.vkey
--signing-key-file payment.skey

Currently I have scenario that I have nami account for which I have 24 words.
I was wondering how I can create skey for it

IMnemonicService mnemonicService= new MnemonicService();
Mnemonic mnemonic = mnemonicService.Restore("24_words");
PrivateKey rootKey = mnemonic.GetRootKey();
System.IO.File.WriteAllBytes(@"c:\temp\some.skey", rootKey.Key);

However the content of this file isn't similar to what is generated with cardano-cli.
We have most of the system written with cardano-cli wrapper so we are not yet ready to fully migrate to cardanosharp-wallet
hence I would like to use MnemonicService and generate signing key and use it in the cardano-cli command.

Differences between 2.0.0 and newer

Hi,

I've been using this library for a while now and recall coming across an issue when submitting a transaction I get an error:
TextEnvelope decode error: DecoderErrorDeserialiseFailure "Shelley Tx" (DeserialiseFailure 1 "Size mismatch when decoding \nRecord RecD.\nExpected 4, but found 3.").

My unity game is using version 2.0.0 and works fine, I never see this error. I forgot I downgraded it to 2.0.0 rather than a newer version due to some bug around sending tokens.
Recently I created an api that uses 2.6.0 of this library and this error came back again. Downgrading my dependency on this library to 2.0.0 from 2.6.0 in nuget and everything works fine.

Any idea why this would happen?
I reviewed the signed transactions manually and found they were like 1 byte different

daedalus address to bytes

Hello. Could you point me on how to generate bytes from daedalus address?
DdzFFzCqrht9W56zJGEFvHHywdeXZiGVYGqVhoZj6SRrS9o2HNLmorEzZhKm7khqfBKvCaTKGLtTnQSToxuvdzJTkQqcAf6f2ErxbSKS -> byte[]

Readme out of date

Hi! I was trying to use the library following the example code on the readme, but the code on the Calculate Fee section does not work any more. I wanted to fix the example, but I couldn't find the way.
Hope I can help in the future. Thanks in advance!

improve Bech32 encode / decode

just a backing issue for future improvement

private byte[] ConvertBits(byte[] data, int fromBits, int toBits, bool pad = true)
{
// TODO: Optimize Looping
// We can use a method similar to BIP39 here to avoid the nested loop, usage of List, increase the speed,
// and shorten this function to 3 lines.
// Or convert to ulong[], loop through it (3 times) take 5 bits at a time or 8 bits at a time...

Maybe the implementations of System.Convert.ToBase64String() and/or Base32 can give a hint on how to improve this method

That said, keeping it clsoe to the reference implementations of BIP32 is a good idea

Bech32.IsValid only works for bech32-encoded addresses and not other entities

Discovered while testing bech32 decoding in cscli PR CardanoSharp/cscli#3 using extended keys and policy keys.

Examples

  • addr_xsk1fzw9r482t0ekua7rcqewg3k8ju5d9run4juuehm2p24jtuzz4dg4wpeulnqhualvtx9lyy7u0h9pdjvmyhxdhzsyy49szs6y8c9zwfp0eqyrqyl290e6dr0q3fvngmsjn4aask9jjr6q34juh25hczw3euust0dw
  • policy_sk1krqllaz7ypdfj5s7ak5psunflp5ta80d6fur5wscmwetmwnht4vex2kshz6vurqn366pyxwjzka0jnfpav4hzlmqefqf0dvstxuwt7ckg5gd0

Expected Bech32.IsValid to return true but is returning false

GetPrefixHeader does not work for all AddressType values

GetPrefixHeader does not work for all values. Examples that do not work, but are valid addresses (as defined in https://github.com/cardano-foundation/CIPs/tree/master/CIP-0019#test-vectors):

  1. addr1yx2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzerkr0vd4msrxnuwnccdxlhdjar77j6lg0wypcc9uar5d2shs2z78ve // type-02
  2. addr128phkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gtupnz75xxcrtw79hu // type-05
  3. addr1gx2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer5pnz75xxcrzqf96k // type-04
  4. stake178phkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gtcccycj5 // type-15

It seems that updating the below snippet could be sufficient:

public static string GetPrefixHeader(AddressType addressType)
    {
      switch (addressType)
      {
        case AddressType.Base:
          return "addr";
        case AddressType.Script:
          return "addr";
        case AddressType.ScriptWithScriptDelegation:
          return "addr";
        case AddressType.Enterprise:
          return "addr";
        case AddressType.EnterpriseScript:
          return "addr";
        case AddressType.Stake:
          return "stake";
        default:
          throw new Exception("Unknown address type");
      }
    }

Derive Reward (aka Stake) Address from Base Payment Address in IAddressService

Wallet users work primarily with base payment addresses but our backend code is more interested in the wallet account's total balance and assets instead of a single payment address.

BlockFrost and Koios expose very useful Acccount-based endpoints accepting a stake address as a request parameter. Lucky for us all the Cardano wallets conveniently share the same underlying stake key and address for all the base payment addresses and we can extract it with a bit of byte data shuffling.

Add a new method to IAddressService and implement it

Address ExtractRewardAddress(Address baseAddress);

Now that we have the reward address we can then query BlockFrost and Koios.

Key criteria

  • Accept testnet and mainnet base payment addresses and extract reward addresses for the same network
  • Input validation to ensure the address is a base payment address
  • Unit test coverage for the above

AddressService.GetAddressBytes does not exists

As per the example shown on how to create a transaction, addressService.GetAddressBytes is used during TransactionOutput, however is not available via Nuget package, nor via browsing the repository.

preprod and preview networks not supported

The Cardano testnet is not usable right now, therefore 2 new public test networks were created.

  • preprod
  • preview

Cardanosharp hasn't been updated to support those new networks yet.

Improve `TransactionBuilder`

Why we should improve TransactionBuilder

Reading through the Transactions Section in the README I noticed that TransactionBuilder doesn't really help build the transaction.

So I extracted the interface for TransactionBuilder and noticed that it looks more like a TransactionSerializer

public interface ITransactionBuilder
{
    long CalculateFee(byte[] transaction);
    byte[] SerializeBody(TransactionBody transactionBody);
    byte[] SerializeTransaction(Transaction transaction);
}

We should name it accordingly. And since Serializers don't CalculateFees but TransactionBuilders could lets assume we do this for now...

public interface ITransactionSerializer
{
    byte[] SerializeBody(TransactionBody transactionBody);
    byte[] SerializeTransaction(Transaction transaction);
}

public interface ITransactionBuilder
{
    Transaction Transaction { get; }
    int Fees { get; }
    // more to come...
}

Since we have a TransactionSerializer this should also be able to DeserializeBody and DeserializeTransaction

public interface ITransactionSerializer
{
    byte[] SerializeBody(TransactionBody transactionBody);
    byte[] SerializeTransaction(Transaction transaction);
    TransactionBody DeserializeBody(byte[] transactionBody);
    Transaction DeserializeTransaction(byte[] transaction);
}

But of course we need a TransactionBuilder that helps create Transaction we can serialize/deserialize by ITransactionSerializer.

How we could improve TransactionBuilder

So what are transactions? They modify the ledger and can:

  • contain Certificates
  • contain Metadata
  • contain Scripts (Native / SmartContracts)
  • be signed (by 1 to n witnesses)
  • spend UTxOs (inputs = outputs - fees)
  • ...and more (like minting / burning tokens, but let's leave this usecase aside for now)

So I propose the ITransactionBuilder to look like this:

public interface ITransactionBuilder
{
    Transaction Transaction { get; }
    int Fees { get; }

    ITransactionBuilder AddCertificate(Certificate certificate);
    ITransactionBuilder AddMetadata(Metadata metadata); // base type for PoolMetadata
    ITransactionBuilder AddInput(Address addr, int index);
    ITransactionBuilder AddOutput(Address addr, int amount);
    ITransactionBuilder AddScript(NativeScript script);

    Transaction Sign(params PrivateKey[] witnesses);
}

Notice:

  • It looks like a StringBuilder...
  • AddXXX(...) are like StringBuilder.Append
  • Sign(...) is the equivalent to StringBuilder.ToString
  • We don't need a Build() method, since Transaction is updated and maintained by the TransactionBuilder "as-we-build"...
  • Sign() would return a new Transaction so that we don't "loose" our building progress if the transaction fails.
  • We have full control over the transaction being built via the Transaction property

What are your thoughts / inputs? Should we pursue this?

Question about deriving addresses and encrypting private keys

Hi,

I love this project, thank you!

I'm trying to mimic how Daedalus does a few things. Currently Daedalus shows used and unused addresses in the Receive tab.
I am capable of deriving 20 addresses at a time and checking with a server to determine if these addresses are used or not. I end up with a list of x used addresses and the next 20 available unused addresses.

I have this all working and it's exactly the same as the Daedalus receive screen. The only issue I'm facing is how to achieve this without access to the private keys as they're encrypted with the spending password.

I have a couple of implementation examples of this but sadly if they're IAccountNodeDerivation or simply byte[] Key, byte[] Chaincode for both private key and public key that means I need the private key to derive the next 20 addresses.

Thanks for your help,
Dan

blazor wasm dotnet 7 (not a issue, but a remark)

I've just tested blazor wasm with dotnet7

 public partial class Index: ComponentBase
    {
        private IAddressService addressService = new AddressService();
        private IMnemonicService service = new MnemonicService();

        public int privateKeyStr { get; set; }
        protected override void OnInitialized()
        {
            string q = "";
            string words = "art forum devote street sure rather head chuckle guard poverty release quote oak craft enemy";
            var mnemonic = new MnemonicService().Restore(words);

            // Fluent derivation API
            var derivation = mnemonic
                .GetMasterNode("password")      // IMasterNodeDerivation
                .Derive(PurposeType.Shelley)    // IPurposeNodeDerivation
                .Derive(CoinType.Ada)           // ICoinNodeDerivation
                .Derive(0)                      // IAccountNodeDerivation
                .Derive(RoleType.ExternalChain) // IRoleNodeDerivation
                                                //or .Derive(RoleType.Staking) 
                .Derive(0);                     // IIndexNodeDerivation

            PrivateKey privateKey = derivation.PrivateKey;
            PublicKey publicKey = derivation.PublicKey;

           

            base.OnInitialized();
        }
    }

And it works!
looks promising!

CalculateAndSetFee relies on TransactionWitnessSet to be initialized

transaction.TransactionWitnessSet.VKeyWitnesses.CreateMocks(numberOfVKeyWitnessesToMock);

Found a situation where a transaction is intending to calculate with no witnesses and only mocks. At the time of calculate, TransactionWitnessSet is null which causes an exception.

Question: Is this implementation ok and we should expect at least an initialized TransactionWitnessSet. Or should we initialize it in this method?

CoinSelection-UseRandomImprove: "The binary key cannot have an odd number of digits" - testnet env

Im getting the error "The binary key cannot have an odd number of digits" when trying to perform a coin selection using "UseRandomImprove" strategy on cardano testnet environment, please check the code below:

`List encodedUtxos = new List()
{
"8282582046ecc0033a70b360fe45537091ca9dcb52238060545235ca203129448cf4bac50082583900c9545514cf191b89f2a27063adfefceaff866557c192df5482942ae438cc1f407e7de7c548a6a62e4814744c949ba1c6282238c55a6acd3a1a001bc33b",
"82825820a09658c3e19301210a505c00c426115406515c6245f835b00e82abd2ba5ba26e0182583900c9545514cf191b89f2a27063adfefceaff866557c192df5482942ae438cc1f407e7de7c548a6a62e4814744c949ba1c6282238c55a6acd3a821a004e659aa3581c82c9d41020cada347ca3c48ea38354955159916b6ddda937fc61de13a44a3344416d69676f333339014a3344416d69676f343331014a3344416d69676f343337014a3344416d69676f35333401581ca4b4a513e4345fda49cca6276bdfc0fe898fc44b9acbb5bb9675d094b82248416d69676f3235330148416d69676f3538300148416d69676f3830340148416d69676f3832340148416d69676f3835310148416d69676f3837390149416d69676f313032300149416d69676f313035320149416d69676f313132390149416d69676f313133360149416d69676f313338380149416d69676f313536340149416d69676f313631320149416d69676f313633310149416d69676f313633380149416d69676f313637300149416d69676f313831360149416d69676f313835360149416d69676f313937390149416d69676f323136340149416d69676f323236350149416d69676f323237340149416d69676f323430330149416d69676f323434360149416d69676f323534310149416d69676f323539330149416d69676f323734320149416d69676f323735310149416d69676f323834300149416d69676f323836340149416d69676f323837340149416d69676f323935330149416d69676f333430310149416d69676f3334383701581cdf3c4544b4a43d7565e9bcc41958b395a1e338a4fe30cd4d46da3b96a249416d69676f313534320149416d69676f3234303601",
"828258202013fb4b69f5e83dd98678ec34f0677c17939957fc0ea22afb2b83e64123c83c0082583900c9545514cf191b89f2a27063adfefceaff866557c192df5482942ae438cc1f407e7de7c548a6a62e4814744c949ba1c6282238c55a6acd3a1a001bc33b",
"828258208741c6b5b913a53bdcaae7344f9d0bf4dd7a9d8ea5e5b1e67742fcec539897570082583900c9545514cf191b89f2a27063adfefceaff866557c192df5482942ae438cc1f407e7de7c548a6a62e4814744c949ba1c6282238c55a6acd3a1a001bc33b",
"828258200c32034146fb94e581bdd5b04af436a44e519e7bec3b845a2ae68bd32f4760630082583900c9545514cf191b89f2a27063adfefceaff866557c192df5482942ae438cc1f407e7de7c548a6a62e4814744c949ba1c6282238c55a6acd3a1a001bc33b",
"828258205ea25e963a1d309fc7c312a6b637b72bc2cd716d2273f4d170f5a60131fdd6270082583900c9545514cf191b89f2a27063adfefceaff866557c192df5482942ae438cc1f407e7de7c548a6a62e4814744c949ba1c6282238c55a6acd3a1a001bc33b",
"828258205ea25e963a1d309fc7c312a6b637b72bc2cd716d2273f4d170f5a60131fdd6270082583900c9545514cf191b89f2a27063adfefceaff866557c192df5482942ae438cc1f407e7de7c548a6a62e4814744c949ba1c6282238c55a6acd3a1a001bc33b",
"828258201b59da607cf691f92080f38f43cfd14f57902d8e2c080a7cc3fcd3c300210bdf0082583900c9545514cf191b89f2a27063adfefceaff866557c192df5482942ae438cc1f407e7de7c548a6a62e4814744c949ba1c6282238c55a6acd3a1a001bc33b",
"82825820896257251e70af85fecff43ce87d11f242bd787c637b39b33179dc97399178800082583900c9545514cf191b89f2a27063adfefceaff866557c192df5482942ae438cc1f407e7de7c548a6a62e4814744c949ba1c6282238c55a6acd3a1a001bc33b",
"828258206c69975778efed999ad96366c431d47575707e7c09ff6c004dd27166b2036d660082583900c9545514cf191b89f2a27063adfefceaff866557c192df5482942ae438cc1f407e7de7c548a6a62e4814744c949ba1c6282238c55a6acd3a1a0018ff36",
"828258206b388166c06e39e8ff278a76f2ae90ae88b26547140b857e6c3ae83e1e1dc8960182583900c9545514cf191b89f2a27063adfefceaff866557c192df5482942ae438cc1f407e7de7c548a6a62e4814744c949ba1c6282238c55a6acd3a821a001e8480a1581c231aff70355327339e962028873bab4af1a3e1605d472806f30b4aada146546f6b656e3101",
"82825820c20dfc86db12c57285be5d04ec0b6e183480eacf4d77041ee01333d6e69685e10182583900c9545514cf191b89f2a27063adfefceaff866557c192df5482942ae438cc1f407e7de7c548a6a62e4814744c949ba1c6282238c55a6acd3a821a001e8480a1581c231aff70355327339e962028873bab4af1a3e1605d472806f30b4aada146546f6b656e3101",
"828258209822c29d6d60d66de34ce9fa199563380c42f8ac60e028344561d09c3bff52be0182583900c9545514cf191b89f2a27063adfefceaff866557c192df5482942ae438cc1f407e7de7c548a6a62e4814744c949ba1c6282238c55a6acd3a821a001e8480a1581c231aff70355327339e962028873bab4af1a3e1605d472806f30b4aada146546f74696f3101",
"82825820461836a03e45a5ebda2ab659822fa3f506d7eac89ff40b93ac7e255753c1f2190182583900c9545514cf191b89f2a27063adfefceaff866557c192df5482942ae438cc1f407e7de7c548a6a62e4814744c949ba1c6282238c55a6acd3a821a001e8480a1581c231aff70355327339e962028873bab4af1a3e1605d472806f30b4aada146546f74696f3101",
"828258201133f32071a317b7f809f56b2bd0d020a2c4b1d3a93be5906d6ee15b21b6a47c0182583900c9545514cf191b89f2a27063adfefceaff866557c192df5482942ae438cc1f407e7de7c548a6a62e4814744c949ba1c6282238c55a6acd3a821a001e8480a1581c231aff70355327339e962028873bab4af1a3e1605d472806f30b4aada146546f74696f3101",
"8282582071d5e26b48bb2dd2aadd3c3bee6db99bd6d18a3e6d8bd9b912131382cf0d6e7d0182583900c9545514cf191b89f2a27063adfefceaff866557c192df5482942ae438cc1f407e7de7c548a6a62e4814744c949ba1c6282238c55a6acd3a821a001e8480a1581c231aff70355327339e962028873bab4af1a3e1605d472806f30b4aada146546f6b656e3101",
"8282582071d5e26b48bb2dd2aadd3c3bee6db99bd6d18a3e6d8bd9b912131382cf0d6e7d0282583900c9545514cf191b89f2a27063adfefceaff866557c192df5482942ae438cc1f407e7de7c548a6a62e4814744c949ba1c6282238c55a6acd3a1a328fc20b",
"82825820448b9b507030d270e287907e3549f33d659cd2541434895040d33a3c1e70bd070082583900c9545514cf191b89f2a27063adfefceaff866557c192df5482942ae438cc1f407e7de7c548a6a62e4814744c949ba1c6282238c55a6acd3a1a006acfc0"
};

        PolicyManager policyManager = new PolicyManager();
        Address paymentAddr = new Address("addr_test1qprk02ddd6ar60qjlh4gmvgy3hxqcezx4yl452yl0tley9kx6zphf83h8hh9d7nfnmlt3gs8n545k2u38kq30f3mzlxqd7rhtf");
        List<Utxo> utxos = new List<Utxo>();
        try

        {
            encodedUtxos.ForEach(e => utxos.Add(UtxoExtensions.GetUtxo(CBORObject.DecodeFromBytes(e.HexToByteArray()))));
            var customerAddressString = utxos[0].OutputAddress;
            Address customerAddr = new Address(customerAddressString);
            var scriptPolicy = policyManager.GetPolicyScript();
            var transactionBody = TransactionBodyBuilder.Create;
            transactionBody.AddOutput(paymentAddr.GetBytes(), 7000000);
            var policyId = scriptPolicy.Build().GetPolicyId();
            ITokenBundleBuilder tokenBundleBuilder = TokenBundleBuilder.Create
                .AddToken(policyId, "Token1".ToBytes(), 1);
            transactionBody.AddOutput(customerAddr.GetBytes(), 2000000, tokenBundleBuilder, outputPurpose: OutputPurpose.Mint);
            transactionBody.SetMint(tokenBundleBuilder);
            var coinSelection = ((TransactionBodyBuilder)transactionBody).UseRandomImprove(utxos, customerAddr.ToString(), tokenBundleBuilder);
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }`

`Bech32.Decode` tests fail on valid BIP173 testvectors

[Theory]
//@TODO Fails [InlineData("A12UEL5L", "", 0x00, "")] //@TODO verify
//@TODO Fails [InlineData("a12uel5l", "", 0x00, "")] //@TODO verify
//@TODO Fails [InlineData("an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1tt5tgs", "", 0x00, "")]
//[InlineData("abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw", "00443214c74254b635cf84653a56d7c675be77df", 0x00, "abcdef")]
//[InlineData("11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqc8247j", "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 0x00, "1")]
//@TODO Fails [InlineData("split1checkupstagehandshakeupstreamerranterredcaperred2y9e3w", "c5f38b70305f5fb6cf03058f3dde463ecd7918f2dc743918f2d", 0x00, "split")]
//@TODO Fails [InlineData("?1ezyfcl", "", 0x00, "")]
//@TODO Fails [InlineData("BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4", "0014751e76e8199196d454941c45d1b3a323f1433bd6", 0x00, "BC")]
//@TODO Fails [InlineData("tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7", "00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262", 0x00, "tb")]
//@TODO Fails [InlineData("bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx", "5128751e76e8199196d454941c45d1b3a323f1433bd6751e76e8199196d454941c45d1b3a323f1433bd6", 0x00, "tb")]
//@TODO Fails [InlineData("BC1SW50QA3JX3S", "6002751e", 0x00, "tb")]
//@TODO Fails [InlineData("bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj", "5210751e76e8199196d454941c45d1b3a323", 0x00, "tb")]
//@TODO Fails [InlineData("tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy", "0020000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433", 0x00, "tb")]
//CIP19 Test Vectors
[InlineData("addr1qx2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer3n0d3vllmyqwsx5wktcd8cc3sq835lu7drv2xwl2wywfgse35a3x", "019493315cd92eb5d8c4304e67b7e16ae36d61d34502694657811a2c8e337b62cfff6403a06a3acbc34f8c46003c69fe79a3628cefa9c47251", 0, "addr")]
[InlineData("addr1z8phkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gten0d3vllmyqwsx5wktcd8cc3sq835lu7drv2xwl2wywfgs9yc0hh", "11c37b1b5dc0669f1d3c61a6fddb2e8fde96be87b881c60bce8e8d542f337b62cfff6403a06a3acbc34f8c46003c69fe79a3628cefa9c47251", 2, "addr")]
[InlineData("addr1yx2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzerkr0vd4msrxnuwnccdxlhdjar77j6lg0wypcc9uar5d2shs2z78ve", "219493315cd92eb5d8c4304e67b7e16ae36d61d34502694657811a2c8ec37b1b5dc0669f1d3c61a6fddb2e8fde96be87b881c60bce8e8d542f", 4, "addr")]
[InlineData("addr1x8phkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gt7r0vd4msrxnuwnccdxlhdjar77j6lg0wypcc9uar5d2shskhj42g", "31c37b1b5dc0669f1d3c61a6fddb2e8fde96be87b881c60bce8e8d542fc37b1b5dc0669f1d3c61a6fddb2e8fde96be87b881c60bce8e8d542f", 6, "addr")]
[InlineData("addr1gx2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer5pnz75xxcrzqf96k", "419493315cd92eb5d8c4304e67b7e16ae36d61d34502694657811a2c8e8198bd431b03", 8, "addr")]
[InlineData("addr128phkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gtupnz75xxcrtw79hu", "51c37b1b5dc0669f1d3c61a6fddb2e8fde96be87b881c60bce8e8d542f8198bd431b03", 10, "addr")]
[InlineData("addr1vx2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzers66hrl8", "619493315cd92eb5d8c4304e67b7e16ae36d61d34502694657811a2c8e", 12, "addr")]
[InlineData("addr1w8phkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gtcyjy7wx", "71c37b1b5dc0669f1d3c61a6fddb2e8fde96be87b881c60bce8e8d542f", 14, "addr")]
[InlineData("stake1uyehkck0lajq8gr28t9uxnuvgcqrc6070x3k9r8048z8y5gh6ffgw", "e1337b62cfff6403a06a3acbc34f8c46003c69fe79a3628cefa9c47251", 28, "stake")]
[InlineData("stake178phkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gtcccycj5", "f1c37b1b5dc0669f1d3c61a6fddb2e8fde96be87b881c60bce8e8d542f", 30, "stake")]
[InlineData("addr_test1qz2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer3n0d3vllmyqwsx5wktcd8cc3sq835lu7drv2xwl2wywfgs68faae", "009493315cd92eb5d8c4304e67b7e16ae36d61d34502694657811a2c8e337b62cfff6403a06a3acbc34f8c46003c69fe79a3628cefa9c47251", 0, "addr_test")]
[InlineData("addr_test1zrphkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gten0d3vllmyqwsx5wktcd8cc3sq835lu7drv2xwl2wywfgsxj90mg", "10c37b1b5dc0669f1d3c61a6fddb2e8fde96be87b881c60bce8e8d542f337b62cfff6403a06a3acbc34f8c46003c69fe79a3628cefa9c47251", 2, "addr_test")]
[InlineData("addr_test1yz2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzerkr0vd4msrxnuwnccdxlhdjar77j6lg0wypcc9uar5d2shsf5r8qx", "209493315cd92eb5d8c4304e67b7e16ae36d61d34502694657811a2c8ec37b1b5dc0669f1d3c61a6fddb2e8fde96be87b881c60bce8e8d542f", 4, "addr_test")]
[InlineData("addr_test1xrphkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gt7r0vd4msrxnuwnccdxlhdjar77j6lg0wypcc9uar5d2shs4p04xh", "30c37b1b5dc0669f1d3c61a6fddb2e8fde96be87b881c60bce8e8d542fc37b1b5dc0669f1d3c61a6fddb2e8fde96be87b881c60bce8e8d542f", 6, "addr_test")]
[InlineData("addr_test1gz2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer5pnz75xxcrdw5vky", "409493315cd92eb5d8c4304e67b7e16ae36d61d34502694657811a2c8e8198bd431b03", 8, "addr_test")]
[InlineData("addr_test12rphkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gtupnz75xxcryqrvmw", "50c37b1b5dc0669f1d3c61a6fddb2e8fde96be87b881c60bce8e8d542f8198bd431b03", 10, "addr_test")]
[InlineData("addr_test1vz2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzerspjrlsz", "609493315cd92eb5d8c4304e67b7e16ae36d61d34502694657811a2c8e", 12, "addr_test")]
[InlineData("addr_test1wrphkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gtcl6szpr", "70c37b1b5dc0669f1d3c61a6fddb2e8fde96be87b881c60bce8e8d542f", 14, "addr_test")]
[InlineData("stake_test1uqehkck0lajq8gr28t9uxnuvgcqrc6070x3k9r8048z8y5gssrtvn", "e0337b62cfff6403a06a3acbc34f8c46003c69fe79a3628cefa9c47251", 28, "stake_test")]
[InlineData("stake_test17rphkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gtcljw6kf", "f0c37b1b5dc0669f1d3c61a6fddb2e8fde96be87b881c60bce8e8d542f", 30, "stake_test")]
public void TestValidInputs(string addr, string expectedHex, byte expectedVer, string expectedHrp)

BIP173 defines valid test vectors for Bech32 here.

All parameters for InlineDataAttribute need review and must be fixed first. (ie. expectedWitVer and expectedHrp)

I think there's an issue in the CalculateFee section in the readme

The example shows:

// Calculate Fee
var fee = transaction.CalculateFee(minFeeA, minFeeB);

// Update Fee and Rebuild
transactionBody.SetFee(fee);
Transaction transaction = transactionBuilder.Build();

Note that transaction is created only after the var fee = transaction.... is called? This wouldn't even compile!

It would be helpful to add an example that shows what you do with the transaction after it's built, personally I had to struggle to figure out that I can take the signed transactions cbor string hex and use that!

Great project everyone, just needs a bit more documentation showing an entire flow from start to finish.
I'd suggest something that shows how to create/restore a wallet, see balances of assets/ada, tx history, submit of actual transaction.

Token metadata JSON asset name field cannot be defined using anonymous type object.

Tokens and NFTs require metadata with some field names that represent unique values. PolicyID and AssetName must appear in the metadata as the actual field names in the JSON structure.

{ "721": { "f46ba28b19f7f35df3a5dbb9efeddee4bdd61ea33ba7fee2c31c655a": { "Token012382": { "name": "Fun tokens, just for fun.", "image": "ipfs://ipfs/QmVE1Ssn2wzc9Rg1emQCtxkMuWdG2AW21VpgbrDftmqnz7" } } } }

AuxiliaryDataBuilder is provided to assign metadata. The AddMetadata method accepts an object type which is then used to generate the JSON structure. All examples show using an anonymous type.

C# code using variables for field names.
metadataBuilder.AddMetadata(721, new { policyIdVariable = new { assetNameVariable = new { name = "Fun tokens, just for fun.", image = "ipfs://ipfs/QmVE1Ssn2wzc9Rg1emQCtxkMuWdG2AW21VpgbrDftmqnz7" } } });

The code above fails to use the variable's (policyIdVariable, assetNameVariable) values as field names. This is because anonymous types are defined at compile-time. As a test, to confirm the challenge, I hardcoded the PolicyID and AssetName as illustrated below.

C# hardcoded
metadataBuilder.AddMetadata(721, new { f46ba28b19f7f35df3a5dbb9efeddee4bdd61ea33ba7fee2c31c655a = new { Token012382 = new { name = "Fun tokens, just for fun.", image = "ipfs://ipfs/QmVE1Ssn2wzc9Rg1emQCtxkMuWdG2AW21VpgbrDftmqnz7" } } });

This did generate the desired metadata for a token minting transaction. There may be an easy way to dynamically define a field name on an anonymous type, but I am unaware of it. Is it possible to pass a JSON formatted string to the AddMetadata method instead of using a class structure?

Any advice or help is appreciated.

Need some advice on if I can use this wallet to the job.

Hello:
I want to know if I can create a C# project to do the following job.
I need one deposit address on two networks, one is for HECO network, another is for ERC20 network.
And I can buy some currency tokens, for example, this token RUFF (Ruff Chain), and send the Ruff tokens to the deposit address I created via HECO network, as the exchange where I buy the RUFF tokens supports only HECO network. After the RUFF tokens arrive, I want to change the token network, from HECO to ERC20, then send the tokens to another wallet address, which is also on ERC20 network.
Simply put, I want to create one C# project, which can switch network for the same cryptocurrency, it is rather useful, as I can see that many exchanges have the same currency tokens, but they may be on different networks, if I want to send the same tokens from one exchange to another exchange, then the tokens have to be on the same network, but quite often, it is impossible.
Please advise if I can do this with the repo.
I can create MetaMask wallet, and MetaMask has some SDK in JavaScript, which I don’t have much experience, but I have good experience with C# .NET on Windows 10.
I have no experience with Cardano wallet, can I create a wallet just like I use MetaMask wallet?
And can I have Cardano wallet to connect with different networks, like HECO, REC20, BEP20, TRC20 and others?
So, I want to know if I can create Cardano wallet with dual networks support (HECO and ERC20), then use C# and this repo to receive some tokens (like RUFF), and change the network (from HECO to ERC20), then transfer the RUFF tokens to another wallet address (outside the MetaMask wallet control)?
If yes, please provide a general idea on how to proceed.
My OS: Windows 10 (22H2), IDE: Visual Studio 2022 (Version 17.4.1) with .net 7 support.
Thanks,

Incorrect NativeScript CBOR Serialization for ScriptAll/ScriptAny/ScriptNofK

Overview

NativeScript types (i.e. ScriptAll/ScriptAny/ScriptNofK) with an internal array will incorrectly serialize to CBOR with an extra nested array. This results in transactions built by CardanoSharp being rejected by the node if they require NativeScripts (e.g. A NativeScript minting policy) with more than one internal scripts within a TransactionWitnessSet.

Incorrect CBOR

NativeScriptIncorrectCBOR

Expected CBOR

NativeScriptExpectedCBOR

Steps to Reproduce

Given the following ScriptAll

var scriptAll = new ScriptAll();
scriptAll.NativeScripts.Add(
    new NativeScript
    {
        InvalidAfter = new ScriptInvalidAfter
        {
            After = 96997186U
        }
    });
scriptAll.NativeScripts.Add(
    new NativeScript
    {
        ScriptPubKey = new ScriptPubKey
        {
            KeyHash = "ee367222ee4d74903eb182757e90b82b3be306fe8b06c88bb2382def".HexToByteArray()
        }
    });

Get the CBOR

var scriptAllCbor = CBORObject.NewArray().Add(1);
foreach (var nativeScript in scriptAll.NativeScripts)
{
    scriptAllCbor.Add(nativeScript.GetCBOR());
}
Console.WriteLine(scriptAllCbor.ToJSONString());

KeyService thread/concurrency safety

In a multi-threaded environment when multiple calls to Generate() and/or Restore() run concurrently, multiple threads mutating the wordIndexes and allWords arrays could have unintended side-effects in the outputs.

Suggestion: Declare and use local method-scoped variables for both arrays instead of instance member variables. E.g. allWords will be declared in the methods and bound accordingly, SetWordsFromEntropy(entropy) can have return type of uint[] which can then be assigned to another local method variable wordIndexes and passed to GetMnemonic(wordIndexes, allWords)?

CIP2 Strategies not working correctly with newly minted assets

//set outputs
var utxos = await GetUtxos(address.ToString());
ITokenBundleBuilder tbb = TokenBundleBuilder.Create
   .AddToken(scriptPolicy.Build().GetPolicyId(), "Awesome NFT".ToBytes(), 1);
transactionBody.AddOutput(address.GetBytes(), 2000000, tbb);
transactionBody.AddOutput(sendPaymentToAddress.GetBytes(), 100000000);

//perform coin selection
var coinSelection = ((TransactionBodyBuilder)transactionBody).UseLargestFirstWithImprove(utxos);

The above will fail. The TokenBundle is for an asset that will be minted in this sample transaction. The strategies does not take into account for this scenario

Mock Witnesses are left in transaction

After using the new mock witnesses functionality, I found myself taking extra steps to remove the mocked witnesses. Since we have an IsMock flag on the VKeyWitness object, maybe we can make a condition during the serialization to ignore mocked witnesses?

CIP 2 - Coin Selection Algorithms for Cardano

As described in the CIP Doc

Algorithms
This section describes the coin selection algorithms used by Cardano Wallet, along with step-by-step descriptions of the computations involved.

All algorithms implement a common interface, as described in the Interface section.

There are two main algorithms used by Cardano Wallet:

Largest-First
Random-Improve
In general, Cardano Wallet gives priority to the Random-Improve algorithm, as experimental evidence shows that it performs better at minimising dust and maintaining a UTxO set with useful outputs. (See Self Organisation in Coin Selection for more details.)

However, in rare cases, the Random-Improve algorithm may fail to produce a result. In such cases, Cardano Wallet will fall back to the Largest-First algorithm.


CIP Link: https://cips.cardano.org/cips/cip2/#algorithms

Bounty: 250 ADA

Issue with Version

I have a TestNet Daedalus acting as a node in my machine, and cardano-submit-api running on top of it
When I try to submit a transaction created with Cardano Sharp I get a 500 and the following error on the Node

HandshakeError (Refused NodeToClientV_11 "version data mismatch: NodeToClientVersionData {networkMagic = NetworkMagic {unNetworkMagic = 1097911063}} /= NodeToClientVersionData {networkMagic = NetworkMagic {unNetworkMagic = 0}}")

I have also tried posting to https://submit-api.testnet.dandelion.link/api/submit/tx and also get a 500 (can't see the server error)

Any ideas? Seems to be something regarding the version, but I have the latest versions of Daeadalus and CardanoSharp

Improve NativeScript

#17 introduced the PrivateKey, PublicKey, Mnemonic, WalletPath, and the various DerivationNode types...
The main types left are going to be around NativeScript. Technically these are already created but I believe they need some refactoring. Its not a very good experience build NativeScript which are used for Minting and MultiSig.

Originally posted by @nothingalike in #5 (comment)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.