Git Product home page Git Product logo

docs.skale.space's People

Contributors

manuelbarbas avatar thegreataxios avatar

Watchers

 avatar

docs.skale.space's Issues

SKALE Connect

Suggestion for this Section

Divide example and theory since there's a lot of theory

Also, since we want to make sure the user on-boarding it's as simple as possible maybe we could have an Example Implementation section explaining step by step/script by script

  1. Claim.sol
  2. ClaimableToken.sol
  3. MainnetNFT.sol
  4. Oracle.js
  5. Oracle-utils.js
  6. Idex.js

Viem

Viem

Viem is a TypeScript interface for Ethereum that provides low-level stateless primitives for interacting with Ethereum.

Some of the main features are:

  • Abstractions over the JSON-RPC API
  • APIs for interacting with Smart Contracts
  • Utilities for working with ABIs

For more information check the View Documentation

Implementation Example

Package Install

npm i viem

Send Transaction

import {createPublicClient, http,parseGwei } from "viem";
import { privateKeyToAccount } from 'viem/accounts'
import { skaleChaosTestnet } from "viem/chains";
import {contract_abi,contract_adress} from "./contract";

import dotenv from 'dotenv'; 
dotenv.config();

async function main() {
	const client = createPublicClient({
		chain: skaleChaosTestnet,
		transport: http()
	});

	const pk = "0x";
	const account=privateKeyToAccount(pk);

	const signature = await account.signTransaction({
		to:contract_adress,
		gas:parseGwei('0.0005'),
		gasPrice:parseGwei('0.0001'),
		nonce: await client.getTransactionCount({address:account.address}),
		data: '0xeefa7dfd0000000000000000000000002b3937fe6ef38cd4be0d9ceb05823087b716d689'
	})

	const hash = await client.sendRawTransaction({serializedTransaction:signature});
	console.log(hash);
}

main()
	.catch((err) => {
		console.error(err);
		process.exitCode = 1;
	});

Using Coinbase Wallet

Coinbase Wallet is a self-custody crypto wallet, available as a browser extension and a mobile app on Android and iOS

Install the NPM Packages

npm install --save web3 @coinbase/wallet-sdk

Example Code

import CoinbaseWalletSDK from '@coinbase/wallet-sdk'
import Web3 from 'web3'

const APP_NAME = 'My Awesome App'
const APP_LOGO_URL = 'https://example.com/logo.png'
const SKALE_JSONRPC_URL = 'https://your.skale.endpoint'
const SKALE_CHAIN_ID = 123456

// Initialize Coinbase Wallet SDK
export const coinbaseWallet = new CoinbaseWalletSDK({
  appName: APP_NAME,
  appLogoUrl: APP_LOGO_URL,
  darkMode: false
})

// Initialize a Web3 Provider object
export const skale = coinbaseWallet.makeWeb3Provider(SKALE_JSONRPC_URL, SKALE_CHAIN_ID)

// Initialize a Web3 object
export const web3 = new Web3(skale)

ThirdWeb

Thirdweb

Thirdweb is a platform that sports a raft of no-code and low-code features developers can use to deploy web3 applications and create smart contracts to sell NFT collections.

It contains easy to onboard developers solutions for wallets, smart contracts and infrastructure. This solutions target different platforms and programming languages such as:

  • React and react native
  • Unity
  • Python
  • Go

For more information check the Thirdweb documentation.

Example Implementation

Wallets

Contracts

Infrastructure

sFUEL Station

sFUEL Station

The sFUEL Station is a general distribution for the SKALE Network. It supports multiple chains by default as well as both Mainnet and Testnet.

Usage of the Station

The sFUEL Station is a great tool that can be used for easy onboarding for users that utilize many different SKALE applications that are supported by the sFUEL Station.
However, the sFUEL Station can be a distraction for initial onboarding and should not be used as a primary sFUEL Distribution option, but available as an alternative for users.

Add your chain

Adding your chain to the sFUEL Station is a three-step process:

  1. Deploy an on-chain faucet. The on-chain faucet should at a minimum provide the functionality found on SKALE Proof-of-Work distribution, however, for a more robust contract that offers more control such as pausing, changing limits, and destruction; checkout the sFUEL Distribution Contract.

  2. Once the smart contract is deployed on your SKALE Chain, head over to the sFUEL Station on Github. Fork the repository, clone the repo down, and open up the folder in your favourite editor or terminal.

  • Edit pow.json and add your chain information into the proper location. If you are using a testnet/staging chain, make sure to add it into the first array. If this is for a mainnet chain, add it to the second array. The details required are chainId, display name, rpc url, and the public object which should have an address field, a fnHash which is the function that will be called by Proof of Work, and then the max fuel amount which should match your smart contract.

[NOTE]
The sFUEL Station for Staging/Testnet is currently operating in a different way than the Mainnet distribution. Send 1 sFUEL to 0x61590e0C2aC946E227Afed97873848cc0ad4aE48 on your SKALE Chain.

  1. Edit the chains.json, platforms.json, and projects.json accordingly.

Management

Managing your on-chain faucet is very simple, just keep it filled up. How much you want to put in your on-chain faucet is up to you. Less is always better, however, if you know that you may not be able to fill it often, err on the side of more to reduce downtime and potential issues.

IMA.js

IMA.js

IMA.JS is a Typescirpt/Javascript library which implements client for SKALE Interchain Messaging Agent (IMA).

Implementation Example

Package Install

npm install --save @skalenetwork/ima-js

Usage

Initialization

There are 2 ways to use IMA.js library in your project:

  • As a single object that contains both Mainnet and Schain (SKALE chain) parts
  • Use Mainnet and Schain objects separately

First approach is more convenient in general because single IMA object have simplified API for some functionality that
requires both Mainnet and Schain interactions, but in this case you will need two web3 objects to be available at the same time.

Second approach is more flexible but requires more developer work in some cases.

Working with a single IMA object

Import and init single IMA-JS object:

import { IMA } from '@skalenetwork/ima-js';

import mainnetAbi from './mainnetAbi.json'; // your local sources
import schainAbi from './schainAbi.json'; // your local sources

const MAINNET_ENDPOINT = '[YOUR_ETHEREUM_MAINNET_ENDPOINT]';
const SCHAIN_ENDPOINT = '[YOUR_SCHAIN_ENDPOINT]';

const mainnetWeb3 = new Web3(MAINNET_ENDPOINT);
const sChainWeb3 = new Web3(SCHAIN_ENDPOINT);

let ima = new IMA(mainnetWeb3, sChainWeb3, mainnetAbi, sChainAbi);

Accessing Mainnet and Schain parts:

  • Mainnet: ima.mainnet - equals to MainnetChain object
  • sChain: ima.schain - equals to Schain object

Working with 2 separate objects

Import and init Mainnet object:

import { MainnetChain } from '@skalenetwork/ima-js';
import mainnetAbi from './mainnetAbi.json'; // your local sources

const MAINNET_ENDPOINT = '[YOUR_ETHEREUM_MAINNET_ENDPOINT]';
const mainnetWeb3 = new Web3(MAINNET_ENDPOINT);

let mainnet = new MainnetChain(mainnetWeb3, mainnetAbi);

Import and init Schain object:

import { SChain } from '@skalenetwork/ima-js';
import schainAbi from './schainAbi.json'; // your local sources

const SCHAIN_ENDPOINT = '[YOUR_SCHAIN_ENDPOINT]';
const sChainWeb3 = new Web3(SCHAIN_ENDPOINT);

