Swisstronik Docs
  • 🇨🇭About Swisstronik
    • What is Swisstronik?
    • Swisstronik vs Ethereum
    • Useful links
  • 🌐General
    • Intel SGX
    • Governance
      • On-Chain Proposal
      • Formatting a Proposal
      • Submitting a Proposal
      • Governable Parameters
    • Community Pool
    • Accounts
    • Transactions
    • Gas and Fees
    • Coin & Tokens
  • ⚒️Development
    • Endpoints
    • Connect wallets
      • MetaMask (EVM) - Manual
      • Keplr (Cosmos)
      • Testnet Metamask (EVM) - Chainlist
      • Testnet MetaMask (EVM) - Manual
      • Testnet Keplr (Cosmos)
    • Get test coins
    • SwisstronikJS SDK
      • SwisstronikJS Functions
      • Swisstronik & Ethereum transactions
      • Transaction - code sample
      • Swisstronik & Ethereum calls
      • Call - code sample
    • Swisstronik CLI
      • Installation
      • Configuration
      • Key management
      • Queries
      • Sending SWTR
      • For SDI Issuers
    • Guides
      • Contract deployment - Hardhat
        • 1. Setting up the Hardhat environment
        • 2. Configure hardhat.config.js
        • 3. Write and compile the smart contract
        • 4. Deploy the smart contract
        • 5. Interact with the contract - Transaction
        • 6. Interact with the contract - Call
      • Contract deployment - Remix IDE
      • Deployment & Interaction PERC-20
        • ERC-20 & PERC-20
        • Sample PERC20 contract
        • Deployment & Interaction with contract
        • How to use encryption
      • Contract verification
      • SDI for dapp developers
    • Local testnet
    • Web3JS, Ethers, Viem and other third-party libraries
  • 🖥️Node setup
    • Setup SGX
      • Supported Hardware
      • Setup Intel SGX
    • Setup node
      • Mainnet
        • v1.0.1 Upgrade
      • Testnet
        • Install from .deb package
        • Configure node
        • Upgrade your testnet node
          • Swisstronik v3 Testnet
          • Swisstronik v4 Testnet
          • Swisstronik v5 Testnet
          • Swisstronik v5.1 Testnet
          • Swisstronik v6 Testnet
          • Swisstronik v7 Testnet
          • Swisstronik v8 Testnet
        • Seed Node
        • Live Peers
        • Genesis Mirror Download
    • CLI Cheatsheet
  • 🤝Delegators
    • What is a delegator?
    • Delegator Guide (CLI)
    • Delegators Security
Powered by GitBook
On this page
  • Example #1. Send encrypted transaction
  • Example #2. Send encrypted balanceOf request
  1. Development
  2. Guides
  3. Deployment & Interaction PERC-20

How to use encryption

PreviousDeployment & Interaction with contractNextContract verification

Last updated 11 months ago

Methods such as eth_estimateGas, eth_call, eth_sendTransaction should have encrypted data field. To do it, you can use

Example #1. Send encrypted transaction

Let's take a look on sample function that accepts ethers signer, destination address (address of contract or EOA), raw data field and value to be sent within transaction. This function will request node public key to perform ECDH and derive shared encryption key and then will encrypt provided data using DEOXYS-II algorithm

const { encryptDataField } = require('@swisstronik/utils')

// Encrypts data field and sends encrypted transaction
// * signer – ethers signer with connected provider
// * destination - destination address
// * data – raw (unencrypted) transaction `data` field
// * value – amount of aswtr to be sent within transaction
const sendShieldedTransaction = async (signer, destination, data, value) => {
    // Encrypt transaction data. `encryptDataField` function also returns 
    // used encryption key to be able decrypt node response. It will be useful 
    // in case if you're sending some query (for example, request PERC20 balance)
    const [encryptedData] = await encryptDataField(
        signer.provider.connection.url,
        data,
        // encryptionKey – also you can provide encryption key by yourself
        // if you want to be able to decrypt transaction payload in the future.
        // Otherwise, it will generate random encryption key using `tweetnacl`
        // library
    )

    // Construct and sign transaction with encrypted data. This transaction will
    // be sent as a regular Ethereum transaction
    return await signer.sendTransaction({
        from: signer.address,
        to: destination,
        data: encryptedData,
        value,
    })
}

Example #2. Send encrypted balanceOf request

Let's take a look on two functions which are used to obtain PERC20 token balance

const { encryptDataField, decryptNodeResponse } = require('@swisstronik/utils')

// Obtains PERC20 token balance using ethers wallet and contract instance
const getTokenBalance = async (wallet, contract) => {
    const req = await sendSignedShieldedQuery(
      wallet,
      contract.address,
      contract.interface.encodeFunctionData("balanceOf", [wallet.address]),
    );
  
    const balance = contract.interface.decodeFunctionResult("balanceOf", req)[0]
    return balance
}

// Sends signed encrypted query to the node
const sendSignedShieldedQuery = async (wallet, destination, data) => {
    if (!wallet.provider) {
        throw new Error("wallet doesn't contain connected provider")
    }

    // Encrypt call data
    const [encryptedData, usedEncryptedKey] = await encryptDataField(
        wallet.provider.connection.url,
        data
    )

    // Get chain id for signature
    const networkInfo = await wallet.provider.getNetwork()
    const nonce = await wallet.getTransactionCount()

    // We treat signed call as a transaction, but it will be sent using eth_call
    const callData = {
        nonce: ethers.utils.hexValue(nonce), // We use nonce to create some kind of reuse-protection
        to: destination,
        data: encryptedData,
        chainId: networkInfo.chainId,
    }

    // Extract signature values
    const signedRawCallData = await wallet.signTransaction(callData)
    const decoded = ethers.utils.parseTransaction(signedRawCallData)

    // Construct call with signature values
    const signedCallData = {
        nonce: ethers.utils.hexValue(nonce), // We use nonce to create some kind of reuse-protection
        to: decoded.to,
        data: decoded.data,
        v: ethers.utils.hexValue(decoded.v),
        r: ethers.utils.hexValue(decoded.r),
        s: ethers.utils.hexValue(decoded.s),
        chainId: ethers.utils.hexValue(networkInfo.chainId)
    }

    // Do call
    const response = await wallet.provider.send('eth_call', [signedCallData, "latest"])

    // Decrypt call result
    return await decryptNodeResponse(wallet.provider.connection.url, response, usedEncryptedKey)
}

Function getTokenBalance creates a signature from owner and calls sendSignedShieldedQuery to encrypt function data, sign the query, send the call and decrypt the response

⚒️
https://www.npmjs.com/package/@swisstronik/utils