-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProgram6.cs
234 lines (187 loc) · 7.39 KB
/
Program6.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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
////////test my wallet in main net first to get balance and then test to send transaction
using CardanoSharp.Wallet.CIPs.CIP2;
using CardanoSharp.Wallet.CIPs.CIP2.Models;
using CardanoSharp.Wallet.Models.Transactions;
using CardanoSharp.Wallet.Extensions;
using CardanoSharp.Wallet.Extensions.Models.Transactions;
using CardanoSharpAsset = CardanoSharp.Wallet.Models.Asset;
using CardanoSharp.Koios.Client;
using Refit;
using CardanoSharp.Wallet.Extensions.Models;
using CardanoSharp.Wallet.TransactionBuilding;
using CardanoSharp.Wallet.Models.Addresses;
using CardanoSharp.Wallet.Models;
using CardanoSharp.Wallet.Enums;
using CardanoSharp.Wallet;
using CardanoSharp.Wallet.Models.Derivations;
using CardanoSharp.Wallet.Models.Keys;
using CardanoSharp.Wallet.Models.Transactions.Scripts;
using CardanoSharp.Wallet.Utilities;
using System.Net;
var networkClient = RestService.For<INetworkClient>("https://api.koios.rest/api/v1");
var epochClient = RestService.For<IEpochClient>("https://api.koios.rest/api/v1");
var blockClient = RestService.For<IBlockClient>("https://api.koios.rest/api/v1");
var transactionClient = RestService.For<ITransactionClient>("https://api.koios.rest/api/v1");
var addressClient = RestService.For<IAddressClient>("https://api.koios.rest/api/v1");
var accountClient = RestService.For<IAccountClient>("https://api.koios.rest/api/v1");
var assetClient = RestService.For<IAssetClient>("https://api.koios.rest/api/v1");
var poolClient = RestService.For<IPoolClient>("https://api.koios.rest/api/v1");
var scriptClient = RestService.For<IScriptClient>("https://api.koios.rest/api/v1");
Mnemonic myWalletMnemonic = new MnemonicService().Restore("my mnemonics");
//Derive Payment Public Key
IIndexNodeDerivation myWalletNode = myWalletMnemonic.GetMasterNode()
.Derive(PurposeType.Shelley)
.Derive(CoinType.Ada)
.Derive(0)
.Derive(RoleType.ExternalChain)
.Derive(0);
myWalletNode.SetPublicKey();
//Derive Stake Public Key
var myWalletstakeNode = myWalletMnemonic.GetMasterNode()
.Derive(PurposeType.Shelley)
.Derive(CoinType.Ada)
.Derive(0)
.Derive(RoleType.Staking)
.Derive(0);
myWalletstakeNode.SetPublicKey();
var mychangeAddress = myWalletMnemonic.GetMasterNode()
.Derive(PurposeType.Shelley)
.Derive(CoinType.Ada)
.Derive(0)
.Derive(RoleType.InternalChain)
.Derive(0);
mychangeAddress.SetPublicKey();
IAddressService addressService = new AddressService();
var senderAddress = addressService.GetBaseAddress(
myWalletNode.PublicKey,
myWalletstakeNode.PublicKey,
NetworkType.Mainnet).ToString();
var destination = "addr1qypf6mmegd0egmey2jfcwvsxl7xc7g6pr9ldvsxp3zu6xfnesh43glgahr2y53eaju56eyzknrhy8n7qvnwc84tz9pqq05drj5";
var changeAddress = addressService.GetBaseAddress(
mychangeAddress.PublicKey,
myWalletstakeNode.PublicKey,
NetworkType.Mainnet).ToString();
//1. Get UTxOs
var utxos = await GetUtxos(senderAddress);
///2. Create the Body
var transactionBody = TransactionBodyBuilder.Create;
//set outputs
transactionBody.AddOutput(destination.ToBytes(), 25000000);
transactionBody.AddOutput(changeAddress.ToBytes(), 75000000);
//perform coin selection
var coinSelection = ((TransactionBodyBuilder)transactionBody).UseLargestFirstWithImprove(utxos);
//add the inputs from coin selection to transaction body builder
AddInputsFromCoinSelection(coinSelection, transactionBody);
//get protocol parameters and set default fee
var epochResponse = await epochClient.GetEpochInformation();
var ppResponse = await epochClient.GetProtocolParameters();
var protocolParameters = ppResponse.Content.FirstOrDefault();
//get network tip and set ttl
var blockSummaries = (await networkClient.GetChainTip()).Content;
var ttl = 2500 + (uint)blockSummaries.First().AbsSlot;
transactionBody.SetTtl(ttl);
///3. Add Witnesses
var witnessSet = TransactionWitnessSetBuilder.Create;
witnessSet.AddVKeyWitness(myWalletNode.PublicKey, myWalletNode.PrivateKey);
witnessSet.AddVKeyWitness(myWalletstakeNode.PublicKey, myWalletstakeNode.PrivateKey);
var transaction = TransactionBuilder.Create;
transaction.SetBody(transactionBody);
transaction.SetWitnesses(witnessSet);
//get a draft transaction to calculate fee
var draft = transaction.Build();
var fee = draft.CalculateFee(protocolParameters.MinFeeA, protocolParameters.MinFeeB);
//update fee and change output
transactionBody.SetFee(fee);
var raw = transaction.Build();
raw.TransactionBody.TransactionOutputs.Last().Value.Coin -= fee;
var signed = raw.Serialize();
try
{
using MemoryStream stream = new MemoryStream(signed);
try
{
Console.WriteLine("Sending...");
var result = await transactionClient.Submit(stream);
Console.WriteLine($"Tx ID: {result.Content}");
//MemoryStream stream2 = new MemoryStream(signedTx);
//var result2 = await transactionClient.Submit(stream2);
//Console.WriteLine($"Tx ID: {result2.Content}");
//var txId = await transactionClient.Submit(stream);
//var xxx = 1;
}
catch (Exception e)
{
Console.Write(e.Message);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
async Task<List<Utxo>> GetUtxos(string address)
{
try
{
var addressBulkRequest = new AddressBulkRequest { Addresses = new List<string> { address } };
var addressResponse = (await addressClient.GetAddressInformation(addressBulkRequest));
var addressInfo = addressResponse.Content;
var utxos = new List<Utxo>();
foreach (var ai in addressInfo.SelectMany(x => x.UtxoSets))
{
if (ai is null) continue;
var utxo = new Utxo()
{
TxIndex = ai.TxIndex,
TxHash = ai.TxHash,
Balance = new Balance()
{
Lovelaces = ulong.Parse(ai.Value)
}
};
var assetList = new List<CardanoSharpAsset>();
foreach (var aa in ai.AssetList)
{
assetList.Add(new CardanoSharpAsset()
{
Name = aa.AssetName,
PolicyId = aa.PolicyId,
Quantity = ulong.Parse(aa.Quantity)
});
}
utxo.Balance.Assets = assetList;
utxos.Add(utxo);
}
return utxos;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return null;
}
}
void AddInputsFromCoinSelection(CoinSelection coinSelection, ITransactionBodyBuilder transactionBody)
{
foreach (var i in coinSelection.Inputs)
{
transactionBody.AddInput(i.TransactionId, i.TransactionIndex);
}
}
void AddChangeOutputs(ITransactionBodyBuilder ttb, List<TransactionOutput> outputs, string address)
{
foreach (var output in outputs)
{
ITokenBundleBuilder? assetList = null;
if (output.Value.MultiAsset is not null)
{
assetList = TokenBundleBuilder.Create;
foreach (var ma in output.Value.MultiAsset)
{
foreach (var na in ma.Value.Token)
{
assetList.AddToken(ma.Key, na.Key, na.Value);
}
}
}
ttb.AddOutput(new Address(address), output.Value.Coin, assetList);
}
}