let schain = new SChain(sChainWeb3, schainAbi);

ETH and token transfers

Detailed documentation about ETH and token transfers using IMA-JS can be found here:

  • [ETH transfers] missing link
  • [ERC20 token transfers] missing link
  • [ERC721 token transfers] missing link
  • [ERC1155 token transfers] missing link

Signing transactions

There are 2 ways to sign a transaction in the current version of IMA-JS:

  • Signing directly with private key
  • Signing with an external provider (currently only Metamask is supported)

Signing with private key

To sing and send a transaction using local private key you should specify privateKey and address in the txOpts object:

// init ima object

const txOpts = {
    address: "[ADDRESS]",
    privateKey: "[PRIVATE_KEY]"
}

this.state.sChain.withdrawETH(
    receiverAddress,
    amountWei,
    txOpts
);

Signing with Metamask

Just drop privateKey from the txOpts object to trigger external signing, keep address field:

// init ima object

const txOpts = {
    address: "[ADDRESS]"
}

this.state.sChain.withdrawETH(
    receiverAddress,
    amountWei,
    txOpts
);

Basic Scaffold

General

Navigation Bar

Manual JSON RPC Calls

JSON RPC Calls

When some platforms or frameworks don't have any quality web3 library or SDK, there's always the possibility to make the blockchain calls directly to the JSON-RPC methods supported by the chain.

Some of the JSON-RPC methods supported by SKALE chains are:

  • eth_getBalance
  • eth_blockNumber
  • eth_getTransactionCount
  • eth_sendTransaction
  • eth_call

For more information about it check the SKALE Documentation

skale.dart

Already have a issue for the Web3.Dart with the implementation steps. Do I make this one more for the SKALE POW example in Dart? @TheGreatAxios

skale.js

SKALE.js

SKALE.js is a community run project designed to offer abstraction over the core SKALE network smart contracts.

Some of the available packages are:

For more information check the project GitHub repository.

Web3.Swift

Web3.Swift

This library implements the web3.js library in Swift. It enables interaction with EVM compatible blockchains.

Some of the features are:

  • Interaction with remote node via JSON RPC
  • Local keystore management
  • Smart-contract ABI parsing
  • Smart contracts interactions
  • Support of common EIPs and ERCs

For more information check the Web3.Swift documentation page.

Using Ledger

Ledger

It is a hardware wallet designed for secure cryptocurrency storage. It is a physical device that securely stores the user's private keys, which are essential for accessing and managing their cryptocurrencies. Ledger wallets are known for their emphasis on security, providing an offline storage solution to protect digital assets from online threats such as hacking and malware.

For more information check the following link https://developers.ledger.com/docs/transport/overview/

Implementation Example

NPM Packages

If you want to use a Ledger Nano S/X/S Plus with the USB protocol

npm install @ledgerhq/hw-transport-webusb

If you want to use a Ledger Nano S/X/S Plus with the HID protocol

npm install @ledgerhq/hw-transport-webhid

Implementation Code

import TransportWebUSB from '@ledgerhq/hw-transport-webusb'
import Eth from '@ledgerhq/hw-app-eth'

const transport = await TransportWebUSB.create();
const evm_ledger = new Eth(transport);

const path = "m/44'/60'/0'/0/0";

const result = await evm_ledger.getAddress(path, false, true);
console.log('Ledger Wallet Address:', result.address);

Razor Network

Razor Network

Razor Network is a decentralized oracle network offering price-feed data to applications. This can be utilized in various actions throughout DeFi and other more general Web3 use cases. Razor is available on the Calypso, Nebula, Titan Mainnet, and Testnets.

Implementation Example

To consume the Razor Network price feeds, your contract should reference ITransparentForwarder. This is an interface that defines the external functions implemented by Data Feeds

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface ITransparentForwarder {
    /**
     * @dev using the hash of collection name, clients can query the result of that collection
     * @param _name bytes32 hash of the collection name
     * @return result of the collection and its power
     */
    function getResult(bytes32 _name) external payable returns (uint256, int8);
}

contract DataFeed {
    ITransparentForwarder public transparentForwarder;
    uint256 public latestResult;
    int8 public latestPower;

    constructor() {
        transparentForwarder = ITransparentForwarder(
            /* Transparent Forwarder contract address deployed on respective chains */
        );
    }

    /// @notice fetch collection result by name
    /// @param name bytes32 hash of the collection name
    /// @return result of the collection and its power
    /// @return power
    function getResult(bytes32 name) public payable returns (uint256, int8) {
        (uint256 result, int8 power) = transparentForwarder.getResult{
            value: msg.value
        }(name);
        latestResult = result;
        latestPower = power;
        return (result, power);
    }
}

For more information go to the Razor data feed documentation.

feat(tool): Dune

Dune

Dune serves as an incredibly flexible web3 analytics tool and source of truth, aligning with the SKALE Network approach to unveil the formerly hidden web3 landscape by showcasing previously web2-exclusive data on the Dune platform.

The SKALE Dashboards on Dune aims to cover all details about delegations, delegators, and validators. In addition to this, it goes beyond the basics to provide analytics about other network components. These include details about each node in the network, every SKALE chain created, and all distributed key generation (DKG) rotations performed.

The data on the SKALE Dashboards in Dune are driven from SKALE smart contracts deployed on Ethereum. This set of contracts ensure the security and management of the network since all actions regarding chains creation, delegations, node creation/rotation and others are performed through these smart contracts.

SKALE Dune Dashboards

To run and maintain such a complex ecosystem like SKALE Network it requires several parties. For this reason the SKALE data on Dune is spread across the following dashboards.

Main

Encompasses general statistics of the network, including metrics like total staked and the number of existing validators.
It features tables and dashboards that provide insights into the core components of the ecosystem.

Screenshot 2023-12-28 at 12 19 12 Screenshot 2023-12-28 at 12 19 02

Validators

Offers detailed insights into each validator's identity and staking conditions. It also includes several tables that provide in-depth information on delegations, the rewards associated with those delegations, and the nodes linked to each validator.

Screenshot 2023-12-28 at 12 28 31 Screenshot 2023-12-28 at 12 32 05

Delegators

For each delegator wallet address, this page provides a wealth of information, including the number of delegations made and a record of all delegations made, along with rewards collected from each validator they have delegated to.

Screenshot 2023-12-28 at 12 30 31 Screenshot 2023-12-28 at 12 31 43

Multi-chain

The SKALE network is a multi-chain ecosystem and this dashboard reveals some numbers of the all existing chains. The data in it shows tables like the number of SKALE chains currently operational on the network, the monthly evolution of unique active wallets and transactions in the network, and also presents an average cost in USD of the gas fees if other EVMs chains would have been exposed to the same transactions load as the SKALE chains.

Screenshot 2023-12-28 at 12 45 02 Screenshot 2023-12-28 at 12 45 26

Node

For each node ID, the Node page offers insights into the node's details, the validator it is linked to, and the SKALE chains it is currently operating on. Additionally, it provides information on the bounties generated by that node, shedding light on the economic activity within the ecosystem.

Screenshot 2023-12-28 at 12 46 46 Screenshot 2023-12-28 at 12 47 03

SKALE Chain

This section is dedicated to each specific SKALE chain. By selecting a particular chain, the dashboard returns essential details such as its lifetime, creation time, nodes forming the chain and also shows how much would have been spend in USD on gas fees if the gas spent on the SKALE Chain was done on other EVM chains.

