public async Task <Result <decimal> > GetFa12AllowanceAsync( string holderAddress, string spenderAddress, string callingAddress, SecureBytes securePublicKey, CancellationToken cancellationToken = default) { var tokenConfig = _currency as Fa12Config; try { var rpc = new Rpc(_rpcNodeUri); var tx = new TezosTransaction { Currency = tokenConfig.Name, From = callingAddress, To = tokenConfig.TokenContractAddress, Fee = 0, //token.GetAllowanceFee, GasLimit = tokenConfig.GetAllowanceGasLimit, StorageLimit = 0, //token.GetAllowanceStorageLimit, Params = CreateGetAllowanceParams(holderAddress, spenderAddress, tokenConfig.ViewContractAddress), UseRun = false, UseOfflineCounter = false }; _ = await tx .FillOperationsAsync( securePublicKey : securePublicKey, tezosConfig : tokenConfig, cancellationToken : cancellationToken) .ConfigureAwait(false); var runResults = await rpc .RunOperations(tx.Head, tx.Operations) .ConfigureAwait(false); return(runResults ?["contents"] ?.LastOrDefault() ?["metadata"] ?["internal_operation_results"] ?[0] ?["result"] ?["errors"] ?[1] ?["with"] ?["args"] ?[0] ?["args"] ?[0] ?["int"] ?.Value <decimal>() ?? 0); } catch (Exception e) { return(new Error(Errors.RequestError, e.Message)); } }
private Result <TezosTransaction> ParseFA12Params(TezosTransaction tx, JObject transaction) { var tokenContractAddress = (_currency as TezosTokens.FA12).TokenContractAddress; if (transaction["target"]?["address"]?.ToString() != tokenContractAddress) { Log.Error( "Error while parsing token transactions {@Id}", transaction["hash"].ToString()); return(null); } //if (transaction["hasInternals"].Value<bool>()) // return null; tx.Fee = transaction["bakerFee"].Value <decimal>(); tx.GasLimit = transaction["gasLimit"].Value <decimal>(); tx.StorageLimit = transaction["storageLimit"].Value <decimal>(); var parameters = transaction.ContainsKey("parameters") ? JObject.Parse(transaction["parameters"].Value <string>()) : null; if (parameters?["entrypoint"]?.ToString() == "approve") { tx.Type = BlockchainTransactionType.TokenApprove; tx.From = transaction["sender"]?["address"]?.ToString(); tx.To = transaction["target"]?["address"]?.ToString(); tx.Amount = 0; } else if (parameters?["entrypoint"]?.ToString() == "transfer") { if (parameters?["value"]?["args"]?[0]?["string"] != null) { tx.From = parameters?["value"]?["args"]?[0]?["string"]?.ToString(); tx.To = parameters?["value"]?["args"]?[1]?["args"]?[0]?["string"]?.ToString(); } else { tx.From = Unforge.UnforgeAddress(parameters?["value"]?["args"]?[0]?["bytes"]?.ToString()); tx.To = Unforge.UnforgeAddress(parameters?["value"]?["args"]?[1]?["args"]?[0]?["bytes"]?.ToString()); } tx.Amount = parameters?["value"]?["args"]?[1]?["args"]?[1]?["int"]?.Value <decimal>() ?? 0; } else { Log.Error( "Error while parsing FA12 token transactions {@Id}", transaction["hash"].ToString()); return(null); } tx.Params = parameters; return(tx); }
public override async Task <Result <IBlockchainTransaction> > GetTransactionAsync( string txId, CancellationToken cancellationToken = default) { var transaction = new TezosTransaction(); var isParentTxValid = false; var requestUri = $"operations/transactions/{txId}?micheline=2"; return(await HttpHelper .GetAsyncResult <IBlockchainTransaction>( baseUri : _baseUri, requestUri : requestUri, headers : _headers, responseHandler : (response, content) => { var txResult = ParseTxs(JsonConvert.DeserializeObject <JArray>(content)); if (txResult.HasError) { return txResult.Error; } if (!txResult.Value.Any()) { return null; } var internalTxs = new List <TezosTransaction>(); foreach (var tx in txResult.Value) { if (!tx.IsInternal) { transaction = tx; isParentTxValid = true; } else { internalTxs.Add(tx); } } transaction.InternalTxs = internalTxs; // replace non valid parent tx by internal tx if (isParentTxValid == false && internalTxs.Count == 1) { transaction = internalTxs.First(); } return transaction; }, cancellationToken : cancellationToken) .ConfigureAwait(false)); }
public async Task <Result <decimal> > GetTokenAllowanceAsync( string holderAddress, string spenderAddress, string callingAddress, SecureBytes securePublicKey, CancellationToken cancellationToken = default) { var token = _currency as TezosTokens.FA12; try { var rpc = new Rpc(_rpcNodeUri); var head = await rpc .GetHeader() .ConfigureAwait(false); var tx = new TezosTransaction { Currency = token, From = callingAddress, To = token.TokenContractAddress, Fee = 0, //token.GetAllowanceFee, GasLimit = token.GetAllowanceGasLimit, StorageLimit = 0, //token.GetAllowanceStorageLimit, Params = GetAllowanceParams(holderAddress, spenderAddress, token.ViewContractAddress), }; await tx.FillOperationsAsync( head : head, securePublicKey : securePublicKey, incrementCounter : false, cancellationToken : cancellationToken) .ConfigureAwait(false); var runResults = await rpc .RunOperations(head, tx.Operations) .ConfigureAwait(false); Log.Debug("getTokenAllowance result {@result}", runResults); return(runResults?["contents"]?.LastOrDefault()?["metadata"]?["internal_operation_results"]?[0]?["result"]?["errors"]?[1]?["with"]?["args"]?[0]?["args"]?[0]?["int"]?.Value <decimal>()); } catch (Exception e) { return(new Error(Errors.RequestError, e.Message)); } }
public TezosTransaction Clone() { var resTx = new TezosTransaction() { Id = Id, Currency = Currency, State = State, Type = Type, CreationTime = CreationTime, From = From, To = To, Amount = Amount, Fee = Fee, GasLimit = GasLimit, GasUsed = GasUsed, StorageLimit = StorageLimit, Burn = Burn, Alias = Alias, Params = Params, IsInternal = IsInternal, InternalIndex = InternalIndex, InternalTxs = new List <TezosTransaction>(), BlockInfo = (BlockInfo)(BlockInfo?.Clone() ?? null) }; if (InternalTxs != null) { foreach (var intTx in InternalTxs) { resTx.InternalTxs.Add(intTx.Clone()); } } return(resTx); }
public TezosTransaction Clone() { var resTx = new TezosTransaction() { Id = this.Id, Currency = this.Currency, State = this.State, Type = this.Type, CreationTime = this.CreationTime, From = this.From, To = this.To, Amount = this.Amount, Fee = this.Fee, GasLimit = this.GasLimit, GasUsed = this.GasUsed, StorageLimit = this.StorageLimit, Burn = this.Burn, Params = this.Params, IsInternal = this.IsInternal, InternalIndex = this.InternalIndex, InternalTxs = new List <TezosTransaction>(), BlockInfo = (BlockInfo)(this.BlockInfo?.Clone() ?? null) }; if (this.InternalTxs != null) { foreach (var intTx in this.InternalTxs) { resTx.InternalTxs.Add(intTx.Clone()); } } return(resTx); }
private Result <IEnumerable <TezosTransaction> > ParseTxs(JArray data) { var result = new List <TezosTransaction>(); foreach (var op in data) { if (!(op is JObject transaction)) { return(new Error(Errors.NullOperation, "Null operation in response")); } var state = StateFromStatus(transaction["status"].Value <string>()); var tx = new TezosTransaction() { Id = transaction["hash"].ToString(), Currency = _currency, State = state, Type = BlockchainTransactionType.Unknown, CreationTime = DateTime.SpecifyKind(DateTime.Parse(transaction["timestamp"].ToString()), DateTimeKind.Utc), GasUsed = transaction["gasUsed"].Value <decimal>(), Burn = transaction["storageFee"].Value <decimal>() + transaction["allocationFee"].Value <decimal>(), IsInternal = transaction.ContainsKey("nonce"), //tx.IsInternal = tx.From == ((TezosTokens.FA12) _currency).SwapContractAddress; InternalIndex = transaction["nonce"]?.Value <int>() ?? 0, BlockInfo = new BlockInfo { Confirmations = state == BlockchainTransactionState.Failed ? 0 : 1, BlockHash = null, BlockHeight = transaction["level"].Value <long>(), BlockTime = DateTime.SpecifyKind(DateTime.Parse(transaction["timestamp"].ToString()), DateTimeKind.Utc), FirstSeen = DateTime.SpecifyKind(DateTime.Parse(transaction["timestamp"].ToString()), DateTimeKind.Utc) } }; if (_currency.Name != Tezos) { if (_currency.Name == NYX) { tx = ParseNYXParams(tx, transaction).Value; } else if (_currency.Name == FA2) { tx = ParseFA2Params(tx, transaction).Value; } else { tx = ParseFA12Params(tx, transaction).Value; } } else { tx.From = transaction["sender"]?["address"]?.ToString(); tx.To = transaction["target"]?["address"]?.ToString(); tx.Amount = transaction["amount"].Value <decimal>(); if (tx.IsInternal) { tx.InternalIndex = transaction["nonce"]?.Value <int>() ?? 0; } else { var txParameters = transaction.ContainsKey("parameters") ? JObject.Parse(transaction["parameters"].Value <string>()) : null; tx.Params = txParameters; tx.Fee = transaction["bakerFee"].Value <decimal>(); tx.GasLimit = transaction["gasLimit"].Value <decimal>(); tx.StorageLimit = transaction["storageLimit"].Value <decimal>(); } } if (tx != null) { result.Add(tx); } } return(result); }