public VirtualChain(NeoAPI api, KeyPair owner) { this.Time = DateTime.UtcNow.ToTimestamp(); var scripthash = new UInt160(owner.signatureHash.ToArray()); var txs = new List <Transaction>(); foreach (var entry in NeoAPI.Assets) { var symbol = entry.Key; var assetID = NeoAPI.GetAssetID(symbol); _assetMap[assetID] = new Asset() { hash = new UInt256(assetID), name = symbol }; var tx = new Transaction(); tx.outputs = new Transaction.Output[] { new Transaction.Output() { assetID = assetID, scriptHash = scripthash, value = 1000000000 } }; tx.inputs = new Transaction.Input[] { }; txs.Add(tx); } GenerateBlock(txs); }
public VirtualChain(NeoAPI api, KeyPair owner, ChainTime time = null) { Reset(); if (time == null) { time = new RealTime(); } this.Time = time; var scripthash = new UInt160(owner.signatureHash.ToArray()); var txs = new List <Transaction>(); foreach (var entry in _assetMap) { var assetID = entry.Key; var tx = new Transaction(); tx.outputs = new Transaction.Output[] { new Transaction.Output() { assetID = assetID, scriptHash = scripthash, value = 1000000000 } }; tx.inputs = new Transaction.Input[] { }; txs.Add(tx); } GenerateBlock(txs); }
public override Dictionary <string, List <UnspentEntry> > GetUnspent(UInt160 hash) { var result = new Dictionary <string, List <UnspentEntry> >(); var account = Chain.GetAccount(hash); foreach (var entry in account.unspent) { var tx = Chain.GetTransaction(entry.prevHash); var output = tx.outputs[entry.prevIndex]; var unspent = new UnspentEntry() { index = entry.prevIndex, hash = entry.prevHash, value = output.value }; var symbol = NeoAPI.SymbolFromAssetID(output.assetID); List <UnspentEntry> list; if (result.ContainsKey(symbol)) { list = result[symbol]; } else { list = new List <UnspentEntry>(); result[symbol] = list; } list.Add(unspent); } return(result); }
public static uint FindBlock(NeoAPI api, DateTime date) { uint min = 0; var max = api.GetBlockHeight(); var timestamp = date.ToTimestamp(); return(FindBlock(api, timestamp, min, max)); }
public void SyncWithNode(NeoAPI api) { var max = api.GetBlockHeight(); var min = (uint)_blocks.Count; for (uint i = min; i <= max; i++) { var block = api.GetBlock(i); AddBlock(block); } }
public static Transaction MintTokens(NEP5 token, KeyPair buyer_key, string symbol, decimal amount) { var attachs = new List <Transaction.Output>(); attachs.Add(new Transaction.Output() { assetID = NeoAPI.GetAssetID(symbol), scriptHash = token.scriptHash, value = amount }); var response = token.api.CallContract(buyer_key, token.scriptHash, "mintTokens", new object[] { }, symbol, attachs); return(response); }
public Transaction ClaimGas(KeyPair ownerKey) { var targetScriptHash = new UInt160(ownerKey.address.AddressToScriptHash()); decimal amount; var claimable = GetClaimable(targetScriptHash, out amount); var references = new List <Transaction.Input>(); foreach (var entry in claimable) { references.Add(new Transaction.Input() { prevHash = entry.hash, prevIndex = entry.index }); } if (amount <= 0) { throw new ArgumentException("No GAS to claim at this address"); } List <Transaction.Input> inputs; List <Transaction.Output> outputs; GenerateInputsOutputs(ownerKey, "GAS", null, out inputs, out outputs); outputs.Add( new Transaction.Output() { scriptHash = targetScriptHash, assetID = NeoAPI.GetAssetID("GAS"), value = amount }); Transaction tx = new Transaction() { type = TransactionType.ClaimTransaction, version = 0, script = null, gas = -1, claimReferences = references.ToArray(), inputs = inputs.ToArray(), outputs = outputs.ToArray(), }; tx.Sign(ownerKey); var ok = SendTransaction(tx); return(ok ? tx : null); }
protected override void Reset() { base.Reset(); foreach (var entry in NeoAPI.Assets) { var symbol = entry.Key; var assetID = NeoAPI.GetAssetID(symbol); _assetMap[assetID] = new Asset() { hash = new UInt256(assetID), name = symbol }; } }
private void MergeTransaction(NeoAPI api, Transaction tx) { transactions[tx.Hash] = tx; foreach (var input in tx.inputs) { if (!transactions.ContainsKey(input.prevHash)) { var other = api.GetTransaction(input.prevHash); transactions[other.Hash] = other; external_txs.Add(other.Hash); } } }
// transfer to multiple addresses public Transaction Transfer(KeyPair from_key, Dictionary <byte[], decimal> transfers) { int max_transfer_count = 6; if (transfers.Count > max_transfer_count) { throw new ArgumentException("Max transfers per call = " + max_transfer_count); } var scripts = new List <byte[]>(); var sender_address_hash = from_key.address.GetScriptHashFromAddress(); int index = 0; foreach (var entry in transfers) { if (entry.Value <= 0) { var addr = new UInt160(entry.Key).ToAddress(); throw new ArgumentException($"Invalid amount {entry.Value} for address {addr}"); } BigInteger amount = ConvertToBigInt(entry.Value); var isLast = index == transfers.Count - 1; var args = new object[] { sender_address_hash, entry.Key, amount }; var bytes = NeoAPI.GenerateScript(scriptHash, new object[] { "transfer", args }, isLast); scripts.Add(bytes); index++; } var final_size = scripts.Sum(x => x.Length); byte[] final_script = new byte[final_size]; using (var stream = new MemoryStream(final_script)) { foreach (byte[] bytes in scripts) { stream.Write(bytes, 0, bytes.Length); } } var response = api.CallContract(from_key, scriptHash, final_script); return(response); }
private static uint FindBlock(NeoAPI api, uint timestamp, uint min, uint max) { var mid = (1 + max - min) / 2; do { var block = api.GetBlock(mid); var blockTime = block.Date.ToTimestamp(); if (blockTime == timestamp) { return(block.Height); } else if (blockTime < timestamp) { var next = api.GetBlock(mid + 1); var nextTime = next.Date.ToTimestamp(); if (nextTime == timestamp) { return(next.Height); } else if (nextTime > timestamp) { return(block.Height); } else { return(FindBlock(api, timestamp, mid + 1, max)); } } else { return(FindBlock(api, timestamp, min, mid - 1)); } } while (true); }
public BlockIterator(NeoAPI api) { this.currentBlock = api.GetBlockHeight(); this.currentTransaction = 0; }
public NEP5(NeoAPI api, string contractHash, string name, BigInteger decimals) : this(api, contractHash) { this._decimals = decimals; this._name = name; }
public NEP5(NeoAPI api, UInt160 contractHash) { this.api = api; this.scriptHash = contractHash; }
public NEP5(NeoAPI api, byte[] contractHash) : this(api, new UInt160(contractHash)) { }
public NEP5(NeoAPI api, string contractHash) : this(api, NeoAPI.GetScriptHashFromString(contractHash)) { }
public void Execute(NeoAPI api, UInt160 script_hash, Action <ListenerVM> visitor) { var balances = new Dictionary <UInt160, decimal>(); var vm = new ListenerVM(this); /*vm.AddScript(token_script); * * var debugger = new DebugClient(); * debugger.SendScript(token_script); */ throw new NotImplementedException(); IEnumerable <Block> sorted_blocks = blocks.Values.OrderBy(x => x.Date); foreach (var block in sorted_blocks) { vm.SetCurrentBlock(block); bool executed = false; foreach (var tx in block.transactions) { switch (tx.type) { case TransactionType.InvocationTransaction: { List <AVMInstruction> ops; try { ops = NeoTools.Disassemble(tx.script); } catch { continue; } for (int i = 0; i < ops.Count; i++) { var op = ops[i]; if (op.opcode == OpCode.APPCALL && op.data != null && op.data.Length == 20) { var otherScriptHash = new UInt160(op.data); if (otherScriptHash != script_hash) { continue; } var engine = new ExecutionEngine(tx, vm, vm); engine.LoadScript(tx.script); engine.Execute( x => { //debugger.Step(x); } ); executed = true; } } break; } } } if (executed) { visitor(vm); } } }
// claim from contract, without having private key public Transaction ClaimGas(KeyPair ownerKey, UInt160 fromScripthash, byte[] verificationScript) { var check = verificationScript.ToScriptHash(); if (check != fromScripthash) { throw new ArgumentException("Invalid verification script"); } decimal amount; var claimable = GetClaimable(fromScripthash, out amount); var references = new List <Transaction.Input>(); foreach (var entry in claimable) { references.Add(new Transaction.Input() { prevHash = entry.hash, prevIndex = entry.index }); } if (amount <= 0) { throw new ArgumentException("No GAS to claim at this address"); } List <Transaction.Input> inputs; List <Transaction.Output> outputs; GenerateInputsOutputs(ownerKey, "GAS", null, out inputs, out outputs); outputs.Add( new Transaction.Output() { scriptHash = fromScripthash, assetID = NeoAPI.GetAssetID("GAS"), value = amount }); Transaction tx = new Transaction() { type = TransactionType.ClaimTransaction, version = 0, script = null, gas = -1, claimReferences = references.ToArray(), inputs = inputs.ToArray(), outputs = outputs.ToArray(), }; var witness = new Witness { invocationScript = ("0014" + ownerKey.address.AddressToScriptHash().ByteToHex()).HexToBytes(), verificationScript = verificationScript }; tx.Sign(ownerKey, new Witness[] { witness }); var ok = SendTransaction(tx); return(ok ? tx : null); }
public Snapshot(UInt160 scriptHash, NeoAPI api, uint startBlock, uint endBlock = 0) { if (endBlock == 0) { endBlock = api.GetBlockHeight(); } if (endBlock < startBlock) { throw new ArgumentException("End block cannot be smaller than start block"); } for (uint height = startBlock; height <= endBlock; height++) { var block = api.GetBlock(height); var snapCount = 0; foreach (var tx in block.transactions) { switch (tx.type) { case TransactionType.ContractTransaction: { foreach (var output in tx.outputs) { if (output.scriptHash == scriptHash) { MergeTransaction(api, tx); snapCount++; break; } } break; } case TransactionType.InvocationTransaction: { List <AVMInstruction> ops; try { ops = NeoTools.Disassemble(tx.script); } catch { continue; } for (int i = 0; i < ops.Count; i++) { var op = ops[i]; if (op.opcode == OpCode.APPCALL && op.data != null && op.data.Length == 20) { var otherScriptHash = new UInt160(op.data); if (otherScriptHash == scriptHash) { MergeTransaction(api, tx); snapCount++; break; } } } break; } } } if (snapCount > 0) { blocks[block.Hash] = block; } } }