Screenshot 2023-12-28 at 12 51 49 Screenshot 2023-12-28 at 12 52 05

Using Trezor

Trezor

Trezor wallet is a hardware wallet designed for secure storage of cryptocurrencies. Similar to other hardware wallets, Trezor provides a physical device that stores the user's private keys offline, reducing the risk of exposure to online threats like hacking and malware.

For more information check the following link https://trezor.io/learn

Install NPM Packages

npm install @trezor/connect

Implementation Example

import TrezorApi from "trezor-connect";

const supportedNetworkURLs = {
  1351057110: "https://staging-v3.skalenodes.com/v1/staging-fast-active-bellatrix"
};

const defaultNetwork = 1;

const Trezor = new TrezorConnector({
  api: TrezorApi,
  supportedNetworkURLs,
  defaultNetwork,
  manifestEmail: "[email protected]",
  manifestAppUrl: "https://test.io/"
});

Kethereum for Kotlin

Kethereum

Kethereum is a Kotlin library created for Ethereum. It opts for a non-monolithic structure, empowering users to selectively integrate modules and thereby maintain a lean library footprint.

KEthereum gives the possibility to pick and choose the modules the developer need and keep the footprint of the library small this way. Some of the modules are:

  • eip155: TX signing with Simple replay attack protection
  • blockscout: BlockScout BlockExplorer helper functions
  • ERC20: Contract wrapper for the ERC20 Token standard
  • wallet: functions for keys from and to JSON wallet files

For more information check the following Kethereum Github repository https://github.com/komputing/KEthereum

Implementation Example

web3Dart

Web3Dart

Library written in dart that enables interaction with EVM compatible blockchains.

Some of the features of the library are:

  • Send signed transactions
  • Generate new wallets
  • Call functions on smart contracts and listen for contract events
  • Code generation based on smart contract ABI for easier interaction

For more informatio checkout the Web3Dart documentation page.

Implementation Example

Install web3dart package

dart pub add web3dart

Contract Call

// ignore_for_file: public_member_api_docs
import 'dart:io';

import 'package:http/http.dart';
import 'package:web3dart/web3dart.dart';
import 'package:path/path.dart' show join, dirname;
import 'package:web_socket_channel/io.dart';

//Private Key
const String privateKey ='place your key';

// SKALE Chaos Chain RPC
// For other SKALE Testnet chains check https://testnet.portal.skale.space/chains
const String rpcUrl = 'https://staging-v3.skalenodes.com/v1/staging-fast-active-bellatrix';
// selected SKALE Chain ID
const int chainId = 1351057110;

// ABI of ERC_721 example contract
final File abiFile = File(join(dirname(Platform.script.path), 'nft_test_abi.json'));


Future<void> main() async {
  // start a client we can use to send transactions
  final client = Web3Client(rpcUrl, Client());

  final EthereumAddress mint_to_address = EthereumAddress.fromHex('Address to receive Mint');
  // Contract adddress deployed on SKALE Chaos Hub
  final EthereumAddress contract_address = EthereumAddress.fromHex('0xcAC71B8faB274429f79F76213fd3BC190041CAA4');
  
  //Credentials to sign tx
  final credentials = EthPrivateKey.fromHex(privateKey);

  //ABI file as string
  final abiCode = await abiFile.readAsString();
  
  final contract = DeployedContract(ContractAbi.fromJson(abiCode, 'NFT_721'), contract_address);
  //Selected contract function to call
  final mintFunction = contract.function('_mintTest');

  // Mint function call
  //Note: The chainId needs to be passes otherwise it will throw the error: -32004 Invalid transaction signature.
  final tx = await client.sendTransaction(
    credentials,
    Transaction.callContract(
      contract: contract,
      function: mintFunction,
      parameters: [mint_to_address],
    ),
    chainId: chainId
  );

  // Transaction Receipt
  final receipt = await client.addedBlocks().asyncMap((_) => client.getTransactionReceipt(tx)).firstWhere((receipt) => receipt != null);
  print(receipt);

  await client.dispose();
}

Run Dart Script

dart web/main.dart 

Emergence

Emergence SDK

Emergence serves as a Web3 SDK tailored for game developers, seamlessly integrating with Unreal Engine and Unity through.
It provides features such as:

  • wallet authentication
  • smart contracts calls
  • NFT inventory services

For more information checkout the Emergence SDK documentation.

Web3.Unity

Web3.Unity

Web3.unity is an open-source gaming SDK written in C# on top of the Nethereum library. The library currently supports games built for web browsers (WebGL), iOS/Android mobile, and desktop.

The SDK is compatible with most EVM-based chains such as SKALE, Ethereum, etc.

Because it's built on top of Nethereum it drives most of capabilities of the library, such as:

  • Sign & verify digital signatures
  • Multiple ERC-20, ERC-721, ERC-1155 token interactions
  • Metamask connection

For more information check the Chainsafe documentation.

Web3J for Java

Web3j

Web3j is a modular, reactive, type safe Java and Android library for working with Smart Contracts and integrating with clients (nodes) on the Ethereum network.

Some of the features are:

  • Complete implementation of Ethereum's JSON-RPC client API over HTTP and IPC
  • Ethereum wallet support
  • Auto-generation of Java smart contract wrappers to create, deploy, transact with and call smart contracts from native Java code
  • Support for ERC20 and ERC721 token standards

For more information check the web3j documentation.

Implementation Example

Install Web3j CLI

curl -L get.web3j.io | sh && source ~/.web3j/source.sh

Create a project

web3j new

Generate a Wallet

web3j wallet create

ERC721 Mint Example Java script

package org.web3j;

import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.WalletUtils;
import org.web3j.generated.contracts.NFT_721;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.http.HttpService;
import org.web3j.tx.gas.StaticGasProvider;
import java.math.BigInteger;


public class Web3App {

   //Can use this as the Node_URL
   //public static String SKALE_Chaos_rpc = "https://staging-v3.skalenodes.com/v1/staging-fast-active-bellatrix";

   private static final String nodeUrl = System.getenv().getOrDefault("WEB3J_NODE_URL", "<node_url>");
   private static final String walletPassword = System.getenv().getOrDefault("WEB3J_WALLET_PASSWORD", "<wallet_password>");
   private static final String walletPath = System.getenv().getOrDefault("WEB3J_WALLET_PATH", "<wallet_path>");

   public static final BigInteger gasLimit = BigInteger.valueOf(5_000_000);
   public static final BigInteger gasPrice = BigInteger.valueOf(1_000_00);

   public static String address = "some address";

   public static void main(String[] args) throws Exception {

      Credentials credentials = WalletUtils.loadCredentials(walletPassword, walletPath);
      Web3j web3j = Web3j.build(new HttpService(nodeUrl));

      NFT_721 nft = NFT_721.deploy(web3j, credentials, new StaticGasProvider(gasPrice, gasLimit)).send();
      System.out.println("Contract address: " + nft.getContractAddress());

      TransactionReceipt mint_receipt = nft._mintTest(address).send();
      System.out.println("Tx has "+ mint_receipt.getTransactionHash());
     }
}

To run the Java script call the following command
Pick the SKALE Chain RPC that suits you

web3j run https://staging-v3.skalenodes.com/v1/staging-fast-active-bellatrix <wallet_path> <wallet_password>

Create Learn Beginner Section

Tasks

Eidolon

Eidolon

It is a Unity SDK built on to of Nethereum library and provides a easy developer onboarding to interact with EVM blockchains. This SDK was created to accommodate all SKALE developer needs, e.g sFUEL distribution.

