-
Notifications
You must be signed in to change notification settings - Fork 100
/
Nep17API.cs
149 lines (134 loc) · 6.25 KB
/
Nep17API.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
using Neo.Cryptography.ECC;
using Neo.Network.P2P.Payloads;
using Neo.Network.RPC.Models;
using Neo.SmartContract;
using Neo.VM;
using Neo.Wallets;
using System;
using System.Linq;
using System.Numerics;
using System.Threading.Tasks;
using static Neo.Helper;
namespace Neo.Network.RPC
{
/// <summary>
/// Call NEP17 methods with RPC API
/// </summary>
public class Nep17API : ContractClient
{
/// <summary>
/// Nep17API Constructor
/// </summary>
/// <param name="rpcClient">the RPC client to call NEO RPC methods</param>
public Nep17API(RpcClient rpcClient) : base(rpcClient) { }
/// <summary>
/// Get balance of NEP17 token
/// </summary>
/// <param name="scriptHash">contract script hash</param>
/// <param name="account">account script hash</param>
/// <returns></returns>
public async Task<BigInteger> BalanceOfAsync(UInt160 scriptHash, UInt160 account)
{
var result = await TestInvokeAsync(scriptHash, "balanceOf", account).ConfigureAwait(false);
BigInteger balance = result.Stack.Single().GetInteger();
return balance;
}
/// <summary>
/// Get symbol of NEP17 token
/// </summary>
/// <param name="scriptHash">contract script hash</param>
/// <returns></returns>
public async Task<string> SymbolAsync(UInt160 scriptHash)
{
var result = await TestInvokeAsync(scriptHash, "symbol").ConfigureAwait(false);
return result.Stack.Single().GetString();
}
/// <summary>
/// Get decimals of NEP17 token
/// </summary>
/// <param name="scriptHash">contract script hash</param>
/// <returns></returns>
public async Task<byte> DecimalsAsync(UInt160 scriptHash)
{
var result = await TestInvokeAsync(scriptHash, "decimals").ConfigureAwait(false);
return (byte)result.Stack.Single().GetInteger();
}
/// <summary>
/// Get total supply of NEP17 token
/// </summary>
/// <param name="scriptHash">contract script hash</param>
/// <returns></returns>
public async Task<BigInteger> TotalSupplyAsync(UInt160 scriptHash)
{
var result = await TestInvokeAsync(scriptHash, "totalSupply").ConfigureAwait(false);
return result.Stack.Single().GetInteger();
}
/// <summary>
/// Get token information in one rpc call
/// </summary>
/// <param name="scriptHash">contract script hash</param>
/// <returns></returns>
public async Task<RpcNep17TokenInfo> GetTokenInfoAsync(UInt160 scriptHash)
{
byte[] script = Concat(
scriptHash.MakeScript("symbol"),
scriptHash.MakeScript("decimals"),
scriptHash.MakeScript("totalSupply"));
var contractState = await rpcClient.GetContractStateAsync(scriptHash.ToString()).ConfigureAwait(false);
var name = contractState.Manifest.Name;
var result = await rpcClient.InvokeScriptAsync(script).ConfigureAwait(false);
var stack = result.Stack;
return new RpcNep17TokenInfo
{
Name = name,
Symbol = stack[0].GetString(),
Decimals = (byte)stack[1].GetInteger(),
TotalSupply = stack[2].GetInteger()
};
}
/// <summary>
/// Create NEP17 token transfer transaction
/// </summary>
/// <param name="scriptHash">contract script hash</param>
/// <param name="fromKey">from KeyPair</param>
/// <param name="to">to account script hash</param>
/// <param name="amount">transfer amount</param>
/// <param name="data">onPayment data</param>
/// <returns></returns>
public async Task<Transaction> CreateTransferTxAsync(UInt160 scriptHash, KeyPair fromKey, UInt160 to, BigInteger amount, object data = null)
{
var sender = Contract.CreateSignatureRedeemScript(fromKey.PublicKey).ToScriptHash();
Signer[] signers = new[] { new Signer { Scopes = WitnessScope.CalledByEntry, Account = sender } };
byte[] script = data is null ? scriptHash.MakeScript("transfer", sender, to, amount) : scriptHash.MakeScript("transfer", sender, to, amount, data);
TransactionManagerFactory factory = new TransactionManagerFactory(rpcClient, magic);
TransactionManager manager = await factory.MakeTransactionAsync(script, signers).ConfigureAwait(false);
return await manager
.AddSignature(fromKey)
.SignAsync().ConfigureAwait(false);
}
/// <summary>
/// Create NEP17 token transfer transaction from multi-sig account
/// </summary>
/// <param name="scriptHash">contract script hash</param>
/// <param name="m">multi-sig min signature count</param>
/// <param name="pubKeys">multi-sig pubKeys</param>
/// <param name="fromKeys">sign keys</param>
/// <param name="to">to account</param>
/// <param name="amount">transfer amount</param>
/// <param name="data">onPayment data</param>
/// <returns></returns>
public async Task<Transaction> CreateTransferTxAsync(UInt160 scriptHash, int m, ECPoint[] pubKeys, KeyPair[] fromKeys, UInt160 to, BigInteger amount, object data = null)
{
if (m > fromKeys.Length)
throw new ArgumentException($"Need at least {m} KeyPairs for signing!");
var sender = Contract.CreateMultiSigContract(m, pubKeys).ScriptHash;
Signer[] signers = new[] { new Signer { Scopes = WitnessScope.CalledByEntry, Account = sender } };
byte[] script = data is null ? scriptHash.MakeScript("transfer", sender, to, amount) : scriptHash.MakeScript("transfer", sender, to, amount, data);
TransactionManagerFactory factory = new TransactionManagerFactory(rpcClient, magic);
TransactionManager manager = await factory.MakeTransactionAsync(script, signers).ConfigureAwait(false);
return await manager
.AddMultiSig(fromKeys, m, pubKeys)
.SignAsync().ConfigureAwait(false);
}
}
}