public async Task <string> TransferNep5(byte[] toAddress, decimal amount, byte[] tokenScriptHash, int decimals = 8) { if (toAddress.Length != 20) { throw new ArgumentException(nameof(toAddress)); } if (amount <= 0) { throw new ArgumentOutOfRangeException(nameof(amount)); } var keyAddress = Helper.CreateSignatureRedeemScript(_accountKey.PublicKey); var fromAddress = keyAddress.ToScriptHash().ToArray(); BigInteger amountBigInteger = ConvertToBigInt(amount, decimals); var result = await CallContract(tokenScriptHash, "transfer", new object[] { fromAddress, toAddress, amountBigInteger }); if (result == null) { return(string.Empty); } return(result.Hash.ToString()); }
/// <summary> /// Creates an Account, ecrypts it using NEP2 and returns it. /// </summary> /// <returns></returns> public async Task <Account> CreateAccount(string label, string password) { var privateKey = new byte[32]; using (var rng = RandomNumberGenerator.Create()) { rng.GetBytes(privateKey); } var key = new KeyPair(privateKey); Array.Clear(privateKey, 0, privateKey.Length); var contract = new Contract { Script = Helper.CreateSignatureRedeemScript(key.PublicKey), Parameters = new List <Parameter> { new Parameter("signature", ParameterType.Signature) }, Deployed = false }; var encryptedKey = await Nep2.Encrypt(key.PrivateKey.ToHexString(), password); var account = new Account(key.PublicKeyHash, key) { Nep2Key = encryptedKey, Contract = contract, Label = label }; AddAccount(account); return(account); }
/// <summary> /// Creates an Account and returns it. /// </summary> /// <returns></returns> public Account CreateAccount(string label) { var privateKey = new byte[32]; using (var rng = RandomNumberGenerator.Create()) { rng.GetBytes(privateKey); } var key = new KeyPair(privateKey); Array.Clear(privateKey, 0, privateKey.Length); var contract = new Contract { Script = Helper.CreateSignatureRedeemScript(key.PublicKey), Parameters = new List <Parameter> { new Parameter("signature", ParameterType.Signature) }, Deployed = false }; var account = new Account(key.PublicKeyHash) { Contract = contract, Label = label }; AddAccount(account); return(account); }
/// <summary> /// Decrypts and add the account to the Wallet Account List, using NEP2. /// </summary> /// <param name="label"></param> /// <param name="encryptedPrivateKey"></param> /// <param name="password"></param> /// <returns></returns> public async Task <Account> ImportAccount(string encryptedPrivateKey, string password, string label) { var privateKey = await Nep2.Decrypt(encryptedPrivateKey, password, _wallet.Scrypt); var key = new KeyPair(privateKey); Array.Clear(privateKey, 0, privateKey.Length); var contract = new Contract { Script = Helper.CreateSignatureRedeemScript(key.PublicKey), Parameters = new List <Parameter> { new Parameter("signature", ParameterType.Signature) }, Deployed = false }; var account = new Account(contract.ScriptHash, key) { Nep2Key = encryptedPrivateKey, Label = label, Contract = contract, IsDefault = false }; AddAccount(account); return(account); }
public void Sign(byte[] privateKey) { var txdata = Serialize(false); var signature = Utils.Sign(txdata, privateKey); var invocationScript = ("40" + signature.ToHexString()).HexToBytes(); var verificationScript = Helper.CreateSignatureRedeemScript(new KeyPair(privateKey).PublicKey); Witnesses = new[] { new Witness { InvocationScript = invocationScript, VerificationScript = verificationScript } }; }
/// <summary> /// Decrypts and add the account to the Wallet Account List, using WIF. /// </summary> /// <param name="wif"></param> /// <param name="label"></param> /// <returns></returns> public Account ImportAccount(string wif, string label) { var key = new KeyPair(Wallet.GetPrivateKeyFromWif(wif)); var contract = new Contract { Script = Helper.CreateSignatureRedeemScript(key.PublicKey), Parameters = new List <Parameter> { new Parameter("signature", ParameterType.Signature) }, Deployed = false }; var account = new Account(contract.ScriptHash, key) { Contract = contract, Label = label }; AddAccount(account); return(account); }
public static WalletInformations GetWalletInformations(SecureString privateKey, BlockchainType keyType) { WalletInformations walletInformations = new WalletInformations(); switch (keyType) { case BlockchainType.Neo: var keyPair = new KeyPair(privateKey.GetString().HexToBytes()); string publicKey = keyPair.PublicKey.ToString(); UInt160 scriptHash = Helper.CreateSignatureRedeemScript(keyPair.PublicKey).ToScriptHash(); // This is a basic NEO address string address = scriptHash.ToAddress(); // This is a derivative of script hash (required by Switcheo) string fixedAddress = scriptHash.ToString().RemoveZeroX(); walletInformations = new WalletInformations() { Wif = keyPair.Export().ToSecureString(), PublicKey = publicKey, ScriptHash = scriptHash.ToString(), Address = address, FixedAddress = fixedAddress }; break; case BlockchainType.Qtum: throw new NotImplementedException(); case BlockchainType.Ethereum: throw new NotImplementedException(); } return(walletInformations); }
GenerateInputsOutputs(KeyPair key, string symbol, IEnumerable <TransactionOutput> targets) { if (targets == null) { throw new WalletException("Invalid amount list"); } var address = Helper.CreateSignatureRedeemScript(key.PublicKey); var unspent = await GetUnspent(Wallet.ToAddress(address.ToScriptHash())); // filter any asset lists with zero unspent inputs unspent = unspent.Where(pair => pair.Value.Count > 0).ToDictionary(pair => pair.Key, pair => pair.Value); var inputs = new List <SignedTransaction.Input>(); var outputs = new List <SignedTransaction.Output>(); string assetId; var info = GetAssetsInfo(); if (info.ContainsKey(symbol)) { assetId = info[symbol]; } else { throw new WalletException($"{symbol} is not a valid blockchain asset."); } if (!unspent.ContainsKey(symbol)) { throw new WalletException($"Not enough {symbol} in address {address}"); } decimal cost = 0; var fromHash = key.PublicKeyHash.ToArray(); var transactionOutputs = targets.ToList(); foreach (var target in transactionOutputs) { if (target.AddressHash.SequenceEqual(fromHash)) { throw new WalletException("Target can't be same as input"); } cost += target.Amount; } var sources = unspent[symbol]; decimal selected = 0; foreach (var src in sources) { selected += (decimal)src.Value; var input = new SignedTransaction.Input { PrevHash = src.TxId.HexToBytes().Reverse().ToArray(), PrevIndex = src.N }; inputs.Add(input); if (selected >= cost) { break; } } if (selected < cost) { throw new WalletException($"Not enough {symbol}"); } if (cost > 0) { foreach (var target in transactionOutputs) { var output = new SignedTransaction.Output { AssetId = assetId.HexToBytes().Reverse().ToArray(), ScriptHash = target.AddressHash.ToArray(), Value = target.Amount }; outputs.Add(output); } } if (selected > cost || cost == 0) { var left = selected - cost; var signatureScript = Helper.CreateSignatureRedeemScript(key.PublicKey).ToScriptHash(); var change = new SignedTransaction.Output { AssetId = assetId.HexToBytes().Reverse().ToArray(), ScriptHash = signatureScript.ToArray(), Value = left }; outputs.Add(change); } return(inputs, outputs); }