Hereโ€™s an overview of what Eidolon SDK handles:

  • Blockchain Interaction: Eidolon.Unity allows you to interact with the Ethereum blockchain effortlessly. With just a few lines of code, you can perform various operations, such as sending transactions, reading contract data, and managing accounts.

  • Wallet Integration: Connect to popular browser wallets like MetaMask, TrustWallet, and Enkrypt. Eidolon.Unity seamlessly integrates with these wallets, providing your users with a familiar and secure way to manage their assets.

  • ERC Standards Support: Eidolon.Unity supports Ethereumโ€™s ERC-20, ERC-721, and ERC-1155 token standards, enabling you to work with a wide range of blockchain assets and NFTs.

  • WebGL Compatibility: Designed to work seamlessly with Unity WebGL, Eidolon.Unity ensures that your games can be easily deployed to the web, allowing players to experience your blockchain-powered creations directly in their browsers.

Quick Start

To integrate and start using the SDK right away go to the Eidolon documentation Quick Start section

Usage Example

The Eidolon SDK aims to make the blockchain development side of things as simple and quick as possible. This means the developer should spend most of his time and resources developing the best game or product possible and not
trying to learn all the different complexity layers of a blockchain.

The simplicity explained above can be seen, for example, in the contracts deployment section of the Eidolon SDK.
The image bellow exemplifies how quickly a ERC-20 token can be deployed.

deploy_token

For more information check the Eidolon documentation.

feat(tool): Create2Factory

Create2 Factory

The CREATE2 opcode enables the prediction of the deployment address for a contract without actually deploying it. This opcode's primary purpose is to ensure that the resulting address remains unaffected by future events. Regardless of changes in the blockchain, the contract can always be deployed at the precomputed address.

In order to address this way of contract creation SKALE built a create2 factory. It was built a simple contract that can deploy other contracts with a deterministic address on any SKALE chain using CREATE2 and check the DEPLOYER permission of the sender. The CREATE2 call will deploy a contract (like CREATE opcode) but instead of the address being keccak256(rlp([deployer_address, nonce])) it instead uses the hash of the contract's bytecode and a salt. This means that a given deployer address will deploy the same code to the same address no matter when or where they issue the deployment. The deployer is deployed with a one-time-use-account, so no matter what chain the deployer is on, its address will always be the same. This means the only variables in determining the address of your contract are its bytecode hash and the provided salt.

Deployment

In order to user SKALE Create2 Factory check the SKALE deterministic deployment proxy

Nethereum

Nethereum

I is a .NET integration library for Ethereum, enabling developers to interact with EVM chains and smart contracts using the C# programming language. It provides a set of APIs and utilities to facilitate communication with the Ethereum blockchain.

Features

The main features of this web3 library are:

  • JSON RPC / IPC Ethereum core methods
  • Simplified smart contract interaction for deployment, function calling, transaction and event filtering and decoding of topics
  • Unity 3d integration
  • ABI to .Net type encoding and decoding, including attribute-based for complex object deserialisation
  • Libraries for standard contracts Token, ENS and Uport
  • Key storage using Web3 storage standard, compatible with Geth and Parity.

For more information check the Nethereum documentation

Unity Implementation Example

The Nethereum.Unity library is a Nethereum specific Unity library and api which provides support for UnityWebRequest to interact with Ethereum using RPC over Http.

All Nethreum realeases can be found in:
https://github.com/Nethereum/Nethereum/releases

The following example showcases how to get the current balance of a wallet.

using System.Collections;
using UnityEngine;
using Nethereum.Web3;
using Nethereum.RPC.Eth.DTOs;
using Nethereum.Unity.Rpc;

  public IEnumerator GetWalletBalance()
    {
        string chain_rpc = "";
        string wallet_address = "";

        var balanceRequest = new EthGetBalanceUnityRequest(chain_rpc);
        yield return balanceRequest.SendRequest(wallet_address, BlockParameter.CreateLatest());
        var balance = Web3.Convert.FromWei(balanceRequest.Result.Value);

        Debug.Log("Wallet Balance " + balance);
    }

Nethereum Playground

In order to quickly experiment Nethereum library and it's capabilities, it was created a platform where developers can learn and run predefined examples that show how to make some requests. It can be useful to help developers deciding if Nethereum is a good fit for their project.
To try it out check https://playground.nethereum.com/.

For more examples and information go to the Nethereum specific GitHub repository

Using Stardust

Stardust

Stardust solution allows developers to quickly create custodial wallets, manage their NFTs, and monetize their collections on a robust marketplace.
With this solution it's possible to create a frictionless user onboarding experience, by removing the need for them to manage their own private keys.

For more information check the Stardust documentation

Implementation Example

The following example provides a number of examples on how to use Stardust WaaS. The default chain used is SKALE Chaos Testnet. For the full code repo go here

const { StardustCustodialSDK, StardustApp, StardustWallet } = require("@stardust-gg/stardust-custodial-sdk");
const { STARDUST_API_KEY, RPC_URL } = require("../../config");
const createStardustWallet = require("./createWallet");
const { providers } = require("ethers");
const getStardustWallet = require("./getWallet");

function stardust() {
	const provider = new providers.JsonRpcProvider(RPC_URL);
	const sdk = new StardustCustodialSDK(STARDUST_API_KEY);

	async function getWallet(walletId) {
		return await getStardustWallet(sdk, walletId);
	}

	return {
		createWallet: async() => createStardustWallet(sdk),
		getWallet,
		getSigner: async(walletId) => {
			const wallet = await getWallet(walletId);
			return wallet.signers.ethers.connect(provider);
		}
	}
}
module.exports = stardust();

Remove Code Limits

  • Remove COde Size Limits
  • Add note in EVM Differences (under BUiLD) that says max contract code size limit is default to 64kb currently, but may become configurable in the future to smaller or larger sizes
  • Note ->> Ethereum is 24kb (after Spurious Snap Dragon)

Create Learn Advanced Section

SKALE Tasks

Topics

Web3.Js

Web3.js

Set of Javascript libraries enabling interaction with a local or remote Ethereum node through HTTP, IPC, or WebSocket protocols.

Some of the features are:

  • Complete implementation of Ethereum's JSON-RPC client API over HTTP and IPC
  • Create accounts, process and sign transactions.
  • Get block and state information from Ethereum nodes.

For more information check the Web3.js documentation.

Implementation Example

Package install

npm install web3

Function Call Contract

import Web3 from "web3";
import {contract_abi,contract_adress} from "./contract";

var web3 = new Web3("https://staging-v3.skalenodes.com/v1/staging-fast-active-bellatrix");
const pk = "wallet pk";
const accountAddress = "wallet address";

const contract = new web3.eth.Contract(contract_abi, contract_adress);

const functionData = contract.methods._mintTest(accountAddress).encodeABI();

async function callMintFunction() {
  web3.eth.accounts.signTransaction( 
    {
      from: accountAddress,
      to: contract_adress,
      gas: 500000,
      gasPrice: 100000,
      data: functionData,
    }, 
    pk)
    .then((signedTransaction) => {
      return web3.eth.sendSignedTransaction(signedTransaction.rawTransaction || "");
    })
    .then((receipt) => {
      console.log("Transaction receipt:", receipt);
    })
    .catch((error) => {
      console.error("Error sending transaction:", error);
    });
}
callMintFunction();

Metaport

Metaport

