|
1 | 1 | import * as vscode from "vscode"; |
2 | 2 | import * as fs from "fs"; |
3 | | -import path from "path"; |
| 3 | +import path, { resolve } from "path"; |
4 | 4 | import { logger } from "../lib"; |
5 | | -import { IContractQP } from "../types"; |
| 5 | +import { ABIFragment, IContractQP, IFunctionQP } from "../types"; |
6 | 6 | import { createABIFile, createAddressFile } from "../utils/functions"; |
7 | 7 | import { getAccountInfo } from "./account"; |
8 | | -import { Account, ec, Provider } from "starknet"; |
| 8 | +import { Account, Contract, ec, Provider } from "starknet"; |
9 | 9 | import { getNetworkProvider } from "./network"; |
10 | 10 |
|
11 | 11 | const loadAllCompiledContract = () => { |
@@ -73,6 +73,16 @@ const getContractInfo = (path_: string, fileName: string) => { |
73 | 73 | return parsedFileData; |
74 | 74 | }; |
75 | 75 |
|
| 76 | +const getContractABI = (path_: string, fileName: string) => { |
| 77 | + const file = fileName.substring(0, fileName.length - 5); |
| 78 | + const fileData = fs.readFileSync( |
| 79 | + path.join(path_, "starkex", file, `${file}_abi.json`), |
| 80 | + { encoding: "utf-8" } |
| 81 | + ); |
| 82 | + const parsedFileData = JSON.parse(fileData); |
| 83 | + return parsedFileData; |
| 84 | +}; |
| 85 | + |
76 | 86 | export const declareContract = async (context: vscode.ExtensionContext) => { |
77 | 87 | try { |
78 | 88 | if (vscode.workspace.workspaceFolders === undefined) { |
@@ -117,3 +127,156 @@ export const declareContract = async (context: vscode.ExtensionContext) => { |
117 | 127 | logger.log(`Error while contract declaration: ${error}`); |
118 | 128 | } |
119 | 129 | }; |
| 130 | + |
| 131 | +export const deployContract = async (context: vscode.ExtensionContext) => { |
| 132 | + try { |
| 133 | + if (vscode.workspace.workspaceFolders === undefined) { |
| 134 | + logger.error("Error: Please open your solidity project to vscode"); |
| 135 | + return; |
| 136 | + } |
| 137 | + const path_ = vscode.workspace.workspaceFolders[0].uri.fsPath; |
| 138 | + const provider = getNetworkProvider(context) as Provider; |
| 139 | + const selectedContract: string = context.workspaceState.get( |
| 140 | + "selectedContract" |
| 141 | + ) as string; |
| 142 | + const selectedAccount = context.workspaceState.get("account") as string; |
| 143 | + console.log(`selectedaAccount first: ${selectedAccount}`); |
| 144 | + if (selectedAccount === undefined) { |
| 145 | + logger.log("No account selected."); |
| 146 | + return; |
| 147 | + } |
| 148 | + const accountInfo = getAccountInfo(context, selectedAccount); |
| 149 | + const keyPair = ec.getKeyPair(accountInfo.privateKey); |
| 150 | + logger.log("Deploying contract..."); |
| 151 | + const account = new Account(provider, accountInfo.accountAddress, keyPair); |
| 152 | + const contractInfo = getContractInfo(path_, selectedContract); |
| 153 | + if (contractInfo.classHash === "") { |
| 154 | + logger.log("No classHash available for selected contract."); |
| 155 | + return; |
| 156 | + } |
| 157 | + const deployResponse = await account.deployContract({ |
| 158 | + classHash: contractInfo.classHash, |
| 159 | + }); |
| 160 | + |
| 161 | + logger.log(`transaction hash: ${deployResponse.transaction_hash}`); |
| 162 | + |
| 163 | + logger.log("waiting for transaction success..."); |
| 164 | + |
| 165 | + await provider.waitForTransaction(deployResponse.transaction_hash); |
| 166 | + |
| 167 | + const { abi: testAbi } = await provider.getClassAt( |
| 168 | + deployResponse.contract_address |
| 169 | + ); |
| 170 | + if (testAbi === undefined) { |
| 171 | + throw new Error("no abi."); |
| 172 | + } |
| 173 | + const myTestContract = new Contract( |
| 174 | + testAbi, |
| 175 | + deployResponse.contract_address, |
| 176 | + provider |
| 177 | + ); |
| 178 | + |
| 179 | + await provider.waitForTransaction(myTestContract.transaction_hash); |
| 180 | + logger.log(`contract deployed successfully: ${myTestContract.address}`); |
| 181 | + } catch (error) { |
| 182 | + logger.log(`Error while contract deployment: ${error}`); |
| 183 | + } |
| 184 | +}; |
| 185 | + |
| 186 | +export const executeContractFunction = async ( |
| 187 | + context: vscode.ExtensionContext |
| 188 | +) => { |
| 189 | + if (vscode.workspace.workspaceFolders === undefined) { |
| 190 | + logger.error("Error: Please open your solidity project to vscode"); |
| 191 | + return; |
| 192 | + } |
| 193 | + const path_ = vscode.workspace.workspaceFolders[0].uri.fsPath; |
| 194 | + const provider = getNetworkProvider(context) as Provider; |
| 195 | + const selectedContract: string = context.workspaceState.get( |
| 196 | + "selectedContract" |
| 197 | + ) as string; |
| 198 | + const selectedAccount = context.workspaceState.get("account") as string; |
| 199 | + if (selectedAccount === undefined) { |
| 200 | + logger.log("No account selected."); |
| 201 | + return; |
| 202 | + } |
| 203 | + const accountInfo = getAccountInfo(context, selectedAccount); |
| 204 | + const keyPair = ec.getKeyPair(accountInfo.privateKey); |
| 205 | + const account = new Account(provider, accountInfo.accountAddress, keyPair); |
| 206 | + const functionABI = await getSelectedFunction(path_, selectedContract); |
| 207 | + const contractInfo = getContractInfo(path_, selectedContract); |
| 208 | + |
| 209 | + const params_: Array<string> = functionABI.inputs.map((e) => { |
| 210 | + return e.value; |
| 211 | + }); |
| 212 | + |
| 213 | + const params = params_ !== undefined ? params_ : []; |
| 214 | + |
| 215 | + if (functionABI.stateMutability === "view") { |
| 216 | + const { abi: testAbi } = await provider.getClassAt(contractInfo.address); |
| 217 | + if (testAbi === undefined) { |
| 218 | + throw new Error("no abi."); |
| 219 | + } |
| 220 | + const contract = new Contract(testAbi, contractInfo.address, provider); |
| 221 | + const functionCall = await contract.call(`${functionABI.name}`); |
| 222 | + logger.log(`${functionCall.res.toString()}`); |
| 223 | + } else { |
| 224 | + const { abi: testAbi } = await provider.getClassAt(contractInfo.address); |
| 225 | + if (testAbi === undefined) { |
| 226 | + throw new Error("no abi."); |
| 227 | + } |
| 228 | + const contract = new Contract(testAbi, contractInfo.address, provider); |
| 229 | + contract.connect(account); |
| 230 | + const res = await contract.invoke(`${functionABI.name}`, params); |
| 231 | + logger.log(`transaction hash: ${res.transaction_hash}`); |
| 232 | + |
| 233 | + logger.log("waiting for transaction success..."); |
| 234 | + |
| 235 | + await provider.waitForTransaction(res.transaction_hash); |
| 236 | + |
| 237 | + logger.log("transaction successfull"); |
| 238 | + } |
| 239 | +}; |
| 240 | + |
| 241 | +const getSelectedFunction = ( |
| 242 | + path_: string, |
| 243 | + selectedContract: string |
| 244 | +): Promise<ABIFragment> => { |
| 245 | + return new Promise((resolve, reject) => { |
| 246 | + try { |
| 247 | + const contractInfo: Array<ABIFragment> = getContractABI( |
| 248 | + path_, |
| 249 | + selectedContract |
| 250 | + ); |
| 251 | + |
| 252 | + console.log(JSON.stringify(contractInfo)); |
| 253 | + if (contractInfo === undefined) return; |
| 254 | + const quickPick = vscode.window.createQuickPick<IFunctionQP>(); |
| 255 | + |
| 256 | + quickPick.items = contractInfo.map((account: ABIFragment) => ({ |
| 257 | + label: account.name, |
| 258 | + })); |
| 259 | + quickPick.onDidChangeActive(() => { |
| 260 | + quickPick.placeholder = "Select Function"; |
| 261 | + }); |
| 262 | + quickPick.onDidChangeSelection((selection: any) => { |
| 263 | + if (selection[0] != null) { |
| 264 | + const { label } = selection[0]; |
| 265 | + quickPick.dispose(); |
| 266 | + const functionItem = contractInfo.filter( |
| 267 | + (i: ABIFragment) => i.name === label |
| 268 | + ); |
| 269 | + if (functionItem.length === 0) |
| 270 | + throw new Error("No function is selected"); |
| 271 | + resolve(functionItem[0]); |
| 272 | + } |
| 273 | + }); |
| 274 | + quickPick.onDidHide(() => { |
| 275 | + quickPick.dispose(); |
| 276 | + }); |
| 277 | + quickPick.show(); |
| 278 | + } catch (error) { |
| 279 | + reject(error); |
| 280 | + } |
| 281 | + }); |
| 282 | +}; |
0 commit comments