示例#1
0
        public static IEnumerator GetDescription(byte[] script, Action <string, string> callback)
        {
            foreach (var entry in methodTable.Keys)
            {
                Debug.Log("disam method: " + entry);
            }

            if (knownContracts == null)
            {
                // Collecting known contract names
                knownContracts = methodTable.Keys.Select(x => x.IndexOf(".") > 0 ? x.Substring(0, x.IndexOf(".")) : x).Distinct().ToList();
            }

            var accountManager = AccountManager.Instance;

            var contracts          = DisasmUtils.ExtractContractNames(script).Where(x => !knownContracts.Contains(x));
            var contractsToLoad    = contracts.Count();
            var contractsProcessed = 0;

            foreach (var contract in contracts)
            {
                WalletGUI.Instance.StartCoroutine(
                    accountManager.phantasmaApi.GetContract(contract, (contractStruct) =>
                {
                    Log.Write($"Registering {contractStruct.methods.Length} methods for {contract}");

                    foreach (var method in contractStruct.methods)
                    {
                        Log.Write($"Registering contract method {contract}.{method.name} with {method.parameters.Length} parameters");
                        DescriptionUtils.RegisterContractMethod($"{contract}.{method.name}", method.parameters.Length);
                    }

                    contractsProcessed++;
                }, (error, msg) =>
                {
                    Log.WriteWarning("Could not fetch contract info: " + contract);
                    contractsProcessed++;
                }));
            }

            while (contractsProcessed < contractsToLoad)
            {
                yield return(null);
            }

            IEnumerable <DisasmMethodCall> disasm;

            try
            {
                disasm = DisasmUtils.ExtractMethodCalls(script, methodTable);
            }
            catch (Exception e)
            {
                callback(null, e.Message);
                yield break;
            }

            // Checking if all calls are "market.SellToken" calls only or "Runtime.TransferToken" only,
            // and we can group them.
            int groupSize             = 0;
            DisasmMethodCall?prevCall = null;

            foreach (var call in disasm)
            {
                if (CheckIfCallShouldBeIgnored(call))
                {
                    continue;
                }

                if (GetCallFullName(call) == "Runtime.TransferToken")
                {
                    if (prevCall != null && !CompareCalls((DisasmMethodCall)prevCall, call, 0, 1))
                    {
                        groupSize = 0;
                        break;
                    }

                    groupSize++;
                }
                else if (GetCallFullName(call) == "market.SellToken")
                {
                    if (prevCall != null && !CompareCalls((DisasmMethodCall)prevCall, call, 0, 2, 4, 5))
                    {
                        groupSize = 0;
                        break;
                    }

                    groupSize++;
                }
                else
                {
                    // Different call, grouping is not supported.
                    groupSize = 0;
                    break;
                }

                prevCall = call;
            }

            int transferTokenCounter = 0; // Counting "market.TransferToken" calls, needed for grouping.
            int sellTokenCounter     = 0; // Counting "market.SellToken" calls, needed for grouping.

            var sb = new StringBuilder();

            foreach (var entry in disasm)
            {
                if (CheckIfCallShouldBeIgnored(entry))
                {
                    continue;
                }

                // Put it to log so that developer can easily check what PG is receiving.
                Log.Write("GetDescription(): Contract's description: " + entry.ToString());

                switch (GetCallFullName(entry))
                {
                case "Runtime.TransferToken":
                {
                    var src       = GetStringArg(entry, 0);
                    var dst       = GetStringArg(entry, 1);
                    var symbol    = GetStringArg(entry, 2);
                    var nftNumber = GetStringArg(entry, 3);

                    if (groupSize > 1)
                    {
                        if (transferTokenCounter == 0)
                        {
                            // Desc line #1.
                            sb.AppendLine("\u2605 Transfer:");
                        }

                        if (transferTokenCounter == groupSize - 1)
                        {
                            // Desc line for token #N.
                            sb.AppendLine($"{symbol} NFT #{ShortenTokenId(nftNumber)}");
                            sb.AppendLine($"to {dst}.");
                        }
                        else
                        {
                            // Desc line for tokens #1 ... N-1.
                            sb.AppendLine($"{symbol} NFT #{ShortenTokenId(nftNumber)},");
                        }
                    }
                    else
                    {
                        sb.AppendLine($"\u2605 Transfer {symbol} NFT #{ShortenTokenId(nftNumber)} to {dst}.");
                    }

                    transferTokenCounter++;

                    break;
                }

                case "Runtime.TransferTokens":
                {
                    var src    = GetStringArg(entry, 0);
                    var dst    = GetStringArg(entry, 1);
                    var symbol = GetStringArg(entry, 2);
                    var amount = GetNumberArg(entry, 3);

                    Token token;
                    accountManager.GetTokenBySymbol(symbol, PlatformKind.Phantasma, out token);

                    var total = UnitConversion.ToDecimal(amount, token.decimals);

                    sb.AppendLine($"\u2605 Transfer {total} {symbol} from {src} to {dst}.");
                    break;
                }

                case "market.BuyToken":
                {
                    var dst       = GetStringArg(entry, 0);
                    var symbol    = GetStringArg(entry, 1);
                    var nftNumber = GetStringArg(entry, 2);

                    sb.AppendLine($"\u2605 Buy {symbol} NFT #{ShortenTokenId(nftNumber)}.");
                    break;
                }

                case "market.CancelSale":
                {
                    var symbol    = GetStringArg(entry, 0);
                    var nftNumber = GetStringArg(entry, 1);

                    sb.AppendLine($"\u2605 Cancel sale of {symbol} NFT #{ShortenTokenId(nftNumber)}.");
                    break;
                }

                case "market.SellToken":
                {
                    var dst         = GetStringArg(entry, 0);
                    var tokenSymbol = GetStringArg(entry, 1);
                    var priceSymbol = GetStringArg(entry, 2);
                    var nftNumber   = GetStringArg(entry, 3);

                    Token priceToken;
                    accountManager.GetTokenBySymbol(priceSymbol, PlatformKind.Phantasma, out priceToken);

                    var price = UnitConversion.ToDecimal(GetNumberArg(entry, 4), priceToken.decimals);

                    var untilDate = GetTimestampArg(entry, 5);

                    if (groupSize > 1)
                    {
                        if (sellTokenCounter == 0)
                        {
                            // Desc line #1.
                            sb.AppendLine("\u2605 Sell:");
                            sb.AppendLine($"{tokenSymbol} NFT #{ShortenTokenId(nftNumber)},");
                        }
                        else if (sellTokenCounter == groupSize - 1)
                        {
                            // Desc line #N.
                            sb.AppendLine($"{tokenSymbol} NFT #{ShortenTokenId(nftNumber)}");
                            sb.AppendLine($"for {price} {priceSymbol} each, offer valid until {untilDate}.");
                        }
                        else
                        {
                            // Desc lines #2 ... N-1.
                            sb.AppendLine($"{tokenSymbol} NFT #{ShortenTokenId(nftNumber)},");
                        }
                    }
                    else
                    {
                        sb.AppendLine($"\u2605 Sell {tokenSymbol} NFT #{ShortenTokenId(nftNumber)} for {price} {priceSymbol}, offer valid until {untilDate}.");
                    }

                    sellTokenCounter++;

                    break;
                }

                case "market.EditAuction":
                {
                    var dst         = GetStringArg(entry, 0);
                    var tokenSymbol = GetStringArg(entry, 1);
                    var priceSymbol = GetStringArg(entry, 2);
                    var nftNumber   = GetStringArg(entry, 3);

                    Token priceToken;
                    accountManager.GetTokenBySymbol(priceSymbol, PlatformKind.Phantasma, out priceToken);

                    var price    = UnitConversion.ToDecimal(GetNumberArg(entry, 4), priceToken.decimals);
                    var endPrice = UnitConversion.ToDecimal(GetNumberArg(entry, 5), priceToken.decimals);

                    var startDate       = GetTimestampArg(entry, 6);
                    var untilDate       = GetTimestampArg(entry, 7);
                    var extensionPeriod = GetStringArg(entry, 8);

                    sb.AppendLine($"\u2605 Edit {tokenSymbol} NFT #{ShortenTokenId(nftNumber)} Auction.");
                    break;
                }

                case "market.ListToken":
                {
                    var dst         = GetStringArg(entry, 0);
                    var tokenSymbol = GetStringArg(entry, 1);
                    var priceSymbol = GetStringArg(entry, 2);
                    var nftNumber   = GetStringArg(entry, 3);

                    Token priceToken;
                    accountManager.GetTokenBySymbol(priceSymbol, PlatformKind.Phantasma, out priceToken);

                    var price    = UnitConversion.ToDecimal(GetNumberArg(entry, 4), priceToken.decimals);
                    var endPrice = UnitConversion.ToDecimal(GetNumberArg(entry, 5), priceToken.decimals);

                    var startDate         = GetTimestampArg(entry, 6);
                    var untilDate         = GetTimestampArg(entry, 7);
                    var extensionPeriod   = GetStringArg(entry, 8);
                    var typeAuction       = GetNumberArg(entry, 9);
                    var listingFee        = GetStringArg(entry, 10);
                    var listingFeeAddress = GetStringArg(entry, 11);

                    if (typeAuction == 0)
                    {
                        sb.AppendLine($"\u2605 List {tokenSymbol} NFT #{ShortenTokenId(nftNumber)} for a Fixed Auction with a price of {price} {priceSymbol}.");
                        break;
                    }
                    else if (typeAuction == 1)
                    {
                        sb.AppendLine($"\u2605 List {tokenSymbol} NFT #{ShortenTokenId(nftNumber)} for a Classic Auction with a starting price of {price} {priceSymbol}.");
                        break;
                    }
                    else if (typeAuction == 2)
                    {
                        sb.AppendLine($"\u2605 List {tokenSymbol} NFT #{ShortenTokenId(nftNumber)} for a Reserve Auction with a reserve price of {price} {priceSymbol}.");
                        break;
                    }
                    else if (typeAuction == 3)
                    {
                        sb.AppendLine($"\u2605 List {tokenSymbol} NFT #{ShortenTokenId(nftNumber)} for a Dutch Auction with a starting price of {price} {priceSymbol} and an end price of {endPrice} {priceSymbol}.");
                        break;
                    }
                    break;
                }

                case "market.BidToken":
                {
                    var dst         = GetStringArg(entry, 0);
                    var tokenSymbol = GetStringArg(entry, 1);
                    var nftNumber   = GetStringArg(entry, 2);

                    //Token priceToken;
                    //accountManager.GetTokenBySymbol(priceSymbol, PlatformKind.Phantasma, out priceToken);

                    //var price = UnitConversion.ToDecimal(GetNumberArg(entry, 3), priceToken.decimals);

                    var buyingFee        = GetStringArg(entry, 4);
                    var buyingFeeAddress = GetStringArg(entry, 5);


                    sb.AppendLine($"\u2605 Bid or Buy {tokenSymbol} NFT #{ShortenTokenId(nftNumber)}.");
                    break;
                }

                case "sale.Purchase":
                {
                    var saleHash    = GetStringArg(entry, 1);
                    var tokenSymbol = GetStringArg(entry, 2);
                    var tokenAmount = GetStringArg(entry, 3);

                    Token priceToken;
                    accountManager.GetTokenBySymbol(tokenSymbol, PlatformKind.Phantasma, out priceToken);

                    var purchase = UnitConversion.ToDecimal(GetNumberArg(entry, 4), priceToken.decimals);

                    sb.AppendLine($"\u2605 Participate to sale {saleHash} with {purchase} {tokenSymbol}.");
                    break;
                }

                case "Runtime.MintToken":
                {
                    var owner     = GetStringArg(entry, 0);
                    var recepient = GetStringArg(entry, 1);
                    var symbol    = GetStringArg(entry, 2);
                    var bytes     = GetByteArrayArg(entry, 3);

                    sb.AppendLine($"\u2605 Mint {symbol} NFT from {owner} with {recepient} as recipient.");
                    break;
                }

                case "Runtime.BurnTokens":
                {
                    var address = GetStringArg(entry, 0);
                    var symbol  = GetStringArg(entry, 1);
                    var amount  = GetNumberArg(entry, 2);

                    Token token;
                    accountManager.GetTokenBySymbol(symbol, PlatformKind.Phantasma, out token);

                    var total = UnitConversion.ToDecimal(amount, token.decimals);

                    sb.AppendLine($"\u2605 Burn {total} {symbol} from {address}.");
                    break;
                }

                case "Runtime.BurnToken":
                {
                    var address   = GetStringArg(entry, 0);
                    var symbol    = GetStringArg(entry, 1);
                    var nftNumber = GetStringArg(entry, 2);

                    sb.AppendLine($"\u2605 Burn {symbol} NFT #{ShortenTokenId(nftNumber)} from {address}.");
                    break;
                }

                case "Runtime.InfuseToken":
                {
                    var address      = GetStringArg(entry, 0);
                    var targetSymbol = GetStringArg(entry, 1);
                    var tokenID      = GetStringArg(entry, 2);
                    var infuseSymbol = GetStringArg(entry, 3);
                    var amount       = GetNumberArg(entry, 4);
                    var amountString = amount.ToString();

                    Token infuseToken;
                    accountManager.GetTokenBySymbol(infuseSymbol, PlatformKind.Phantasma, out infuseToken);

                    sb.AppendLine($"\u2605 Infuse {targetSymbol} NFT #{ShortenTokenId(tokenID)} with " + (infuseToken.flags.Contains("Fungible") ? $"{UnitConversion.ToDecimal(amount, infuseToken.decimals)} {infuseSymbol}." : $"{infuseSymbol} NFT #{ShortenTokenId(amountString)}."));
                    break;
                }

                case "Nexus.CreateToken":
                {
                    var address   = GetStringArg(entry, 0);
                    var symbol    = GetStringArg(entry, 1);
                    var name      = GetStringArg(entry, 2);
                    var maxSupply = GetNumberArg(entry, 3);
                    var decimals  = GetNumberArg(entry, 4);
                    var flags     = GetNumberArg(entry, 5);
                    var ctScript  = GetByteArrayArg(entry, 6);

                    sb.AppendLine($"\u2605 Create token {symbol} with name '{name}', {maxSupply} max supply, {decimals} decimals from {address}.");
                    break;
                }

                case "GHOST.getLockedContent":
                {
                    var nftSymbol = GetStringArg(entry, 0);
                    var nftID     = GetStringArg(entry, 1);

                    sb.AppendLine($"\u2605 Get locked content for {nftSymbol} #{ShortenTokenId(nftID)}.");
                    break;
                }

                case "GHOST.mintToken":
                {
                    var editionId         = GetNumberArg(entry, 0);
                    var editionMax        = GetNumberArg(entry, 1);
                    var editionMode       = GetNumberArg(entry, 2);
                    var creator           = GetStringArg(entry, 3);
                    var royalties         = GetNumberArg(entry, 4);
                    var mintTicker        = GetStringArg(entry, 5);
                    var numOfNfts         = GetNumberArg(entry, 6);
                    var name              = GetStringArg(entry, 7);
                    var description       = GetStringArg(entry, 8);
                    var type              = GetStringArg(entry, 9);
                    var imageURL          = GetStringArg(entry, 10);
                    var infoURL           = GetStringArg(entry, 11);
                    var attributeType1    = GetStringArg(entry, 12);
                    var attributeValue1   = GetStringArg(entry, 13);
                    var attributeType2    = GetStringArg(entry, 14);
                    var attributeValue2   = GetStringArg(entry, 15);
                    var attributeType3    = GetStringArg(entry, 16);
                    var attributeValue3   = GetStringArg(entry, 17);
                    var lockedContent     = GetStringArg(entry, 18);
                    var listPrice         = GetNumberArg(entry, 19);
                    var listPriceCurrency = GetStringArg(entry, 20);
                    var listLastEndDate   = GetTimestampArg(entry, 21);
                    var infusedAsset      = GetStringArg(entry, 22);
                    var infusedAmount     = GetNumberArg(entry, 23);
                    var hasLocked         = GetStringArg(entry, 24);

                    if (editionId > 0)
                    {
                        sb.AppendLine($"\u2605 Mint on existing series #{editionId}, a total of {numOfNfts}x {mintTicker}.");
                    }
                    else
                    {
                        sb.AppendLine($"\u2605 Mint on a new series {numOfNfts}x {mintTicker}, with a {royalties}% royalty and named: {name}.");
                    }
                    if (infusedAmount > 0)
                    {
                        accountManager.GetTokenBySymbol(infusedAsset, PlatformKind.Phantasma, out var infusedToken);
                        var infusedAmountWithDecimals = infusedToken.flags.Contains("Fungible") ? UnitConversion.ToDecimal(infusedAmount, infusedToken.decimals) : 0;

                        sb.AppendLine($"\u2605 Infuse {numOfNfts}x {mintTicker} with {(infusedAmountWithDecimals > 0 ? infusedAmountWithDecimals.ToString() : infusedAmount.ToString())} {infusedAsset} each.");
                    }
                    if (listPrice > 0)
                    {
                        accountManager.GetTokenBySymbol(listPriceCurrency, PlatformKind.Phantasma, out var listPriceToken);
                        var listPriceWithDecimals = (listPrice > 0) ? UnitConversion.ToDecimal(listPrice, listPriceToken.decimals) : 0;

                        sb.AppendLine($"\u2605 Sell {numOfNfts}x {mintTicker}, for {listPriceWithDecimals} {listPriceCurrency}, offer valid until {listLastEndDate}.");
                    }
                    break;
                }

                default:
                    sb.AppendLine(entry.ToString());
                    break;
                }
            }

            if (sb.Length > 0)
            {
                callback(sb.ToString(), null);
                yield break;
            }

            callback(null, "Unknown transaction content.");
        }