Metaport is a Javascript/Typescript customizable IMA bridge widget embeddable into any web application. It enables SKALE network developers an easy way to guide users through executing IMA bridge transactions throughout the SKALE Network and with Ethereum.

Some of the possible usages are:

  • Guide users through transferring ERC-20 tokens between your dApp and a dApp on another SKALE chain.
  • Guide users through multi-step wraps and transfers between Ethereum, the Europa liquidity Hub, and the Calypso NFT Hub.
  • Allow users to bridge tokens from your game on the Nebula Gaming Hub to the Ruby Exchange DEX on Europa Hub.
  • Help users quickly unwrap stuck tokens on various chains.
Screenshot 2023-12-22 at 16 35 05

To test out a playground environment, check out https://testnet.portal.skale.space/

Implementation Example

  1. Package Install
npm install --save @skalenetwork/[email protected]
  1. Implementation

You can import Metaport into any modern web application (Vue/React/Angular/etc).
Add empty div with metaport id in the root page of your application:

<div id='metaport'></div>

Import Metaport library and init the object:

import { Metaport } from '@skalenetwork/metaport';

const metaport = new Metaport(METAPORT_OPTIONS);
  1. Configure Metaport Options

====

Implementation in SSR (Server-Side Rendering)

Metaport has browser-only build. To use it in an application that uses server-side rendering
you need to adapt it using trick described here.

Here is an example of Metaport import & usage in Next.js app with SSR:

// in react component

const [metaport, setMetaport] = React.useState();

async function loadMetaport() {
    const Metaport = (await import('@skalenetwork/metaport')).Metaport;
    setMetaport(new Metaport({
      openOnLoad: true,
      skaleNetwork: 'staging',
      chains: ['mainnet', 'chainName1'],
      tokens: {'mainnet': {'eth': {}}}
    }));
}

useEffect(() => {
    loadMetaport();
}, []);

useEffect(() => {
    if (metaport) {
      console.log('metaport widget initialized');
    }
}, [metaport]);

Example Metaport Options

const metaport = new Metaport({
    openOnLoad: true, // Open Metaport on load (optional, default = false)
    openButton: false, // Show open/close action button (optional, default = true)
    autoLookup: false, // Automatic token lookup for M2S tokens (default = true)
    mainnetEndpoint: MAINNET_ENDPOINT, // Ethereum Mainnet endpoint, required only for M2S or S2M transfers (optional, default = null)
    skaleNetwork: 'staging3', // SKALE network that will be used - mainnet, staging, or staging3 (optional, default = mainnet)
    debug: false, // Enable debug mode (optional, default = false)
    chains: [ // List of SKALE Chains that will be available in the Metaport UI (default = [])
        'chainName1',
        'chainName2',
        'chainName3'
    ],
    chainsMetadata: { // Chain name aliases that will be displayed in the UI (optional, default = {})
        'chainName1': {
            alias: 'Europa SKALE Chain', // optional
            minSfuelWei: '27000000000000', // optional
            faucetUrl: '[FAUCET_URL]' // optional
        },
        ...
    },
    tokens: { // List of tokens that will be available in the Metaport UI (default = {})
        'chainName2': { // chain name where token origin deployed (mainnet or SKALE Chain name)
            'erc20': { // token type (erc20 and eth are supported)
                '_[TOKEN_SYMBOL]_[TOKEN_ORIGIN_ADDRESS]': { // token keyname (composed from token symbol and origin token address)
                    'name': 'TOKEN_NAME1', // token display name
                    'address': '0x0357', // token origin address
                    'symbol': '[TOKEN_SYMBOL]' // token symbol
                    'cloneSymbol': 'CTST' // optional, symbol of the clone token
                    'iconUrl': 'https://example.com/my_token_icon.png', // optional
                    'decimals': '6' // optional (default = '18')
                }               
            }
        }
    },
    theme: { // custom widget theme (default = dark SKALE theme)
        primary: '#00d4ff', // primary accent color for action buttons
        background: '#0a2540', // background color
        mode: 'dark' // theme type - dark or light
    }
});

Other Examples

See https://github.com/Dirt-Road-Development/skale-metaport-demo-cra

Learn PR | Suggestions

Learn

Beginner

SKALE Chain Fuel -> SKALE Chain Gas (Reason: Donโ€™t think most people will associate fuel to gas)

Tasks

feat(tool): Multicall3

Multicall

It has two primary use-cases:

  • Enabling the ability to read off of multiple contracts with a single request
  • The ability to execute multiple state-changing transactions in a single request

Deployment

The multicall contract was deployed on SKALE Network on several chains and can be found under the address:
0xcA11bde05977b3631167028862bE2a173976CA112

The deployment is currently available on the following SKALE Chains.

Chains with Multicall

(Add Table)

Chain Mainnet Testnet
Europa โœ“ โœ“
Calypso โœ“ โœ“
Chaos Testnet ย  โœ“
Nebula โœ“ โœ“
Pscyhe โœ“ โœ“
Titan โœ“ โœ“

