Sapphire ParaTime is like a rollup on top of Oasis Consensus chain. Consensus handles governance. Sapphire handles solidity contracts with private variables/storage.
Install MetaMask. Then click "Add to MetaMask" under "sapphire.oasis.io" https://docs.oasis.io/dapp/sapphire/network#rpc-endpoints
- Already have ROSE tokens on Consensus? move them to sapphire with
- https://rose.oasis.io/move/ (uses wallets like metamask)
- https://wallet.oasis.io/ (click ParaTimes, Deposit to ParaTime)
- Ready to buy?
- use an exchange that supports Sapphire ROSE (e.g. MEXC, XeggeX, KuCoin)
- use an exchange that supports Consensus ROSE (e.g. coinbase, binance, transak) and move ROSE through https://rose.oasis.io/move/ to Sapphire
- Already have ROSE tokens on Emerald?
- https://wallet.oasis.io/ (click ParaTimes, Withdraw to Consensus from Emerald. And then click ParaTimes, Deposit to ParaTime Sapphire)
- Already have wROSE tokens on Sapphire? unwrap them with https://wrose.oasis.io/
- open MetaMask and switch to Sapphire chain
- oasis explorer https://explorer.dev.oasis.io/mainnet/sapphire/address/0x0000000000000000000000000000000000000000
- TODO: make grpc explorer that fetches staked balance too
- https://rose.oasis.io/stake/ (stake, view staked balance, unstake) same validators
- ecosystem dapps (maybe https://accumulated.finance/stake/rose)
- use an exchange that supports Sapphire ROSE (e.g. MEXC, XeggeX, KuCoin)
- use an exchange that supports Consensus ROSE (e.g. coinbase, binance) and move ROSE through https://rose.oasis.io/move/ to Consensus
- TODO: install Sapphire MetaMask Snap https://www.npmjs.com/package/@oasisprotocol/sapphire-snap: so you can see what you are signing in encrypted transactions
- use a hardware wallet that MetaMask supports: so PC malware can't steal tokens
- advanced: use multi-signature wallet https://safe.oasis.io/
- list https://oasisprotocol.org/ecosystem / https://oasisrose.garden/dapps/
- view if their contract is verified in https://explorer.dev.oasis.io/mainnet/sapphire/address/0x6665a6Cae3F52959f0f653E3D04270D54e6f13d8
- view their verified contract in https://sourcify.dev/#/lookup/0x6665a6Cae3F52959f0f653E3D04270D54e6f13d8
- if private dApp website is removed, use their verified contract in https://abi-playground.oasis.io/?network=23294&contractAddress=0x6665a6Cae3F52959f0f653E3D04270D54e6f13d8
- Contract: use
privatekeyword in solidity, and don't emit events with private data - Frontend: add https://www.npmjs.com/package/@oasisprotocol/sapphire-paratime (diagram) or @oasisprotocol/sapphire-ethers-v6 or @oasisprotocol/sapphire-viem-v2
- Backend: create an off-chain app that runs in trusted execution environment https://docs.oasis.io/rofl/app
Use APIs:
-
Oasis gRPC: https://grpc.oasis.io
reliable, hard to use, very few interesting endpoints, loadbalanced so nodes can possibly return different height
use with npm @oasisprotocol/client-rt
import * as oasis from '@oasisprotocol/client' import * as oasisRT from '@oasisprotocol/client-rt' import BigNumber from 'bignumber.js' export const sapphireConfig = { mainnet: { runtimeId: '000000000000000000000000000000000000000000000000f80306c9858e7279', }, testnet: { runtimeId: '000000000000000000000000000000000000000000000000a6d1e3ebf60dff6c', }, decimals: 18, } export async function getSapphireBalance(ethAddress: `0x${string}`) { const nic = new oasis.client.NodeInternal('https://grpc.oasis.io') const consensusWrapper = new oasisRT.consensusAccounts.Wrapper(oasis.misc.fromHex(sapphireConfig.mainnet.runtimeId)) const underlyingAddress = await oasis.address.fromData( oasisRT.address.V0_SECP256K1ETH_CONTEXT_IDENTIFIER, oasisRT.address.V0_SECP256K1ETH_CONTEXT_VERSION, oasis.misc.fromHex(ethAddress.replace('0x', '')), ) const balanceResult = await consensusWrapper .queryBalance() .setArgs({ address: underlyingAddress, }) .query(nic) const balance = oasis.quantity.toBigInt(balanceResult.balance) return { raw: balance, formatted: fromBaseUnits(balance, sapphireConfig.decimals), } } function fromBaseUnits(valueInBaseUnits: bigint, decimals: number): string { const value = new BigNumber(valueInBaseUnits.toString()).shiftedBy(-decimals) // / 10 ** decimals if (value.isNaN()) { throw new Error(`Not a number in fromBaseUnits(${valueInBaseUnits})`) } return value.toFixed() }
-
Oasis Explorer's API: https://nexus.oasis.io/v1/spec/v1.html
not as reliable, some endpoints are slow and throw timeout errors, data can sometimes be a few minutes behind gRPC
-
Web3 gateway: https://sapphire.oasis.io
many ethereum-compatible tools use this, but it only returns EVM transactions, (e.g. this would be missing https://explorer.dev.oasis.io/mainnet/sapphire/tx/cb54b077f856756e616002cd8a328dc97ae875dc6910664e36d9aed18511480c - moving ROSE from/to Consensus, making a Sapphire transfer using Oasis CLI, staking using Oasis CLI)
-
Rosetta API, without most useful optional endpoints: https://rosetta.oasis.io/api/block
eww
(You can also create a custom ParaTime, e.g. clone Sapphire, but only allow your compute nodes)