|
| 1 | +--- |
| 2 | +title: Create and Deploy an iApp |
| 3 | +description: |
| 4 | + How to create a confidential iExec application and deploy it on iExec protocol |
| 5 | +--- |
| 6 | + |
| 7 | +# Create and Deploy an iApp |
| 8 | + |
| 9 | +iApps (iExec Applications) are decentralized applications that run on the iExec |
| 10 | +network. They leverage confidential computing to ensure data privacy and |
| 11 | +security while providing scalable off-chain computation. |
| 12 | + |
| 13 | +## About iApp Generator |
| 14 | + |
| 15 | +Bootstrap TEE-compatible applications in minutes without any hardcoding skills, |
| 16 | +iApp Generator handles all the low-level complexity for you. |
| 17 | + |
| 18 | +- **Select your project mode & language** - Get started with either a basic or |
| 19 | + advanced setup, depending on your experience with the iExec framework. You can |
| 20 | + use Python or JavaScript—whichever you prefer! |
| 21 | +- **Develop your iApp effortlessly** - Write your application logic using |
| 22 | + familiar programming languages while the generator handles all TEE-specific |
| 23 | + configurations. |
| 24 | +- **Access to TEEs easily** - No need to dive into low-level requirements, |
| 25 | + create iApps that connect to TEEs in minutes. |
| 26 | +- **Check and deploy iApps quickly** - iApp Generator checks that your iApp |
| 27 | + complies with the iExec Framework and streamlines its deployment. |
| 28 | + |
| 29 | +## Prerequisites |
| 30 | + |
| 31 | +Before getting started, make sure you have the following installed: |
| 32 | + |
| 33 | +- **Node.js** (version 18 or higher) - [Download here](https://nodejs.org/) |
| 34 | +- **Docker** - [Download here](https://www.docker.com/get-started) |
| 35 | +- **Docker Hub account** - [Sign up here](https://hub.docker.com/) (required for |
| 36 | + deployment) |
| 37 | + |
| 38 | +## Installation |
| 39 | + |
| 40 | +First, install the iApp Generator CLI tool using your preferred package manager: |
| 41 | + |
| 42 | +::: code-group |
| 43 | + |
| 44 | +```sh [npm] |
| 45 | +npm install -g @iexec/iapp |
| 46 | +``` |
| 47 | + |
| 48 | +```sh [yarn] |
| 49 | +yarn global add @iexec/iapp |
| 50 | +``` |
| 51 | + |
| 52 | +```sh [pnpm] |
| 53 | +pnpm add -g @iexec/iapp |
| 54 | +``` |
| 55 | + |
| 56 | +```sh [bun] |
| 57 | +bun add -g @iexec/iapp |
| 58 | +``` |
| 59 | + |
| 60 | +::: |
| 61 | + |
| 62 | +## Quick Start |
| 63 | + |
| 64 | +Once installed, you can create and deploy your first iApp. The CLI will guide |
| 65 | +you through an interactive setup process to configure your project name, |
| 66 | +programming language, and template: |
| 67 | + |
| 68 | +<CLIDemo |
| 69 | + initialCommand="iapp init" |
| 70 | + asciiText="iApp" |
| 71 | + :steps="[ |
| 72 | + { |
| 73 | + showAt: 2, |
| 74 | + completeAt: 4, |
| 75 | + question: 'What is your project name? (A folder with this name will be created)', |
| 76 | + answer: 'hello-world', |
| 77 | + showTyping: true, |
| 78 | + isComplete: false |
| 79 | + }, |
| 80 | + { |
| 81 | + showAt: 4, |
| 82 | + completeAt: 6, |
| 83 | + question: 'Which language do you want to use?', |
| 84 | + answer: 'JavaScript', |
| 85 | + options: [ |
| 86 | + { label: 'JavaScript', selected: true }, |
| 87 | + { label: 'Python', selected: false } |
| 88 | + ], |
| 89 | + highlighted: false, |
| 90 | + isComplete: false |
| 91 | + }, |
| 92 | + { |
| 93 | + showAt: 6, |
| 94 | + completeAt: 8, |
| 95 | + question: 'What kind of project do you want to init?', |
| 96 | + answer: 'Hello World', |
| 97 | + options: [ |
| 98 | + { label: 'Hello World - iapp quick start', selected: true }, |
| 99 | + { label: 'advanced', selected: false } |
| 100 | + ], |
| 101 | + highlighted: false, |
| 102 | + isComplete: false |
| 103 | + } |
| 104 | + ]" |
| 105 | + :completionStep="8" |
| 106 | + :completionMessage="'Generating your iApp...'" |
| 107 | + :completionItems="[ |
| 108 | + '📁 Created hello-world/', |
| 109 | + '📄 Added package.json', |
| 110 | + '🐳 Added Dockerfile', |
| 111 | + '⚙️ Added iExec configuration' |
| 112 | + ]" |
| 113 | + :successMessage="'Your iApp is ready!'" |
| 114 | +/> |
| 115 | + |
| 116 | +After the interactive setup, continue with development and deployment: |
| 117 | + |
| 118 | +## Development and Testing |
| 119 | + |
| 120 | +Navigate to your project and run tests locally to simulate the TEE environment. |
| 121 | +The CLI will build a Docker image, run your app, and show you the results: |
| 122 | + |
| 123 | +<CLIDemo |
| 124 | + initialCommand="iapp test" |
| 125 | + :steps="[ |
| 126 | + { |
| 127 | + showAt: 2, |
| 128 | + question: 'No app secret is configured (from iapp.config.json)', |
| 129 | + answer: '', |
| 130 | + showTyping: false, |
| 131 | + isComplete: true |
| 132 | + }, |
| 133 | + { |
| 134 | + showAt: 3, |
| 135 | + question: 'App docker image built (sha256:9cc0de820aaaf8f86700a3ec4082fe69b9e9a48a117ebb0ade0d82d0879cbe41)', |
| 136 | + answer: '', |
| 137 | + showTyping: false, |
| 138 | + isComplete: true |
| 139 | + }, |
| 140 | + { |
| 141 | + showAt: 4, |
| 142 | + question: 'App docker image ran and exited successfully.', |
| 143 | + answer: '', |
| 144 | + showTyping: false, |
| 145 | + isComplete: true |
| 146 | + }, |
| 147 | + { |
| 148 | + showAt: 5, |
| 149 | + completeAt: 6, |
| 150 | + question: 'Would you like to see the app logs? (12 lines)', |
| 151 | + answer: 'no', |
| 152 | + options: [ |
| 153 | + { label: 'yes', selected: false }, |
| 154 | + { label: 'no', selected: true } |
| 155 | + ], |
| 156 | + highlighted: false, |
| 157 | + showTyping: false, |
| 158 | + isComplete: false |
| 159 | + }, |
| 160 | + { |
| 161 | + showAt: 7, |
| 162 | + question: 'Checked app output', |
| 163 | + answer: '', |
| 164 | + showTyping: false, |
| 165 | + isComplete: true |
| 166 | + }, |
| 167 | + { |
| 168 | + showAt: 8, |
| 169 | + completeAt: 10, |
| 170 | + question: 'Would you like to see the result? (View ./output/)', |
| 171 | + answer: 'yes', |
| 172 | + options: [ |
| 173 | + { label: 'yes', selected: true }, |
| 174 | + { label: 'no', selected: false } |
| 175 | + ], |
| 176 | + highlighted: false, |
| 177 | + showTyping: false, |
| 178 | + isComplete: false |
| 179 | + } |
| 180 | + ]" |
| 181 | + :completionStep="11" |
| 182 | + :completionMessage="'📁 output directory content:'" |
| 183 | + :completionItems="[ |
| 184 | + '└ computed.json', |
| 185 | + '└ result.txt' |
| 186 | + ]" |
| 187 | + :successMessage="'hello world'" |
| 188 | + :autoRestart="true" |
| 189 | +/> |
| 190 | + |
| 191 | +## Deployment |
| 192 | + |
| 193 | +After your tests pass and the package is built, you can deploy your iApp to a |
| 194 | +supported network. During deployment, you'll enter your DockerHub credentials, |
| 195 | +specify your app version, and push both standard and TEE-compatible images: |
| 196 | + |
| 197 | +<CLIDemo |
| 198 | + initialCommand="iapp deploy" |
| 199 | + asciiText="Deploy" |
| 200 | + :steps="[ |
| 201 | + { |
| 202 | + showAt: 2, |
| 203 | + question: 'Using chain bellecour', |
| 204 | + answer: '', |
| 205 | + showTyping: false, |
| 206 | + isComplete: true |
| 207 | + }, |
| 208 | + { |
| 209 | + showAt: 3, |
| 210 | + question: 'Using saved walletPrivateKey (from iapp.config.json)', |
| 211 | + answer: '', |
| 212 | + showTyping: false, |
| 213 | + isComplete: true |
| 214 | + }, |
| 215 | + { |
| 216 | + showAt: 4, |
| 217 | + completeAt: 6, |
| 218 | + question: 'What is your username on DockerHub? (It will be used to properly tag the Docker image)', |
| 219 | + answer: 'bob', |
| 220 | + showTyping: true, |
| 221 | + isComplete: false |
| 222 | + }, |
| 223 | + { |
| 224 | + showAt: 6, |
| 225 | + completeAt: 8, |
| 226 | + question: 'What is your DockerHub access token?', |
| 227 | + answer: '**********************', |
| 228 | + showTyping: true, |
| 229 | + isComplete: false |
| 230 | + }, |
| 231 | + { |
| 232 | + showAt: 8, |
| 233 | + completeAt: 10, |
| 234 | + question: 'What is the version of your iApp?', |
| 235 | + answer: '0.0.1', |
| 236 | + showTyping: true, |
| 237 | + isComplete: false |
| 238 | + }, |
| 239 | + { |
| 240 | + showAt: 10, |
| 241 | + question: 'Docker image built (sha256:a53fc4c480f482c384a13266ea2cb6cc5572733c866c44a5f604f4bfab3a744a) and tagged bob/hello-world:0.0.1', |
| 242 | + answer: '', |
| 243 | + showTyping: false, |
| 244 | + isComplete: true |
| 245 | + }, |
| 246 | + { |
| 247 | + showAt: 11, |
| 248 | + question: 'Pushed image bob/hello-world:0.0.1 on dockerhub', |
| 249 | + answer: '', |
| 250 | + showTyping: false, |
| 251 | + isComplete: true |
| 252 | + }, |
| 253 | + { |
| 254 | + showAt: 12, |
| 255 | + question: 'Pushed TEE image bob/hello-world:0.0.1-tee-scone-5.9.1-v16-debug-ce3a01d9c5d7 on dockerhub', |
| 256 | + answer: '', |
| 257 | + showTyping: false, |
| 258 | + isComplete: true |
| 259 | + }, |
| 260 | + { |
| 261 | + showAt: 13, |
| 262 | + question: 'TEE app deployed', |
| 263 | + answer: '', |
| 264 | + showTyping: false, |
| 265 | + isComplete: true |
| 266 | + } |
| 267 | + ]" |
| 268 | + :completionStep="14" |
| 269 | + :completionMessage="'Deployment of your iApp completed successfully:'" |
| 270 | + :completionItems="[ |
| 271 | + '└ Docker image: bob/hello-world:0.0.1-tee-scone-5.9.1-v16-debug-ce3a01d9c5d7', |
| 272 | + '└ iApp address: 0x1f80DCebc2EAAff0Db7156413C43B7e88D189923' |
| 273 | + ]" |
| 274 | + :successMessage="'Run iapp run 0x1f80DCebc2EAAff0Db7156413C43B7e88D189923 to execute your iApp on an iExec TEE worker'" |
| 275 | + :autoRestart="true" |
| 276 | +/> |
| 277 | + |
| 278 | +## Real Examples |
| 279 | + |
| 280 | +Here are some real-world examples of iApps to help you understand how they work |
| 281 | +in practice. |
| 282 | + |
| 283 | +### Email Notification iApp |
| 284 | + |
| 285 | +This iApp lets you send updates to your contacts without ever seeing their email |
| 286 | +addresses, privacy is preserved by design. |
| 287 | + |
| 288 | +::: code-group |
| 289 | + |
| 290 | +```js [Node.js] |
| 291 | +/* User runs: "Send updates to my contacts about my project" */ |
| 292 | +const contacts = loadProtectedData(); // User's protected contact list |
| 293 | +contacts.forEach((contact) => { |
| 294 | + sendEmail(contact, projectUpdateMessage); |
| 295 | +}); |
| 296 | +// → Emails sent directly, you never see the addresses |
| 297 | +``` |
| 298 | + |
| 299 | +```python [Python] |
| 300 | +# User runs: "Send updates to my contacts about my project" |
| 301 | +contacts = load_protecteddata() # User's protected contact list |
| 302 | +for contact in contacts: |
| 303 | + send_email(contact, project_update_message) |
| 304 | +# → Emails sent directly, you never see the addresses |
| 305 | +``` |
| 306 | + |
| 307 | +::: |
| 308 | + |
| 309 | +### Oracle Update iApp |
| 310 | + |
| 311 | +This iApp securely updates a price oracle using private trading data, ensuring |
| 312 | +sensitive information stays confidential. |
| 313 | + |
| 314 | +::: code-group |
| 315 | + |
| 316 | +```js [Node.js] |
| 317 | +// User runs: "Update price oracle with my private trading data" |
| 318 | +const tradingData = loadProtectedData(); // User's protected trading history |
| 319 | +const averagePrice = calculateWeightedAverage(tradingData); |
| 320 | +updateOracleContract(averagePrice); |
| 321 | +// → Oracle updated with real data, trading history stays private |
| 322 | +``` |
| 323 | + |
| 324 | +```python [Python] |
| 325 | +# User runs: "Update price oracle with my private trading data" |
| 326 | +trading_data = load_protecteddata() # User's protected trading history |
| 327 | +average_price = calculate_weighted_average(trading_data) |
| 328 | +update_oracle_contract(average_price) |
| 329 | +# → Oracle updated with real data, trading history stays private |
| 330 | +``` |
| 331 | + |
| 332 | +::: |
| 333 | + |
| 334 | +### Automated Transactions iApp |
| 335 | + |
| 336 | +This iApp automates monthly payments using protected payment details, so |
| 337 | +financial information remains private. |
| 338 | + |
| 339 | +::: code-group |
| 340 | + |
| 341 | +```js [Node.js] |
| 342 | +// User runs: "Automate payments every month" |
| 343 | +const paymentInfo = loadProtectedData(); // User's payment details |
| 344 | +for (let month = 0; month < 12; month++) { |
| 345 | + processPayment(paymentInfo); |
| 346 | +} |
| 347 | +// → Payments processed, payment details stay private |
| 348 | +``` |
| 349 | + |
| 350 | +```python [Python] |
| 351 | +# User runs: "Automate payments every month" |
| 352 | +payment_info = load_protecteddata() # User's payment details |
| 353 | +for month in range(12): |
| 354 | + process_payment(payment_info) |
| 355 | +# → Payments processed, payment details stay private |
| 356 | +``` |
| 357 | + |
| 358 | +::: |
| 359 | + |
| 360 | +<script setup> |
| 361 | +import CLIDemo from '@/components/CLIDemo.vue'; |
| 362 | +</script> |
0 commit comments