Implementation Example

	const [ signer ] = await hre.ethers.getSigners();

	    const tokens = [
	    	"0x4f2040FEaAD8b19E254006153E7BBB0674F4DaE3", // token0
	    	"0x7464f84F2c6686b6365a373E8FB7c15741e07275",
	    	"0x677b7FfE9435735F2b1CEE325527e9268CD011F2",
	    	"0xa0aC0f7A8726351beF090B6966aA77E07cF0Fb15",
	    ];

	    const multicallABI = [{"type":"function","stateMutability":"payable","outputs":[{"type":"uint256","name":"blockNumber","internalType":"uint256"},{"type":"bytes[]","name":"returnData","internalType":"bytes[]"}],"name":"aggregate","inputs":[{"type":"tuple[]","name":"calls","internalType":"struct Multicall3.Call[]","components":[{"type":"address","name":"target","internalType":"address"},{"type":"bytes","name":"callData","internalType":"bytes"}]}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"tuple[]","name":"returnData","internalType":"struct Multicall3.Result[]","components":[{"type":"bool","name":"success","internalType":"bool"},{"type":"bytes","name":"returnData","internalType":"bytes"}]}],"name":"aggregate3","inputs":[{"type":"tuple[]","name":"calls","internalType":"struct Multicall3.Call3[]","components":[{"type":"address","name":"target","internalType":"address"},{"type":"bool","name":"allowFailure","internalType":"bool"},{"type":"bytes","name":"callData","internalType":"bytes"}]}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"tuple[]","name":"returnData","internalType":"struct Multicall3.Result[]","components":[{"type":"bool","name":"success","internalType":"bool"},{"type":"bytes","name":"returnData","internalType":"bytes"}]}],"name":"aggregate3Value","inputs":[{"type":"tuple[]","name":"calls","internalType":"struct Multicall3.Call3Value[]","components":[{"type":"address","name":"target","internalType":"address"},{"type":"bool","name":"allowFailure","internalType":"bool"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"bytes","name":"callData","internalType":"bytes"}]}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"uint256","name":"blockNumber","internalType":"uint256"},{"type":"bytes32","name":"blockHash","internalType":"bytes32"},{"type":"tuple[]","name":"returnData","internalType":"struct Multicall3.Result[]","components":[{"type":"bool","name":"success","internalType":"bool"},{"type":"bytes","name":"returnData","internalType":"bytes"}]}],"name":"blockAndAggregate","inputs":[{"type":"tuple[]","name":"calls","internalType":"struct Multicall3.Call[]","components":[{"type":"address","name":"target","internalType":"address"},{"type":"bytes","name":"callData","internalType":"bytes"}]}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"basefee","internalType":"uint256"}],"name":"getBasefee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"blockHash","internalType":"bytes32"}],"name":"getBlockHash","inputs":[{"type":"uint256","name":"blockNumber","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"blockNumber","internalType":"uint256"}],"name":"getBlockNumber","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"chainid","internalType":"uint256"}],"name":"getChainId","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"coinbase","internalType":"address"}],"name":"getCurrentBlockCoinbase","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"difficulty","internalType":"uint256"}],"name":"getCurrentBlockDifficulty","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"gaslimit","internalType":"uint256"}],"name":"getCurrentBlockGasLimit","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"timestamp","internalType":"uint256"}],"name":"getCurrentBlockTimestamp","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"balance","internalType":"uint256"}],"name":"getEthBalance","inputs":[{"type":"address","name":"addr","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"blockHash","internalType":"bytes32"}],"name":"getLastBlockHash","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[{"type":"tuple[]","name":"returnData","internalType":"struct Multicall3.Result[]","components":[{"type":"bool","name":"success","internalType":"bool"},{"type":"bytes","name":"returnData","internalType":"bytes"}]}],"name":"tryAggregate","inputs":[{"type":"bool","name":"requireSuccess","internalType":"bool"},{"type":"tuple[]","name":"calls","internalType":"struct Multicall3.Call[]","components":[{"type":"address","name":"target","internalType":"address"},{"type":"bytes","name":"callData","internalType":"bytes"}]}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"uint256","name":"blockNumber","internalType":"uint256"},{"type":"bytes32","name":"blockHash","internalType":"bytes32"},{"type":"tuple[]","name":"returnData","internalType":"struct Multicall3.Result[]","components":[{"type":"bool","name":"success","internalType":"bool"},{"type":"bytes","name":"returnData","internalType":"bytes"}]}],"name":"tryBlockAndAggregate","inputs":[{"type":"bool","name":"requireSuccess","internalType":"bool"},{"type":"tuple[]","name":"calls","internalType":"struct Multicall3.Call[]","components":[{"type":"address","name":"target","internalType":"address"},{"type":"bytes","name":"callData","internalType":"bytes"}]}]}];
	    const multicallAddress = "0xcA11bde05977b3631167028862bE2a173976CA11";
	    const multicall = new hre.ethers.Contract(multicallAddress, multicallABI, signer);

	    const contracts = tokens.map((addr: string) => new hre.ethers.Contract(addr, abi, signer));

	    const balances = await Promise.all(contracts.map((contract) => {
	    	return contract.balanceOf(signer.address);
	    }));

	    const allowances = await Promise.all(contracts.map((contract) => {
	    	return contract.allowance(signer.address, multicallAddress);
	    }));

	    for (let i = 0; i < contracts.length; i++) {
	    	if (allowances[i].toString() !== balances[i].toString()) {
	    		await contracts[i].approve(multicallAddress, balances[i]);
	    	}
	    }

	    /** Creating Random Wallets for Distribution **/
	    const wallets = [
			new hre.ethers.Wallet.createRandom(),
			new hre.ethers.Wallet.createRandom(),
			new hre.ethers.Wallet.createRandom(),
			new hre.ethers.Wallet.createRandom(),
			new hre.ethers.Wallet.createRandom(),
	    ];

	    let distributionCalls = [];

	    contracts.forEach((contract, index) => {
	    	wallets.forEach((wallet, index2) => {
		    	distributionCalls.push([
		    		contract.address,
		    		false,
		    		contract.interface.encodeFunctionData("transferFrom", [signer.address, wallet.address, 1])
		    	]);
		    });
	    });

	    const results = await multicall.aggregate3(distributionCalls);

Check the full SKALE multicall example here.

Using Magic

Magic

Magic is a developer SDK that integrates with your application to enable passwordless Web3 onboarding and authentication using magic links (similar to Slack and Medium).

Magic offers two solutions in their SDKs, targeting different platforms:

  • Dedicated Wallet, a customizable white-labeled wallet solution
  • Universal Wallet, which provides a plug-and-play experience

For more information check the Magic Documentation.

Create Learn Introduction Section

Tasks

Using Web3Auth

WITH BUG: Can't connect to SKALE Chains. Need to check

Web3Auth

Pluggable wallet infrastructure for Web3 wallets and applications. It streamlines the onboarding of both mainstream and crypto native users in under a minute by providing experiences that they're most comfortable with.

Web3Auth's MPC-based wallet management infrastructure provides secure, non-custodial wallet management, where users maintain control of their cryptographic key pair. The login service only accesses a single share, preventing the provider from retrieving the user's wallet independently.

Implementation Example

NPM Packages

npm install --save @web3auth/modal

Client ID
Get your client ID under https://dashboard.web3auth.io/

Implementation code

import { Web3Auth } from "@web3auth/modal";
import Web3 from "web3";

const web3auth = new Web3Auth({
  clientId: "BPi5PB_UiIZ-cPz1GtV5i1I2iOSOHuimiXBI0e-Oe_u6X3oVAbCiAZOTEBtTXw4tsluTITPqA8zMsfxIKMjiqNQ", // get it from Web3Auth Dashboard
  web3AuthNetwork: "sapphire_mainnet",
  chainConfig: {
    chainNamespace: "eip155",
    chainId: "0x50877ed6",
    rpcTarget: "https://staging-v3.skalenodes.com/v1/staging-fast-active-bellatrix",
    // Avoid using public rpcTarget in production.
    // Use services like Infura, Quicknode etc
    displayName: "SKALE Chaos Testnet",
    blockExplorer: "https://staging-fast-active-bellatrix.explorer.staging-v3.skalenodes.com/",
    ticker: "sFUEL",
    tickerName: "sFUEL",
  },
});
await web3auth.initModal();

const web3authProvider = await web3auth.connect();

const web3 = new Web3(web3authProvider);

Integration Errors

In case of encountering polyfill related issues check the Web3auth troubleshooting page about this topic

Mirage

Mirage

The Mirage platform serves as a gateway to a comprehensive suite of proven solutions tailored for the development, enhancement, scalability, support, and publication of Web3 games. Primarily, the platform offers SDKs designed for seamless integration, providing solutions for both Unity and Unreal engine.

The SDKs for both platforms are EVM compatible and have the following features:

  • Interaction with Web3 wallets (either WalletConnect or MetaMask) for all supported platforms
  • Interaction with EVM-compatible blockchains
  • Interaction with smart contracts

For more information visit the Mirage documentation

Implementation Example

Unity

Unreal

Full Sync Node

The Full-Sync Node is an available software implementation of a read-only SKALE Node that can help decrease the load on the core nodes of your chain. Applications are commonly read-heavy compared to writes, meaning they pull data from the chain more often than push them. For applications that contain many reads, a full-sync node can help increase chain stability and speed by reducing the number of actions the core nodes on the chain must do, leaving them with a more extraordinary ability to handle transactions.

General Steps

  • Provision a machine
  • Notify core team of IP/IPs range (x.x.x.x:x.x.x.x) and SKALE Chain for full-sync.
  • Complete Full Sync setup

Node Machine Requirements

  • A Linux x86_64 machine
  • Ubuntu 18.04
  • 8 physical cores
  • 32GB RAM
  • 100GB root storage
  • 2TB attached storage

