First you will need to install the @phala/fn CLI tool using your node package manager (npm) or use node package execute (npx). In this tutorial we use npx.
Now create your first template with the CLI tool command:
npx@phala/fn@latestinituserJourney
Select one of the template and press enter to see something similar to the example below:
npx@phala/fn@latestinituserJourney? Please select one of the templates for your "userJourney" project: โฏphat-contract-starter-kit:SenddatafromanyAPItoyoursmartcontractwithJavascript.lensapi-oracle-consumer-contract:SenddatafromLensAPItoyoursmartcontracttoempoweryourWeb3SocialdApp.vrf-oracle:TEE-guardedVerifiableRandomFunctiontemplatetobringrandomnesstoyoursmartcontract. airstack-phat-contract: Request an accountโs data from Airstackโs API to compute trust score and send to your Web3 dApp on-chain.
thegraph-phat-contract:ConnectyoursubgraphsfromTheGraphtoyouron-chaindAppsviaPhatContract.
cd into the newly created template and ls the directory which will look similar to below.
First, create your Phala Profile account on the Phala Dashboard. Here is a quick 1 minute YouTube video on setting up from scratch. Here is what your Phala Profile account overview should look like:
Option 1: Export Polkadot account as json file
Go to your browser and click on the polkadot.js extension. Select your account and click "Export Account". Next, you will be prompted for your password before saving the file to your project directory. Note this is what will be set to POLKADOT_WALLET_ACCOUNT_PASSPHRASE. Make sure to save the file as polkadot-account.json in the root of your project directory.
Option 2: Set mnemonic phrase to POLKADOT_WALLET_SURI
After creating your Phala Profile, set your .env variable POLKADOT_WALLET_SURI to the mnemonic phrase from generating the new Polkadot Account.
Here is a screenshot of how to set POLKADOT_WALLET_SURI:
Testing Locally
Test Default Phat Contract Locally
With a template created and a basic default Phat Contract example ready to test, letโs step through the process of preparing your repo to execute the test locally.
First step is to install the package dependencies with the following command:
npminstall
Everything should go smoothly and produce similar output below:
Now that the package dependencies are installed, lets build the default Phat Contract which is located in ./src/index.ts.
For those want to understand what the contents of ./src/index.ts mean, go here read more. If you are already familiar with the concepts then you can proceed to with the deployment process.
Build the default Phat Contract with this command:
npx@phala/fnbuild
You will see output similar to the example below. and a file in ./dist/index.js will be generated.
Notice that the test fails and reports that a Malformed request received was emitted and the request was undefined. This is expected as you will need to define the parameters by adding a -a abi.encode(requestId, profileId) https://api-v2-mumbai-live.lens.dev to your command.
To simulate the expected result locally, run the Phala Oracle function now with this command:
npx @phala/fn run dist/index.js -a 0x0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000043078303100000000000000000000000000000000000000000000000000000000 https://api-v2-mumbai-live.lens.dev
What are the ingredients for the npx @phala/fn run command?
Our Phat Contract script, now fully constructed, is ready for a trial run. This simulation mirrors the live script's operation when deployed on the Phala Network.
The command's first parameter is a HexString, representing a tuple of types [uint, bytes]. This serves as the entry function. The second parameter is a string, embodying the configurable secrets fed into the main function.
The Coders.decode function deciphers these parameters, yielding the decoded requestId and encodedReqStr. These decoded elements then become the raw material for the rest of the custom logic within the script.
npx @phala/fn run dist/index.js -a 0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000
00000000000000000000000000000000000000000000000000000000043078303100000000000000000000000000000000000000000000000000000000 https://api-mumbai.lens.dev
# handle req: 0x0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000043078303100000000000000000000000000000000000000000000000000000000
# Request received for profile 0x01# response: 0,1,201# {"output":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c9"}
# โจ Done in 1.42s.
We have now successfully tested the default Phat Contract and ran a test to verify the function returns a response as expected.
Testing Default Phat Contract with Local Hardhat Node
Previously we showed how to test the default Phat Contract locally without a running node, but we can also run two other tests.
Run the default mocha e2e tests.
Run local hardhat node and watch the requests that are pushed and see how the Phat Contract transforms the data.
Run the default mocha e2e tests
Letsโs start with the first test case.
Note: You will need to ensure you configure your local vars POLYGON_RPC_URL and MUMBAI_RPC_URL.env file. You can do this with cp .env.local .env then edit the .env with your information.
npmrunlocalhost-test
You will now see that all test cases have passed.
npmrunlocalhost-test# Compiled 14 Solidity files successfully## OracleConsumerContract.sol# โ Push and receive message (1664ms)## 1 passing (2s)## โจ Done in 3.29s.
This is how the e2e mocha test will look like. You can customize this file at OracleConsumerContract.ts.
Run local hardhat node and watch the requests that are pushed and see how the Phat Contract transforms the data
First we will start a local hardhat node.
npmrunlocalhost-node
With our hardhat node running locally, we can now deploy the OracleConsumerContract.sol contract to the local hardhat network.
Make sure to copy the deployed contract address when you deploy your own contract locally. Note you contract address will be different than 0x0165878A594ca255338adfa4d48449f69242Eb8F. We will now start watching the hardhat node deployed contract for any new requests.
npx @phala/fn watch 0x0165878A594ca255338adfa4d48449f69242Eb8F artifacts/contracts/OracleConsumerContract.sol/OracleConsumerContract.json dist/index.js -a https://api-mumbai.lens.dev/
npx @phala/fn watch 0x0165878A594ca255338adfa4d48449f69242Eb8F artifacts/contracts/OracleConsumerContract.sol/OracleConsumerContract.json dist/index.js -a https://api-mumbai.lens.dev/
# Listening for OracleConsumerContract.sol MessageQueued events...
Letโs now make a new request and see what happens with the listenerโs output. In separate tab, you will push a request with the following.
Themumbai testnet is deprecated since 2024/04/08, meaning the steps to deploy to a testnet will no longer work out of the box.
You can opt to use the amoy testnet or any other EVM testnet instead.
With the contracts successfully compiled, now we can begin deploying first to Polygon Mumbai Testnet. If you have not gotten MATIC for Mumbai Testnet then get MATIC from a faucet. Ensure to save the address after deploying the Consumer Contract because this address will be use in the "Configure Client" section of Phat Bricks UI. The deployed address will also be set to the environment variable MUMBAI_CONSUMER_CONTRACT_ADDRESS.
npmruntest-deploy
# deploy contracts to testnet mumbainpmruntest-deploy# Deploying...## ๐ Your Consumer Contract has been deployed, check it out here: https://mumbai.polygonscan.com/address/0x10FA409109E073C15b77A8352cB6A89C12CD1605
## You also need to set up the consumer contract address in your .env file:## MUMBAI_CONSUMER_CONTRACT_ADDRESS=0x10FA409109E073C15b77A8352cB6A89C12CD1605## Configuring...# Done# โจ Done in 8.20s.
(Optional) Verify Contract on Polygon Mumbai Testnet
Ensure to update the mumbai.arguments.ts file with the constructor arguments used to instantiate the Consumer Contract. If you add additional parameters to the constructor function then make sure to update the mumbai.arguments.ts file.
Note: Your contract address will be different than 0x090E8fDC571d65459569BC87992C1026121DB955 when verifying your contract. Make sure to get your actual contract address from the console log output after executing npm run test-deploy.
npmruntest-verify--0x090E8fDC571d65459569BC87992C1026121DB955# $ hardhat verify --network mumbai --constructor-args mumbai.arguments.ts 0x090E8fDC571d65459569BC87992C1026121DB955# Nothing to compile# No need to generate any newer typings.# Successfully submitted source code for contract# contracts/OracleConsumerContract.sol:OracleConsumerContract.sol at 0x090E8fDC571d65459569BC87992C1026121DB955# for verification on the block explorer. Waiting for verification result...## Successfully verified contract OracleConsumerContract.sol on Etherscan.# https://mumbai.polygonscan.com/address/0x090E8fDC571d65459569BC87992C1026121DB955#code# โจ Done in 5.91s.
Deploy Phat Contract to PoC6 Testnet
For customizing your Phat Contract, checkout Phat Contract custom configurations in Customizing Your Phat Contract to learn more before deploying to PoC6 testnet.
Now that are Phat Contract has built successfully, let's deploy to Phala PoC6 Testnet with the following command:
# If you did not export your Polkadot account in a # polkadot-account.json file in the root of projectnpx@phala/fnupload--coreSettings=https://api-v2-mumbai-live.lens.dev/# If polkadot-account.json is in the root of projectnpx@phala/fnupload-a./polkadot-account.json--coreSettings=https://api-v2-mumbai-live.lens.dev/
Here is the expected output:
Note: your contract IDs will vary and not be the same as the IDs below.
npx@phala/fnupload-a./polkadot-account.json--coreSettings=https://api-v2-mumbai-live.lens.dev/# ? Please enter your client RPC URL https://polygon-mumbai.g.alchemy.com/v2/JLjOfWJycWFOA0kK_SJ4jLGjtXkMN1wc# ? Please enter your consumer address 0xA4Be456Fd0d41968a52b34Cdb8Ba875F2281134a# ? Please Enter hahaha account password [hidden]# Creating an optimized build... done# Compiled successfully.## 17.64 KB dist/index.js# Connecting to the endpoint: wss://poc6.phala.network/ws... done# Querying your Brick Profile contract ID... done# Your Brick Profile contract ID: 0x4071788a8ce6fbab0cacea0cb1aa52853b5537db7955643e5010c22913c2b1dd# Instantiating the ActionOffchainRollup contract... done# The ActionOffchainRollup contract has been instantiated: 0x9c777c16b0a185caa895835b8f3b9e8d67be9f5e30197f71b4d32d2b8fde4b3b
# Setting up the actions... done# ๐ Your workflow has been added, you can check it out here: https://bricks-poc6.phala.network/workflows/0x4071788a8ce6fbab0cacea0cb1aa52853b5537db7955643e5010c22913c2b1dd/3
# Your Attestor address: 0x2b5fe2920cce2f522d69613adaa9378ba43b687d# Your WORKFLOW_ID: 3# โจ Done in 73.22s.
Go to the Phala Dashboard and you can see your newly deployed Phat Contract.
Interact with Consumer Contract on Polygon Mumbai
Test Consumer Contract on Mumbai with a few tests to check for malformed requests failures, successful requests, and set the attestor.
npmruntest-set-attestor
npmruntest-set-attestor# $ hardhat run --network mumbai ./scripts/mumbai/set-attestor.ts# Setting attestor...# ๐จNOTE๐จ# Make sure to set the Consumer Contract Address in your Phat Bricks ๐งฑ UI dashboard (https://bricks-poc6.phala.network)
# - Go to 'Configure Client' section where a text box reads 'Add Consumer Smart Contract'# - Set value to 0x090E8fDC571d65459569BC87992C1026121DB955# Done# โจ Done in 2.69s.
Test pushing a malform request.
npmruntest-push-malformed-request
npmruntest-push-malformed-request# $ hardhat run --network mumbai ./scripts/mumbai/push-malformed-request.ts# Pushing a malformed request...# Done# โจ Done in 2.48s.
Test pushing a valid request.
npmruntest-push-request
npmruntest-push-request# Pushing a request...# Done# โจ Done in 2.97s.
Update Phat Contract on Phala PoC6 Testnet
Sometimes you may have had a bug in your script or you want to test things out on the fly without deploying a whole new Phat Contract. We now allow you to update your Phat Contract easily in the commandline. Now let's update the Phat Contract with the following command:
# If you did not export your Polkadot account in a # polkadot-account.json file in the root of projectnpx@phala/fnupdate# If polkadot-account.json is in the root of projectnpx@phala/fnupdate-a./polkadot-account.json
npx@phala/fnupdate-a./polkadot-account.json# ? Please Enter hahaha account password [hidden]# Creating an optimized build... done# Compiled successfully.## 17.64 KB dist/index.js# Connecting to the endpoint: wss://poc6.phala.network/ws... done# Querying your Brick Profile contract ID... done# Your Brick Profile contract ID: 0x4071788a8ce6fbab0cacea0cb1aa52853b5537db7955643e5010c22913c2b1dd# Checking your workflow settings... done# Updating... done# The Phat Function for workflow 1 has been updated.# โจ Done in 10.82s.
Congrats! You've now successfully updated your Phat Contract!
Deploy to Polygon Mainnet
Ensure to save the address after deploying the Consumer Contract because this address will be used in the "Configure Client" section of Phat Bricks UI. The deployed address will also be set to the environment variable POLYGON_CONSUMER_CONTRACT_ADDRESS.
Note: Your contract address will be different than 0xbb0d733BDBe151dae3cEf8D7D63cBF74cCbf04C4 when verifying your contract. Make sure to get your actual contract address from the console log output after executing npm run main-deploy.
npmrunmain-deploy# Deploying...## ๐ Your Consumer Contract has been deployed, check it out here: https://polygonscan.com/address/0xbb0d733BDBe151dae3cEf8D7D63cBF74cCbf04C4
## You also need to set up the consumer contract address in your .env file:## POLYGON_CONSUMER_CONTRACT_ADDRESS=0xbb0d733BDBe151dae3cEf8D7D63cBF74cCbf04C4## Configuring...# Done# โจ Done in 8.20s.
(Optional) Verify Contract on Polygon Mainnet
Ensure to update the polygon.arguments.ts file with the constructor arguments used to instantiate the Consumer Contract. If you add additional parameters to the constructor function then make sure to update the polygon.arguments.ts file.
npmrunmain-verify--0xbb0d733BDBe151dae3cEf8D7D63cBF74cCbf04C4# Nothing to compile# No need to generate any newer typings.# Successfully submitted source code for contract# contracts/OracleConsumerContract.sol.sol:OracleConsumerContract.sol.sol.sol at 0xbb0d733BDBe151dae3cEf8D7D63cBF74cCbf04C4
# for verification on the block explorer. Waiting for verification result...## Successfully verified contract OracleConsumerContract.sol on Etherscan.# https://polygonscan.com/address/0xbb0d733BDBe151dae3cEf8D7D63cBF74cCbf04C4#code# Done in 8.88s.
Deploy Phat Contract to Phala Mainnet
For customizing your Phat Contract, Phat Contract custom configurations can be found here in Customizing Your Phat Contract to learn more before deploying to Phala Mainnet.
Now that are Phat Contract has built successfully, let's deploy to Phala Mainnet with the following command:
# If you did not export your Polkadot account in a # polkadot-account.json file in the root of projectnpx@phala/fnupload--mode=production--coreSettings=https://api-v2.lens.dev/# If polkadot-account.json is in the root of projectnpx@phala/fnupload--mode=production-a./polkadot-account.json--coreSettings=https://api-v2.lens.dev/
Here is the expected output:
Note: your contract IDs will vary and not be the same as the IDs below.
npx@phala/fnupload--mode=production-a./polkadot-account.json--coreSettings=https://api-v2.lens.dev/# ? Please enter your client RPC URL https://polygon.g.alchemy.com/v2/JLjOfWJycWFOA0kK_SJ4jLGjtXkMN1wc# ? Please enter your consumer address 0xA4Be456Fd0d41968a52b34Cdb8Ba875F2281134a# ? Please Enter hahaha account password [hidden]# Creating an optimized build... done# Compiled successfully.## 17.64 KB dist/index.js# Connecting to the endpoint: wss://api.phala.network/ws... done# Querying your Brick Profile contract ID... done# Your Brick Profile contract ID: 0x4071788a8ce6fbab0cacea0cb1aa52853b5537db7955643e5010c22913c2b1dd# Instantiating the ActionOffchainRollup contract... done# The ActionOffchainRollup contract has been instantiated: 0x9c777c16b0a185caa895835b8f3b9e8d67be9f5e30197f71b4d32d2b8fde4b3b
# Setting up the actions... done# ๐ Your workflow has been added, you can check it out here: https://bricks-poc6.phala.network/workflows/0x4071788a8ce6fbab0cacea0cb1aa52853b5537db7955643e5010c22913c2b1dd/3
# Your Attestor address: 0x2b5fe2920cce2f522d69613adaa9378ba43b687d# Your WORKFLOW_ID: 2# โจ Done in 73.22s.
Interact with Consumer Contract on Polygon Mainnet
Execute Scripts to Consumer Contract on Polygon Mainnet. The Consumer Contract on Polygon Mainnet with a few actions to mimic a malformed request, successful requests, and set the attestor.
npmrunmain-set-attestor# Setting attestor...# ๐จNOTE๐จ# Make sure to set the Consumer Contract Address in your Phat Bricks ๐งฑ UI dashboard (https://bricks-poc6.phala.network)
# - Go to 'Configure Client' section where a text box reads 'Add Consumer Smart Contract'# - Set value to 0xbb0d733BDBe151dae3cEf8D7D63cBF74cCbf04C4# Done# โจ Done in 1.56s.# execute push-malformed-requestnpmrunmain-push-malformed-request# Pushing a malformed request...# Done# execute push-requestnpmrunmain-push-request# Pushing a request...# Done
Update Phat Contract on Phala Mainnet
Sometimes you may have had a bug in your script or you want to test things out on the fly without deploying a whole new Phat Contract. We now allow you to update your Phat Contract easily in the command line. Now let's update the Phat Contract with the following command:
# If you did not export your Polkadot account in a # polkadot-account.json file in the root of projectnpx@phala/fnupdate--mode=production# If polkadot-account.json is in the root of projectnpx@phala/fnupdate--mode=production-a./polkadot-account.json
npx@phala/fnupdate--mode=production-a./polkadot-account.json# ? Please Enter hahaha account password [hidden]# Creating an optimized build... done# Compiled successfully.## 17.64 KB dist/index.js# Connecting to the endpoint: wss://api.phala.network/ws... done# Querying your Brick Profile contract ID... done# Your Brick Profile contract ID: 0x4071788a8ce6fbab0cacea0cb1aa52853b5537db7955643e5010c22913c2b1dd# Checking your workflow settings... done# Updating... done# The Phat Function for workflow 1 has been updated.# โจ Done in 10.82s.
๐ Congrats! You've now successfully updated your Phat Contract!
Closing
Once you have stored, the deployed address of the Consumer Contract and set the value in the "Configure Client" section of the deployed Phala Oracle, you will now have a basic boilerplate example of how to connect your Polygon dApp to a LensAPI Oracle Blueprint. Execute a new requests and check if your configuration is correct like below: