Secret Network
WebsiteDiscordGithub
  • πŸ‘‹INTRODUCTION
    • Secret Network Introduction
    • Secret Network Techstack
      • Private transactions - A quick summary
      • Blockchain Technology
        • Cosmos Basics
        • Tendermint
        • Cosmos SDK
        • IBC
        • CosmWasm
      • Privacy Technology
        • Encryption - Key Management
          • Overview
          • Key Derivation & Encryption Techniques
          • The Initialization Of Secret Network
          • Full Node Boostrap
          • Contract State Encryption
          • Transaction Encryption
          • Consensus seed rotation
        • Trusted Execution Environmentsβ€Š (TEE) β€”β€Š Intel SGX
          • How Secret Network Uses SGX
          • SGX-SPS Security & Reliabillity
          • Remote Attestation
          • Trusted & Untrusted Core
          • Sealing
        • Private smart contracts - overview
  • πŸ’»Development
    • 🏠Getting Started
      • Setting Up Your Environment
        • Cargo.toml Best Practices (Crates vs Dependencies)
      • Compile and Deploy
      • Running the Application
      • Compile and Deploy on Secret testnet (best for Javascript devs)
      • Fullstack dApp Integration
    • πŸ€“Secret Contracts
      • Secret Contracts & CosmWasm
        • Framework overview
        • Secret Contract Components
          • Instantiation Message
          • Execution Message
          • Query Message
          • Deps/DepsMut
          • Storage
            • Prefixed Storage
            • Singleton
            • Keymap
            • Append Store
            • Best practices
        • CosmWasm vs Secret CosmWasm
      • Secret Tokens (SNIP-20)
      • Contract - module call
      • Secret contract - Design Space/Features
        • Secret Contracts introduction
        • Gas/Fee usage
        • TPS and scalability
        • Privacy Essentials
        • Access Control
          • Viewing Keys
          • Permits
        • Trusted and untrusted data
        • Secret-VRF - on-chain Randomness
        • Privacy design
          • Mitigate privacy risks - full guide
          • Gas Evaporation & Tracking
        • Confidential Computing Layer
        • Fiat/Crypto Onboarding
        • Account abstraction
        • Fee abstraction
        • Wallet support
        • Bridge (messaging/tokens)
        • IBC (Hooks, PFM, Wasm)
        • Price Oracles
        • Auto Restaking
      • Permissioned Viewing
        • Viewing Keys
        • Permits
      • Cross Contract Communication
      • Submessages
        • get_contract_code_hash
      • Randomness API - Secret VRF
        • Native On-chain randomness
        • Randomness over IBC
      • Execution Finalization
      • Factory Contracts
      • Contract Migration
        • Manual - < v1.11
        • Native - from v1.11
      • Cross-deploy Vanilla CW and Secret Contracts
      • Testing Secret Contracts
        • Unit Tests
        • Continuous Integration
        • Datatype Handling - Uint, floats etc.
    • πŸ‘€Secret Contract - Reference, Guides, Examples
      • Starter guide - Millionaire's Problem
      • Reference Contracts
      • Open source dApps
      • Tools & Libraries
        • Network interaction SDKs
          • Secret.js (JavaScript)
          • SecretPy (Python)
          • SecretK (Kotlin)
          • Secret.NET
            • Snippets
              • Deploying a Contract
              • Send Native Coin
              • Query a Contract
              • Create a new Wallet
              • Permits
              • SNIP20
              • SNIP721
          • Shade.Js
        • LocalSecret - Devnet docker
        • Smart contract - Tools/Utils
          • Secret Toolkit
          • CW-Plus
          • Fadroma - SC framework
          • Hidden Gems
          • Other
            • Secret IDE
            • Polar
    • πŸ–ΌοΈFrontend Development
      • Getting Started with SecretJS
        • Usage Examples
          • Sending Queries
          • Sending Messages
          • Contract Migration
          • Wallet Integrations
          • Query Permits
          • SNIP20 (SCRT Tokens)
          • SNIP721 (Secret NFTs)
      • Feegrant
        • Understanding Feegrant allowances
        • Grant allowances
        • Using grant allowances to execute transactions
        • Using the Fee Grant Faucet
    • πŸ“¬Deployment Addresses/ API Endpoints
      • Secret (SNIP 20) token contracts list
        • SNIP Asset naming guidelines
      • Connecting to the Network
        • API Endpoints Mainnet (Secret-4)
        • API Endpoints Testnet (Pulsar-3)
        • Usage examples
        • Comparison of endpoint types
      • Create your own SNIP-25 IBC Token
  • Secret AI
    • 🀝Introduction
    • πŸ—οΈArchitecture
    • πŸ‘©β€πŸ’»Secret AI SDK
      • Setting Up Your Environment
      • Running the Application
    • πŸͺ™Economics
    • Smart Contract Reference
      • SubscriptionManager
      • WorkerManager
      • RewardsManager
  • 🌐SecretVM - Confidential Virtual Machines
    • 🀝Introduction
    • πŸ—οΈArchitecture
    • β˜‘οΈAttestation
      • What is Attestation
      • Obtaining Attestation Data
      • Attestation Report - Key Fields
      • Chain of Trust
    • 🏁Launching a SecretVM
    • πŸ› οΈManaging SecretVM Lifecycle
    • βœ…Verifying a SecretVM
      • 🐒Full Verification
      • 🐰Quick Verification
    • πŸ’‘Best Practices for Developers
    • πŸ“–Glossary
  • πŸ”“Confidential Computing Layer
    • πŸ§‘β€πŸš€IBC Developer Toolkit
      • Basics
        • Overview
        • Cross-chain Messaging with IBC Hooks
          • Functions, Methods, and Data Structures
          • Typescript SDK
          • IBC-Hooks
        • IBC Relaying with Go Relayer
      • Usecases
        • Storing Encrypted Data on Secret Network
          • Key-Value store Developer Tutorial
        • Secret VRF for IBC with IBC-Hooks
        • Confidential Voting
        • Sealed Bid Auctions
      • Supported Networks
        • Mainnet
        • Testnet
    • 🀝Ethereum (EVM) Developer Toolkit
      • Basics
        • Overview
        • Connecting Metamask to Secret Network
        • SecretPath + Reown integration
        • Cross-chain Messaging
          • SecretPath
            • Architecture Overview
            • Detailed Architecture
            • SecretPath Developer Tutorials
            • Public EVM Gateway Architecture
            • How to deploy SecretPath on your chain
          • Axelar GMP
            • Architecture Overview
            • Axelar GMP Developer Tutorial
      • Usecases
        • Storing Encrypted Data on Secret Network
          • Key-Value store Developer Tutorial
        • Sealed Bid Auction
          • Sealed Bid Auction Developer Tutorial
        • Confidential Voting
          • Confidential Voting Developer Tutorial with SecretPath
        • VRF
          • Implementing VRF into any EVM Contract
          • VRF Developer Tutorial
          • Performance figures of SecretVRF vs competitors
          • Using encrypted payloads for VRF
          • Converting from Chainlink VRF to Secret VRF in four steps
        • Confidential Document Sharing
        • Tokens
          • From EVM to Secret
      • Supported Networks
        • EVM
          • EVM Mainnet
          • EVM Testnet
          • Gateway Contract ABI
        • Secret Gateway
          • SecretPath mainnet (secret-4) contracts
          • SecretPath testnet (pulsar-3) contracts
    • πŸ™ŒSolana Developer Toolkit
      • Usecases
        • Storing Encrypted Data on Secret Network
          • Key-value Store Developer Tutorial
        • VRF
          • VRF Developer Tutorial
      • Program IDs
        • Solana Mainnet & Testnet
        • Gateway Contract IDL
  • 🀫Overview, Ecosystem and Technology
    • πŸš€Secret Network Overview
      • The SCRT coin
      • Private Tokens
      • Use Cases
        • Decentralized Finance (DeFi)
        • Art And Digital Media
        • Gaming
        • Data Privacy
        • Payments And Transactions
        • Communication
      • The technology
      • History
      • Roadmap (Core development)
        • Secret 2.0
      • Where To Buy SCRT?
      • Using the Testnet
    • 🐸Ecosystem Overview
      • Wallets
      • Applications
      • Explorers & tools
      • Funding
        • SCRT Labs Grants
        • Dilutive funding/VC raise
        • Community Pool
        • Developer bounties
          • SCRT Labs bounties [on-hold]
          • CCBL [on-hold]
          • CCR [On-hold]
        • Application specific
          • Shade Grants
      • Contributors & Entities
        • Validators
        • SCRT Labs
        • Secret Foundation
        • Secret Committees
          • Support
          • Governance
      • Secret Network Dictionary
  • πŸ”§Infrastructure
    • πŸ”“Use SecretCLI
      • Secretcli vs. Secretd
      • Install
      • Configuration
      • Address Types
      • Key Types
      • Generating Keys
      • Viewing Keys
      • Query Transactions
      • Send Tokens
      • Multisig Keys
      • Multisig Transactions
      • Transaction Broadcasting
      • Fees & Gas
      • Fee Distribution
      • Secret Contracts
      • Slashing
      • Minting
      • Delegating
      • Restake
      • Nodes
      • Governance
        • Creating Governance Proposals
        • Query Proposals
        • Deposits
        • Voting
    • πŸ”Use Ledger hardware wallet
      • πŸ”Ledger with SecretCLI
    • πŸ–₯️Running a node/validator
      • Setting up a node/validator
        • Hardware setup
          • Hardware Compliance
          • VPS/Bare-Metal Compliance
            • Leaseweb Setup
            • PhoenixNAP Setup
            • Psychz Setup
            • nForce Setup
            • Vultr Setup
            • OVHCloud Setup
            • Microsoft Azure Setup
          • Patching your Node
          • Enclave verification
          • Registration troubleshooting
        • Testnet Setup
          • Install SGX
          • Install secretd
          • Setup Full Node
          • Testnet State Sync
          • Becoming a Testnet Validator
          • Installing CLI & Creating A New Address
        • Mainnet Setup
          • Install SGX
          • Install secretd
          • Setup Full Node
          • Quicksync / Snapshot
          • Statesync
          • Becoming A Validator
          • Installing CLI & Creating A New Address
      • Maintaining a node/validator
        • Slashing information
        • Migrating a Validator
        • Troubleshooting
        • Validator Backup
        • Server security
          • SSH authentication
          • Server configuration
          • Uncomplicated-Firewall (UFW)
          • Local CLI
        • Node Monitoring
          • Prometheus
            • Environment Preperation
            • Install Node Exporter
            • Install Prometheus
            • Configuring Prometheus
          • Grafana
            • Install Grafana
            • Grafana Dashboard
            • Next Steps
          • Docker
            • Install Docker
            • Configuration
            • Start Containers
            • Grafana Dashboard
            • Application Ports
            • Stop Containers
          • Goaccess
            • Install Goaccess
            • Setup Goaccess
        • Helpful commands
          • Query Validators
          • Bond Tokens
          • Withdraw Rewards
          • Query Delegations
          • Unbond Tokens
          • Query Unbonding-Delegations
          • Redelegate Tokens
          • Query Redelegations
          • Query Parameters
          • Query Pool
          • Query Delegations To Validator
      • API Noderunning
        • Running Multiple Nodes on the Same Server
        • Node Loadbalancing using Nginx
          • Setup Nginx
          • Example Nginx config
        • Using Auto heal to improve cluster uptime for Nginx
      • Sentry and Archive nodes
        • Mantlemint
        • Sentry Nodes
        • Archive Nodes
    • ⛓️IBC Relayers
      • Hermes
      • RLY
      • IBC channel database
    • πŸ†™Upgrade Instructions
      • v1.13
      • v1.12
      • v1.11
      • v1.10
      • v1.9
      • v1.8
      • v1.7
      • Shockwave Omega v1.6
      • v1.5
      • Shockwave Delta v1.4
      • Shockwave Delta v1.4 (Testnet)
      • Shockwave Alpha v1.3
      • Cosmovisor
      • Vulcan Network Upgrade (OLD)
    • ☠️Postmortems
      • SNIP-20 leaks
      • xApic
      • Secpk-Verifications Bloat
      • Earn Contract Exploit
      • Testnet Halt 95
    • ✍️Contribute to the documentation
      • Report Bugs
      • Suggest Enhancements
      • First Contribution Guide
      • Pull Request Templates
        • Update Documentation
        • Bug Fix
        • Improve Performance
        • Change Functionality
      • Style Guide
    • 🌊Versioning & Changelog
      • Secret Network v1.13
      • Secret Network v1.12
      • Secret Network v1.11
      • Secret Network v1.10
      • Secret network v1.9
      • Secret Network v1.7/1.8
      • Secret Network v1.6
      • Secret Network v1.5
      • Secret Network v1.4 (CosmWasm 1.0)
Powered by GitBook
On this page
  • Typescript Demo
  • Dependencies
  • Generating Wallets
  • Query Client
  • Signatures
  • Browser Wallets
  • Getting Signer and Signer Address
  • Generating the message and StdSignDoc
  • Encryption
  • Broadcasting the message

Was this helpful?

Edit on GitHub
Export as PDF
  1. Confidential Computing Layer
  2. IBC Developer Toolkit
  3. Basics
  4. Cross-chain Messaging with IBC Hooks

Typescript SDK

CCL IBC SDK for typescript developers

PreviousFunctions, Methods, and Data StructuresNextIBC-Hooks

Last updated 9 months ago

Was this helpful?

Typescript Demo

See a fullstack Next.js typescript demo (using Osmosis Mainnet). Code available .

Dependencies

For encryption, we recommend using @solar-republic/neutrino which has useful chacha20poly1305related functionalities and additional primitives for generating ephemereal lightweight wallets. Installation:

npm install --save @solar-republic/neutrino

For signing, encoding and other cryptographic needs in the Cosmos ecosystem, it is common to use the suite of @cosmjs packages. You can install the following:

npm install --save @cosmjs/crypto @cosmjs/amino @cosmjs/encoding

If you are developing in the browser environment or connecting to a public network you might also need

npm install --save @cosmjs/stargate
# or
npm install --save @cosmjs/cosmwasm-stargate

Note: You can also use any Typescript / Javascript package managers and runtimes e,g, bun, yarn, pnpm etc.

Generating Wallets

For chacha20poly1305, we need to use a crypthographic keypair and it's advised to use one that isn't the same as the user's wallet. The SDK provides a method for generating a new wallet that can be used for encryption purposes. For our purposes, we just need a private / public keys of Secp256k1 type and there are various ways to generate them.

@cosmjs/crypto

import { Slip10Curve, Random, Bip39, Slip10, stringToPath, Secp256k1 } from "@cosmjs/crypto"

const seed = await Bip39.mnemonicToSeed(Bip39.encode(Random.getBytes(16)));
const { privateKey } = Slip10.derivePath(Slip10Curve.Secp256k1, seed, stringToPath("m/44'/1'/0'/0"));
const pair = await Secp256k1.makeKeypair(privateKey);
// must be compressed to 33 bytes from 65
const publicKey = Secp256k1.compressPubkey(pair.pubkey);

@solar-republic/neutrino

import { gen_sk, sk_to_pk } from "@solar-republic/neutrino"

const privateKey = gen_sk(); 
const publicKey = sk_to_pk(privateKey);

@secretjs