示例#2
0
        protected override void SignTransaction(string platform, SignatureKind kind, string chain, byte[] script, byte[] payload, int id, Action <Hash, string> callback)
        {
            var accountManager = AccountManager.Instance;

            var targetPlatform = RequestPlatform(platform);

            if (targetPlatform == PlatformKind.None)
            {
                callback(Hash.Null, "Unsupported platform: " + platform);
                return;
            }

            var state = AccountManager.Instance.CurrentState;

            if (state == null)
            {
                callback(Hash.Null, "not logged in");
                return;
            }

            var nexus   = AccountManager.Instance.Settings.nexusName;
            var account = AccountManager.Instance.CurrentAccount;

            WalletGUI.Instance.CallOnUIThread(() =>
            {
                try
                {
                    WalletGUI.Instance.StartCoroutine(DescriptionUtils.GetDescription(script, (description, error) => {
                        if (description == null)
                        {
                            WalletGUI.Instance.MessageBox(MessageKind.Error, "Error during description parsing.\nContact the developers.\nDetails: " + error);
                            callback(Hash.Null, "description parsing error");
                            return;
                        }

                        WalletGUI.Instance.Prompt("Allow dapp to send a transaction on your behalf?\n" + description, (success) =>
                        {
                            if (success)
                            {
                                WalletGUI.Instance.SendTransaction(description, script, payload, chain, ProofOfWork.None, (hash) =>
                                {
                                    AppFocus.Instance.EndFocus();

                                    if (hash != Hash.Null)
                                    {
                                        callback(hash, null);
                                    }
                                    else
                                    {
                                        callback(Hash.Null, "something bad happend while sending");
                                    }
                                });
                            }
                            else
                            {
                                AppFocus.Instance.EndFocus();
                                callback(Hash.Null, "user rejected");
                            }
                        });
                    }));
                }
                catch (Exception e)
                {
                    WalletGUI.Instance.MessageBox(MessageKind.Error, "Error during description parsing.\nContact the developers.\nDetails: " + e.Message);
                    callback(Hash.Null, "description parsing error");
                    return;
                }
            });
        }