Node Network Requirements

  • Ports 80, 443, 3009, and 10000โ€“18192, and ICMP IPv4 shouldn't be closed by external firewall

Node Software Prerequisites

  • 16GB Swap
  • docker
  • docker-compose โ†’ 1.27.4
  • iptables-persistent, btrfs-progs, lsof, lvm2, psmisc, and apt packages

From Fresh Machine

sudo apt-get update

# Install Docker and Docker-compose
sudo apt-get install docker.io
sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# Install other dependencies
sudo apt install iptables-persistent btrfs-progs lsof lvm2 psmisc

# Setup Swapfile
sudo fallocate -l 16G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
sudo cp /etc/fstab /etc/fstab.bak
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

[NOTE]
Before proceeding, notify the core team of the IP address of your full-sync node. It's suggested to use an elastic IP for the whitelisted IP address.

Installation

  1. Download sync-node-cli tool
VERSION_NUM=2.2.0-sync-node.6 && sudo -E bash -c "curl -L https://github.com/skalenetwork/node-cli/releases/download/$VERSION_NUM/skale-$VERSION_NUM-`uname -s`-`uname -m`-sync >  /usr/local/bin/skale"
  1. Apply executable permissions to the downloaded binary:
chmod +x /usr/local/bin/skale
  1. Test the installation
skale --help

4 Prepare .env file:

CONTAINER_CONFIGS_STREAM="2.2.0-sync-node.0"
ENDPOINT=[[By Validator], YOUR GETH/INFURA ENDPOINT]
MANAGER_CONTRACTS_ABI_URL="https://raw.githubusercontent.com/skalenetwork/skale-network/master/releases/mainnet/skale-manager/1.9.0/skale-manager-1.9.0-mainnet-abi.json"
IMA_CONTRACTS_ABI_URL="https://raw.githubusercontent.com/skalenetwork/skale-network/master/releases/mainnet/IMA/1.3.0/mainnet/abi.json"
DISK_MOUNTPOINT=[[By Validator], your attached storage /dev/sda or /dev/xvdd (this is an example. You just need to use your 2TB block device)]
DOCKER_LVMPY_STREAM="1.0.2-stable.0"
ENV_TYPE="mainnet"

SCHAIN_NAME=[[By Validator], SCHAIN NAME FOR YOUR SYNC NODE]
  1. Init sync node:
skale sync-node init [ENV_FILE_PATH]
  1. Wait until your sync node will be inited
  2. After the node is successfully inited, wait until skaled will download the snapshot and starts catchup blocks (usually 15โ€“30 minutes)

Setup SSL certs

Node SSL certificates support secure communication with sChain endpoints. By default, each node of a SKALE Chain listens on HTTP and WS ports. If SSL certs exist on the node, then HTTPS and WSS ports are also turned on.

To upload SSL certs to the node run:

skale ssl upload -c $PATH_TO_CERT_FILE -k $PATH_TO_KEY_FILE

To check the status of your certs run:

skale ssl status

Once certs are uploaded, HTTPS/WSS endpoints should become available for your chain.

Full sync node update

Update full sync SKALE node on current machine

skale sync-node update [ENV_FILEPATH]

Options:

  • --yes - update without additional confirmation

Arguments:

  • ENV_FILEPATH - path to env file where parameters are defined

[NOTE]
You can just update a file with environment variables used during skale sync-node init.

Maintenance

Maintenance commands are not available for a sync node.

Web3.Unreal

Web3.Unreal

Web3.unreal is a plugin that brings web3 functionality to desktop games built with Unreal Engine.

Some of the features are:

  • Interaction with remote node via JSON RPC
  • Smart-contract ABI parsing
  • Smart contracts interactions
  • Support of common EIPs and ERCs

For more information check the Web3.Unreal documentation page.

Using Portis

Portis

Portis is a non-custodial Web3 wallet SDK supported by a variety of "evergreen" browsers. The Portis SDK allows you to integrate your dApp with SKALE.

For more information and support, see https://docs.portis.io/#/quick-start

Install the NPM Packages

npm install --save web3 @portis/web3

Example Code

import Portis from '@portis/web3';
import Web3 from 'web3';


// Your setup information
const endpoint = 'https://your.skale.endpoint'; // your SKALE Chain endpoint
const skaleChainId = 123456                     // chainId of your SKALE Chain
const testAPIKey = 'your_api_key';

const mySKALEChain = {
    nodeUrl: endpoint,
    chainId: skaleChainId,
    nodeProtocol: "rpc"
}

// Setting network
const portis = new Portis(testAPIKey, mySKALEChain);
let web3 = new Web3(portis.provider);

Example Sandbox

https://codesandbox.io/s/portis-wallet-integration-skale-dev-docs-41knv

Create Developers Page

Smart Contractย Creation

SKALE Specifics

IMA

sFUEL

Tasks

Web3Auth

Not sure if it makes sense here since their product is mostly the wallet a and we already touch on the wallet section @TheGreatAxios

Using MetaMask

Metamask

Metamask is a Chromium (Chrome, Brave, and Edge) and Firefox browser add-on that provides a non-custodial Ethereum wallet. An end-user's private key is stored in an encrypted Vault data stored in the browser.

It can also connect to hardware based wallets such as Ledger.

https://medium.com/mycrypto/how-to-ensure-youre-running-the-legitimate-version-of-metamask-5fcd8ab32b96[Please be sure you and your end-users are running a legitimate version of Metamask!]

Metamask allows you to integrate your dApp with SKALE by setting the Network RPC endpoint for your users. For more information and support, see https://consensys.net/blog/metamask/connect-users-to-layer-2-networks-with-the-metamask-custom-networks-api

Install the NPM Packages

npm install --save web3

Example Code

import Web3 from 'web3';

let web3 = "";

let switchToSKALE = {
  chainId: "0x50877ed6", //decodes to 1351057110
  chainName: "SKALEChaos Testnet",
  rpcUrls: ["https://staging-v3.skalenodes.com/v1/staging-fast-active-bellatrix"],
  nativeCurrency: {
    name: "SKALE FUEL",
    symbol: "sFUEL",
    decimals: 18
  },
  blockExplorerUrls: [
    "https://staging-fast-active-bellatrix.explorer.staging-v3.skalenodes.com"
  ]
};

web3 = window.web3;

  if (window.ethereum) {
    window.web3 = new Web3(window.ethereum);
    try {
      // Request account access if needed
      await window.ethereum.enable();
      console.log("MetaMask - Web3 Initialized!");

      //Get user wallet accounts
      window.web3.eth.getAccounts((error, accounts) => {
        if (error) {
          console.error(error);
        }
        console.log(accounts);

        //request change to SKALE Network
        window.ethereum
          .request({
            method: "wallet_addEthereumChain",
            params: [switchToSKALE, accounts[0]]
          })
          .catch((error) => console.log(error.message));
      });
    } catch (error) {
      // User denied account access...
    }
  }
  // Legacy dapp browsers...
  else if (window.web3) {
    window.web3 = new Web3(web3.currentProvider);
    console.log("MetaMask - Web3 Initialized!");
  }
  // Non-dapp browsers...
  else {
    console.log(
      "Non-Web3 browser detected. You should consider trying MetaMask!"
    );
  }

Example Sandbox

https://codesandbox.io/s/metamask-wallet-integration-skale-dev-docs-k77zj

Create Developers Quick Start

Landing Page

Quick Start

Using Wallet Connect

Wallet Connect

The Wallet Connect is an open source protocol to link dApps to mobile wallets using deep linking, and allows you to integrate your dApp with SKALE.