import { Wallet } from "secretjs";
const { privateKey, publicKey } = new Wallet()

Query Client

Before proceeding to encryption, you might want to create a quering client that will be used for querying the state and contract of the Secret Network. At the very least, it is requited for fetching the public key of a gateway contract for deriving a shared key used later for encryption.

To perform a simple query on a secret contract we can use methods from @solar-republic/neutrino:

import { SecretContract } from "@solar-republic/neutrino"

// create a contract instantse
const contract = await SecretContract(
    secretNodeEndpoint,
    secretContractAddress
)

// query example:
// get encryption key from a gateway contract
const queryRes = await contract.query({ encryption_key: {} })


// extract res value
const gatewayPublicKey = queryRes[2]

For more persistent use-cases you can use secretjs:

import { SecretNetworkClient } from "secretjs"

// create a client:
const client = new SecretNetworkClient({
    chainId, 
    url // endpoint URL of the node
});

// query the contact and get the value directly
const gatewayPublicKey =  await client.query.compute.queryContract({
    contract_address
    code_hash, // optionally
    { encryption_key: {} } // query msg
});

Signatures

Browser Wallets

Most of the Cosmos wallets provide a method for signing arbitrary messages following the mentioned specification.

// window.keplr.signArbi....
signArbitrary(chainId: string, signer: string, data: string | Uint8Array) : Promise<StdSignature>