示例#3
0
        protected override void SignTransaction(string nexus, string chain, byte[] script, byte[] payload, int id, Action <Hash, string> callback)
        {
            var state = AccountManager.Instance.CurrentState;

            if (state == null)
            {
                callback(Hash.Null, "not logged in");
                return;
            }

            var expectedNexus = AccountManager.Instance.Settings.nexusName;

            if (nexus != expectedNexus)
            {
                callback(Hash.Null, "nexus mismatch, expected: " + expectedNexus);
                return;
            }

            var account = AccountManager.Instance.CurrentAccount;

            if (account.platforms.HasFlag(PlatformKind.Phantasma))
            {
                WalletGUI.Instance.CallOnUIThread(() =>
                {
                    string description;
                    try
                    {
                        description = DescriptionUtils.GetDescription(script);
                    }
                    catch (Exception e)
                    {
                        WalletGUI.Instance.MessageBox(MessageKind.Error, "Error during description parsing.\nContact the developers.\nDetails: " + e.Message);
                        callback(Hash.Null, "description parsing error");
                        return;
                    }
                    WalletGUI.Instance.Prompt("Allow dapp to send a transaction on your behalf?\n" + description, (success) =>
                    {
                        if (success)
                        {
                            // TODO show description of transfer :^)
                            WalletGUI.Instance.SendTransaction(description, script, payload, chain, (hash) =>
                            {
                                if (hash != Hash.Null)
                                {
                                    callback(hash, null);
                                }
                                else
                                {
                                    callback(Hash.Null, "something bad happend while sending");
                                }
                            });
                        }
                        else
                        {
                            callback(Hash.Null, "user rejected");
                        }
                    });
                });
            }
            else
            {
                callback(Hash.Null, "current account does not support Phantasma platform");
            }
        }