1+ global using Newtonsoft . Json ;
2+
3+ // SecretNET
4+ global using SecretNET ;
5+ global using SecretNET . Tx ;
6+ global using SecretNET . Common ;
7+ global using SecretNET . Common . Storage ;
8+ using System . Reflection . Metadata ;
9+
10+
11+ // See https://aka.ms/new-console-template for more information
12+
13+ #region *** Helper functions / Objects ***
14+
15+ Action < string > writeHeadline = ( text ) =>
16+ {
17+ Console . ForegroundColor = ConsoleColor . Cyan ;
18+ Console . WriteLine ( $ "\r \n **************** { text } ****************\r \n ") ;
19+ Console . ForegroundColor = ConsoleColor . White ;
20+ } ;
21+
22+ Action < string , SecretTx > logSecretTx = ( name , tx ) =>
23+ {
24+ Console . WriteLine ( $ "{ name } Txhash: { tx ? . Txhash } ") ;
25+ Console . ForegroundColor = ConsoleColor . Gray ;
26+ Console . WriteLine ( $ "(Gas used: { tx . GasUsed } - Gas wanted { tx . GasWanted } )") ;
27+ Console . ForegroundColor = ConsoleColor . White ;
28+
29+ //Console.WriteLine($"\r\nCodeId: {JsonConvert.SerializeObject(tx.GetResponseJson(), Formatting.Indented)}");
30+
31+ if ( tx is SingleSecretTx < Secret . Compute . V1Beta1 . MsgStoreCodeResponse > )
32+ {
33+ Console . WriteLine ( $ "\r \n CodeId: { ( ( SingleSecretTx < Secret . Compute . V1Beta1 . MsgStoreCodeResponse > ) tx ) . Response . CodeId } ") ;
34+ }
35+
36+ if ( tx is SingleSecretTx < Secret . Compute . V1Beta1 . MsgInstantiateContractResponse > )
37+ {
38+ Console . WriteLine ( $ "\r \n ContractAddress: { ( ( SingleSecretTx < Secret . Compute . V1Beta1 . MsgInstantiateContractResponse > ) tx ) ? . Response ? . Address } ") ;
39+ }
40+
41+ if ( tx != null && ( tx . Code > 0 || ( tx . Exceptions ? . Any ( ) ) . GetValueOrDefault ( ) ) )
42+ {
43+ Console . ForegroundColor = ConsoleColor . Red ;
44+ if ( tx . Code > 0 && ! string . IsNullOrWhiteSpace ( tx . Codespace ) )
45+ {
46+ Console . WriteLine ( $ "\r \n !!!!!!!!!!!! Something went wrong => Code: { tx . Code } ; Codespace: { tx . Codespace } !!!!!!!!!!!!") ;
47+ }
48+ if ( ( tx . Exceptions ? . Any ( ) ) . GetValueOrDefault ( ) )
49+ {
50+ foreach ( var ex in tx . Exceptions )
51+ {
52+ Console . WriteLine ( $ "\r \n !!!!!!!!!!!! Exception: { ex . Message } !!!!!!!!!!!!") ;
53+ }
54+ }
55+ Console . WriteLine ( $ "\r \n { tx . RawLog } ") ;
56+ Console . ForegroundColor = ConsoleColor . White ;
57+ Console . ReadLine ( ) ;
58+ }
59+ } ;
60+
61+ // TxOptions
62+ var txOptions = new TxOptions ( )
63+ {
64+ GasLimit = 60_000 ,
65+ GasPriceInFeeDenom = 0.26F
66+ } ;
67+
68+ var txOptionsExecute = new TxOptions ( )
69+ {
70+ GasLimit = 300_000 ,
71+ GasPriceInFeeDenom = 0.26F
72+ } ;
73+
74+ var txOptionsUpload = new TxOptions ( )
75+ {
76+ GasLimit = 12_000_000 ,
77+ GasPriceInFeeDenom = 0.26F
78+ } ;
79+
80+ #endregion
81+
82+ writeHeadline ( "Setup SecretNetworkClient / Wallet" ) ;
83+
84+ //var storageProvider = new InMemoryOnlyStorage(); // Temporary and most likely only for DEV
85+ var storageProvider = new AesEncryptedFileStorage ( "" , "SuperSecurePassword" ) ;
86+ var createWalletOptions = new CreateWalletOptions ( storageProvider ) ;
87+
88+ Wallet wallet = null ;
89+ if ( await storageProvider . HasPrivateKey ( ) )
90+ {
91+ var storedMnemonic = await storageProvider . GetFirstMnemonic ( ) ;
92+ wallet = await Wallet . Create ( storedMnemonic , options : createWalletOptions ) ;
93+ }
94+ else
95+ {
96+ wallet = await Wallet . Create ( options : createWalletOptions ) ;
97+
98+ Console . WriteLine ( "Please first fund the wallet with some SCRT via https://faucet.pulsar.scrttestnet.com/ " ) ;
99+ Console . ReadLine ( ) ;
100+ }
101+
102+ var gprcUrl = "https://grpc.testnet.secretsaturn.net" ; // get from https://github.com/scrtlabs/api-registry
103+ var chainId = "pulsar-2" ;
104+
105+ var createClientOptions = new CreateClientOptions ( gprcUrl , chainId , wallet ) ;
106+ var secretClient = new SecretNetworkClient ( createClientOptions ) ;
107+
108+ Console . WriteLine ( "wallet.Address: " + wallet . Address ) ;
109+
110+
111+ #region *** Get Balance ***
112+
113+ // *** Get Balance (1000000 uscrt == 1 SCRT) ***
114+
115+ writeHeadline ( "Get Balance" ) ;
116+
117+ var response = await secretClient . Query . Bank . Balance ( wallet . Address ) ;
118+ Console . WriteLine ( $ "Balance: { ( float . Parse ( response . Amount ) / 1000000f ) } SCRT") ;
119+
120+ //Console.ReadLine();
121+
122+ #endregion
123+
124+ #region *** Get Subacccount and Send $SCRT ***
125+
126+ // Send SCRT
127+ var subaccountWallet = await wallet . GetSubaccount ( 1 ) ;
128+ Console . WriteLine ( $ "\r \n Subaccount.Address: { subaccountWallet . Address } ") ;
129+
130+ var sendResponse = await secretClient . Tx . Bank . Send ( toAddress : subaccountWallet . Address , amount : 1000000 , denom : null ) ;
131+ Console . WriteLine ( $ "BroadcastResponse: { ( sendResponse . Code == 0 ? "Success" : "Error (see log)" ) } ") ;
132+
133+ var r1 = await secretClient . Query . Bank . Balance ( subaccountWallet . Address ) ;
134+ Console . WriteLine ( $ "Subaccount Balance: { ( float . Parse ( r1 . Amount ) / 1000000f ) } SCRT\r \n ") ;
135+
136+ //Console.ReadLine();
137+
138+ #endregion
139+
140+ #region *** Simulate and broadcast a complex transaction ***
141+
142+ var sendToAlice = new Cosmos . Bank . V1Beta1 . MsgSend ( )
143+ {
144+ FromAddress = wallet . Address ,
145+ ToAddress = subaccountWallet . Address
146+ } ;
147+ sendToAlice . Amount . Add ( new Cosmos . Base . V1Beta1 . Coin ( ) { Amount = "1" , Denom = "uscrt" } ) ;
148+
149+ var sendToEve = new Cosmos . Bank . V1Beta1 . MsgSend ( )
150+ {
151+ FromAddress = wallet . Address ,
152+ ToAddress = subaccountWallet . Address // use the same address for simplicity
153+ } ;
154+ sendToEve . Amount . Add ( new Cosmos . Base . V1Beta1 . Coin ( ) { Amount = "1" , Denom = "uscrt" } ) ;
155+
156+ var messages = new [ ] { sendToAlice , sendToEve } ;
157+
158+ var simulate = await secretClient . Tx . Simulate ( messages ) ;
159+
160+ Console . WriteLine ( $ "Simulate => GasUsed { simulate . GasInfo . GasUsed } uscrt") ;
161+
162+ var tx = await secretClient . Tx . Broadcast ( messages , new TxOptions
163+ {
164+ // Adjust gasLimit up by 10% to account for gas estimation error
165+ GasLimit = ( int ) Math . Ceiling ( simulate . GasInfo . GasUsed * 1.1 ) ,
166+ } ) ;
167+
168+ logSecretTx ( "Broadcast result" , tx ) ;
169+
170+ //Console.ReadLine();
171+
172+ #endregion
173+
174+ #region *** Auth ***
175+
176+ // *** Get Account ***
177+
178+ writeHeadline ( "Get Account" ) ;
179+
180+ var accountResponse = await secretClient . Query . Auth . Account ( wallet . Address ) ;
181+ Console . WriteLine ( "AccountResponse:\r \n " + JsonConvert . SerializeObject ( accountResponse , Formatting . Indented ) + "\r \n " ) ;
182+
183+ //Console.ReadLine();
184+
185+ #endregion
186+
187+ #region *** Codes ***
188+
189+ // *** Get Codes with source ***
190+
191+ writeHeadline ( "Get my Codes with source" ) ;
192+
193+ var codesResponse = await secretClient . Query . Compute . Codes ( ) ;
194+ var withSource = codesResponse . Where ( c => ! string . IsNullOrWhiteSpace ( c . Source ) && c . CreatorAddress == wallet . Address ) . ToList ( ) ;
195+ Console . WriteLine ( $ "My Codes with source (Count: { withSource . Count } ):\r \n " + JsonConvert . SerializeObject ( withSource , Formatting . Indented ) + "\r \n " ) ;
196+
197+ //Console.ReadLine();
198+
199+ #endregion
200+
201+ #region *** Smart Contract (Upload, Init, Query, Execute) ***
202+
203+ // *** Smart Contract (Upload, Init, Query, Execute) ***
204+
205+ writeHeadline ( "Upload Contract (mysimplecounter.wasm.gz)" ) ;
206+
207+ // *** Upload Contract ***
208+ // https://secretjs.scrt.network/#secretjstxcomputestorecode
209+
210+ byte [ ] wasmByteCode = File . ReadAllBytes ( @"..\..\..\..\..\Resources\mysimplecounter.wasm.gz" ) ;
211+
212+ // MsgStoreCode
213+ var msgStoreCodeCounter = new MsgStoreCode ( wasmByteCode ,
214+ source : "https://github.com/scrtlabs/secret-template" , // Source is a valid absolute HTTPS URI to the contract's source code, optional
215+ builder : "enigmampc/secret-contract-optimizer:latest" // Builder is a valid docker image name with tag, optional
216+ ) ;
217+
218+ var storeCodeResponse = await secretClient . Tx . Compute . StoreCode ( msgStoreCodeCounter , txOptions : txOptionsUpload ) ;
219+ logSecretTx ( "StoreCodeResponse" , storeCodeResponse ) ;
220+
221+ // *** Init Contract ***
222+ writeHeadline ( "Init Contract with CodeId " + storeCodeResponse . Response . CodeId ) ;
223+
224+ string ? contractAddress = null ;
225+ string contractCodeHash = null ;
226+ if ( storeCodeResponse . Response . CodeId > 0 )
227+ {
228+ var codeId = storeCodeResponse . Response . CodeId ;
229+ contractCodeHash = await secretClient . Query . Compute . GetCodeHashByCodeId ( codeId ) ;
230+
231+ var msgInitContract = new MsgInstantiateContract (
232+ codeId : codeId ,
233+ label : $ "MySimpleCouter { codeId } ",
234+ initMsg : new { count = 100 } ,
235+ codeHash : contractCodeHash ) ; // optional but way faster
236+
237+ var initContractResponse = await secretClient . Tx . Compute . InstantiateContract ( msgInitContract , txOptions : txOptionsUpload ) ;
238+ logSecretTx ( "InstantiateContract" , initContractResponse ) ;
239+
240+ contractAddress = initContractResponse ? . Response ? . Address ;
241+
242+ Console . WriteLine ( "Contract CodeHash: " + contractCodeHash ) ;
243+ Console . WriteLine ( "Contract Address: " + contractAddress ) ;
244+
245+ }
246+
247+ //Console.ReadLine();
248+
249+ #region *** Query Contract ***
250+
251+ //string contractAddress = "Set manual if needed";
252+ //string contractCodeHash = "Set manual if needed";
253+
254+ // *** Query Contract ***
255+
256+ writeHeadline ( "Query Contract with address " + contractAddress ) ;
257+
258+ var queryMsg = new { get_count = new { } } ;
259+
260+ Console . WriteLine ( "Query : " + JsonConvert . SerializeObject ( queryMsg , Formatting . Indented ) + "\r \n " ) ;
261+
262+ var queryContractResult = await secretClient . Query . Compute . QueryContract < object > ( contractAddress , queryMsg , contractCodeHash ) ;
263+ Console . WriteLine ( "QueryContractResult:\r \n " + queryContractResult . Response ) ;
264+
265+ //Console.ReadLine();
266+
267+ #endregion
268+
269+ #region *** Execute Contract ***
270+
271+ // *** Execute Contract ***
272+
273+ writeHeadline ( "Execute Contract with address " + contractAddress ) ;
274+
275+ var executeMsg = new { increment = new { } } ;
276+
277+ Console . WriteLine ( "Execute : " + JsonConvert . SerializeObject ( executeMsg , Formatting . Indented ) + "\r \n " ) ;
278+
279+ var msgExecuteContract = new MsgExecuteContract ( contractAddress : contractAddress , msg : executeMsg , codeHash : contractCodeHash , sender : null , sentFunds : null ) ;
280+
281+ var executeContractResponse = await secretClient . Tx . Compute . ExecuteContract ( msgExecuteContract , txOptionsExecute ) ;
282+ logSecretTx ( "ExecuteContract" , executeContractResponse ) ;
283+
284+ Thread . Sleep ( 1000 ) ; // give some time to let it settle
285+
286+ var queryContractResult2 = await secretClient . Query . Compute . QueryContract < object > ( contractAddress , queryMsg , contractCodeHash ) ;
287+ Console . WriteLine ( "\r \n QueryContractResult (again) :\r \n " + queryContractResult2 . Response ) ;
288+
289+ Console . ReadLine ( ) ;
290+
291+ #endregion
292+
293+ #endregion
0 commit comments