Although the API method requires a chainId, it is set to empty string before signing the message

Cosmology

CosmJS

Manually

Getting Signer and Signer Address

Firstly we need to get an amino signer that will be used for generating the signature. @cosmjs has a defined interface OfflineAminoSigner with signAmino and getAccounts methods and any other signer that implements it can be used for the purpose.

// In browser environment we can get it from a wallet extension. E.g with Keplr:
const signer = window.keplr.getOfflineSigner(chainId);


//  ...


// In Node environment we can use `Secp256k1Wallet` class that also implements `OfflineAminoSigner` interface
import { Secp256k1Wallet } from "@cosmjs/amino"


// see examples of generating a random above but in this case you will probably be using a persistent one from a .env file 
// you can also pass extra options like prefix as the second argument
const signer = await Secp256k1HdWallet.fromMnemonic(userMnemonic) 


//  ...

// Here we are getting the first accounts from the signer
// accessing the address and renaming it to `signerAddress` 
const [{ address : signerAddress }] =  await signer.getAccounts();

//  ...

Generating the message and StdSignDoc

To use signAmino, we need to generate a StdSignDoc object that will be used for signing the message to pass as an argument.

CosmJS provides a function for this:

function makeSignDoc(msgs: AminoMsg[], fee: StdFee, chainId: string, memo: string | undefined, accountNumber: number | string, sequence: number | string, timeout_height?: bigint): StdSignDoc;

The 036 standard requires the message fields to AminoMsg to be:

type AminoMsg = {
    // static type url
    type: ;
    value: {
        // signer address
        signer: string;
        // plaintext or base64 encoded message
        data: string;
    }
}

As for the rest of the fields, they can be set to an empty string or 0. The final example will look like this:

const data = "my message";


const signDoc  = makeSignDoc(
    [{                              // list of amino messages
        type: "sign/MsgSignData", 
        value:  { 
            signer: signerAddress, 
            data:   data 
        }
    }], 
    { gas: "0", amount: [] },      // StdFee
    "",                            // chainId 
    "",                            // memo
    0,                             // accountNumber
    0                              // sequence
    // timeout_height
)

After getting the document we can sign it with the signer:

const signRes = await signer.signAmino(signerAddress, signDoc);

Encryption

After getting a public key of a gateway contract you can use it to derive a shared key like this:

import { sha256, Random } from "@cosmjs/crypto"
import { fromBase64, toBase64, toAscii } from "@cosmjs/encoding";
import { chacha20_poly1305_seal, ecdh } from "@solar-republic/neutrino"
// this is a dependency of `@solar-republic/neutrino` so consider importing these methos 
import { concat, json_to_bytes } from "@blake.regalia/belt";


// ...
//   define
//  
//      `clientPrivateKey`
//      `gatewayPublicKey`
//      `signerAddress`
//
//   like described above
// ...


const sharedKey = sha256(ecdh(clientPrivateKey, gatewayPublicKey))

// We also need to generate a one-time nonce, which can be done like this:
const nonce =  Random.getBytes(12)

// Prepare a message for the action you want to take on the contract
const msg = ExecuteMsg { ...}


/// Defining payload structure idential to the Rust data structure
const payload : EncryptedPayload = {
    // e.g, cosmos1...
    user_address: signerAddress,
    // uint8array -> base64  (-> Binary)
    user_pubkey: toBase64(signerPubkey),
    // e.g. "cosmos" from "cosmos1..."
    hrp: signerAddress.split("1")[0], 
    // or to toBinary(msg) from `@cosmjs/cosmwasm-stargate`
    msg: toBase64(json_to_bytes(msg))
}