For more information and support, see https://docs.walletconnect.com/getting-started

Install NPM Packages

npm install --save web3 @walletconnect/web3-provider

Example Code

import WalletConnectProvider from "@walletconnect/web3-provider";
import Web3 from 'web3';


// Your setup information
const endpoint = 'https://your.skale.endpoint';             // your SKALE Chain endpoint
const ethereumEndpoint = 'https://your.ethereum.endpoint'   // your Ethereum endpoint
const skaleChainId = 123456                                 // chainId of your SKALE Chain

const provider = new WalletConnectProvider({
    rpc: {
      skaleChainId: endpoint,
      4: ethereumEndpoint
    }
  });
  await provider.enable();
  const web3 = new Web3(provider);

Example Sandbox

https://codesandbox.io/s/wallet-connect-wallet-integration-skale-dev-docs-forked-5xq08

Using Bitski

Bitski is a non-custodial OAuth-based Web3 wallet SDK. The Bitski SDK allows you to integrate your dApp with SKALE.

For more information and support, see https://docs.bitski.com/

Install the NPM Packages

npm install --save web3 bitski

Implementation Example

import { Bitski } from 'bitski';
import Web3 from 'web3';


// Your setup information
const endpoint = 'https://your.skale.endpoint'; // your SKALE Chain endpoint
const skaleChainId = 123456                     // chainId of your SKALE Chain
const testAPIKey = 'your_client_id';
const callbackUrl = 'https://your.app/oath-callback.html';

const bitski = new Bitski(
    testAPIKey,
    callbackUrl
);

const network = {
    rpcUrl: endpoint,
    chainId: skaleChainId,
}

// Setting network
const provider = bitski.getProvider({ network });
let web3 = new Web3(provider);

function loginUser() {
  bitski.signIn().then(() => {
    console.log("sign in successful");
  });
}

Using Invisible Signers

Creating a seamless user onboarding experience is essential for the success of any dApp. A well-designed onboarding process can increase user retention and foster a positive first impression, which is crucial for encouraging users to come back for more.

Thanks to the zero gas fees nature of the SKALE chains projects can perform transactions on behalf of the users without compromising the company sustainability by covering huge gas fees costs.

In order to achieve the described above, the application can generate on the background a wallet for each user, distribute the free gas token to it and store it on the backend. Every time a user performs a transaction, the background wallet signs the transaction without the user having idea he just made a on-chain transaction.

Implementation Example

This codebase uses the Typescript language along with the Viem library to showcase a proof of concept on how to utilize background signers within an API or Server based environment.

This example also uses a sticky session per userId meaning that the randomly generated accounts are mapped 1:1 with a userId. This will persist only for the duration of the service liftetime. On application crash or restart new wallets will be created. To resolve these types of issues you can encrypt the private keys and store them in something like Redis to make a more sophisticated service that would also allow for multiple AZ usage.

1- Custodian

import { initializeCustodian } from "./utils";
import { createClient } from "./utils";
import { CUSTODIAN_PRIVATE_KEY, WSS_URL } from "./config";
import { parseEther } from "viem";

const DEFAULT_FILL_UP_VALUE: bigint = parseEther("0.00000002");

class Custodian {
    #nonce = 0;
    #custodian;
    #client;

    constructor() {
        this.#custodian = initializeCustodian(CUSTODIAN_PRIVATE_KEY as `0x${string}`);
        this.#client = createClient(WSS_URL);
    }

    public get custodian() {
        return this.#custodian;
    }

    public get client() {
        return this.#client;
    }

    public async isValidCustodian() {
        const balance = await this.#client.getBalance({
            address: this.#custodian.account.address
        });

        if (balance < parseEther("0.00005")) {
            throw new Error("Custodian Balance must be > 0.00005");
        }

        this.#nonce = await this.#client.getTransactionCount({
            address: this.#custodian.account.address
        });
    }

    public async distribute(to: `0x${string}`) {
        const hash = await this.#custodian.sendTransaction({
            to,
            value: DEFAULT_FILL_UP_VALUE,
            nonce: this.#nonce++
        });
        const tx = await this.#client.waitForTransactionReceipt({
            hash
        });
    }
}
export default new Custodian();

2- Background Signers

import { WalletClient, getAddress, parseAbi } from "viem";
import Custodian from "./custodian";
import { createSigner } from "./utils";
import { skaleChaosTestnet } from "viem/chains";
import { Contract } from "./contract";

class BackgroundSigners {
    #custodian: typeof Custodian;
    #signers: {[key: string]: WalletClient} = {};

    constructor() {
        this.#custodian = Custodian;
    }

    
    public async getUser(userId: string) {
        if (this.#signers[userId] === undefined) {
            const signer = createSigner();
            this.#signers[userId] = signer;
            await this.#custodian.distribute(signer.account.address);
            
        }
        
        return this.#signers[userId].account?.address as `0x${string}`;
    }

    public async remove(userId: string) {
        const account = this.#signers[userId].account;
        if (!account) return;
        this.#signers[userId].sendTransaction({
            to: this.#custodian.custodian.account.address,
            value: BigInt(1),
            type: "legacy",
            account,
            chain: skaleChaosTestnet
        });
    }

    public async backgroundSignerAction(userId: string, args: any[], functionName: "mint" | "burn") {
        const account = this.#signers[userId].account;
        if (!account) throw new Error("Account Not Found");

        await this.#signers[userId].writeContract({
            abi: Contract.abi,
            address: getAddress(Contract.address),
            functionName,
            args,
            account,
            chain: skaleChaosTestnet
        })
    }
}

export default new BackgroundSigners();

3- API

import { Router } from "express";
import BackgroundSigners from "./background_signers";
import { parseEther } from "viem";

const router = Router();

router.post("/mint", async (req, res) => {
    const userId: string = req.body.userId;
    const address = await BackgroundSigners.getUser(userId);
    
    try {
        await BackgroundSigners.backgroundSignerAction(userId, [address, parseEther("1")], "mint");
        return res.status(200).send("Minted Successfully");
    } catch (err) {
        return res.status(500).send("Error Minting");
    }
});

router.post("/burn", async (req, res) => {
    const userId: string = req.body.userId;
    const address = await BackgroundSigners.getUser(userId);
    
    try {
        await BackgroundSigners.backgroundSignerAction(userId, [parseEther("1")], "burn");
        return res.status(200).send("Burned Successfully");
    } catch (err) {
        return res.status(500).send("Error Burning");
    }
});

export default router;

Create Tools Page

Contracts

Data

  1. documentation
  2. documentation

Explorers

  1. documentation

Faucets

  1. documentation

Oracles

  1. documentation
  2. documentation

Packages

  1. documentation
  2. documentation enhancement
  3. documentation
  4. documentation enhancement
  5. documentation
  6. documentation
  7. question
  8. documentation enhancement
  9. question
  10. documentation
  11. documentation enhancement
  12. documentation enhancement
  13. documentation enhancement
  14. documentation enhancement
  15. documentation
  16. documentation
  17. documentation
  18. enhancement
  19. documentation
  20. documentation
  21. documentation

RPC Providers

  1. documentation help wanted
  2. documentation
  3. documentation help wanted
  4. documentation

Wallets

  1. documentation
  2. documentation
  3. documentation
  4. documentation
  5. documentation
  6. documentation enhancement
  7. documentation
  8. documentation
  9. documentation
  10. documentation
  11. documentation
  12. documentation

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.