/// getting the payload ciphertext 
const ciphertext = concat(chacha20_poly1305_seal(
    sharedKey,
    nonce,
    // or toUtf8( JSON.stringify(payload) )  
    json_to_bytes( payload )
));

// finally the payload_hash is sha256 of the ciphertext
const ciphertextHash = sha256(ciphertext);


//    ...

Encrypting + Signing

Produced digest of hashing the ciphertext can be used as our message that we want to sign according to the 036 standard. The final message will look like this:

// calling `makeSignDoc` with nullifed fields like described earlier
const signDoc = getArb36SignDoc(signerAddress, ciphertextHash);
// signing the message
const signRes = await signer.signAmino(signerAddress, signDoc);

After this we are getting all the required fields for creating an EncryptedPayload message or an ExecuteMsg::Encrypted { ... }

const encrypted = {
    // uint8array -> base64  (-> Binary)
    nonce              :     toBase64(nonce),
    // public key of a pair that was used in deriving a shread key 
    user_key           :     toBase64(clientPublicKey),
    // ciphertext of with the user data and actual message
    payload            :     toBase64(ciphertext),
    // sha256 hash of the ciphertext
    payload_hash       :     toBase64(ciphertextHash),
    // signatire over sha256( getArb36SignDoc( payload_hash ) ) already in base64
    payload_signature  :     signRes.signature.signature,
}

Broadcasting the message

The encrypted message is safe to broadcast over public blockchain and other infrastructure. A common use-case in context of Cosmos account might be broadcasting it over IBC originating from a chain other than the Secret Network.

The potential use-case might involve broadcasting the message by initiating an IBC message directly and attaching the message as a payload (IBC-Hook) or passing the message to a smart contract on a remote chain to process and bridge it to the Secret Network.

Since Cosmwasm is quite flexible with defining messages due to supporting JSON serialization, it is possible the process is very similar in both cases so we only going to cover IBC-hooks for simplicity:

import { MsgTransfer } from "cosmjs-types/ibc/applications/transfer/v1/tx";
import { SigningStargateClient, MsgTransferEncodeObject } from "@cosmjs/stargate";

/// creating a client
const client = await SigningStargateClient(
    "https://rpc.cosmoshub.io"    //  endpoint of the remote network 
    signer,                       // offlineSigner  
)


// defining the IBC transfer message
const msg : MsgTransferEncodeObject = {
    typeUrl: "/ibc.applications.transfer.v1.MsgTransfer",
    value: MsgTransfer.fromPartial({
      sender:   signerAddress,
      receiver: secretGatewayContractAddress,
      sourceChannel: "channel-0",
      sourcePort: "transfer",
      timeoutTimestamp:  BigInt(
        // 5 minutes from now           |  ms -> ns
        Math.floor(Date.now() + 300_000) * 1_000_000
      ),
      // IBC Hook memo msg
      memo: JSON.stringify({
        wasm: {
            // must be same as receiver
            contract: secretGatewayContractAddress,
            // encrypted message defined above
            msg: encrypted
        }
      })
    })
}

// signing and broadcasting the message
const res = await client.signAndBroadcast(signerAddress, [msg])

To make sure that malicious applications aren't tricking the user into signing an actual blockchain transaction, it is discouraged to sign arbitrary blobs of data. To address the situation, there are various standards that inject additional data to the message before signing it. The most used in the Cosmos ecosystem is defined in which is also used in the SDK.

Here is a definition taken from documentation of :

Cosmology signArbitrary method as part of the interface for their wallet client and provides implementation / integration for every popular Cosmos wallet out there

The logic of the method has already been implemented and proposed as an addition to the library however it has been hanging in a unmerged PR for a while. You can find the full implementation with examples and tests

πŸ”“
πŸ§‘β€πŸš€
here
here
ADR 036
Keplr wallet
defines
[PR] Here