skalenetwork / docs.skale.space Goto Github PK
View Code? Open in Web Editor NEWHome Page: https://docs.skale.space/
License: MIT License
Home Page: https://docs.skale.space/
License: MIT License
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
Viem is a TypeScript interface for Ethereum that provides low-level stateless primitives for interacting with Ethereum.
Some of the main features are:
For more information check the View Documentation
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;
});
Coinbase Wallet is a self-custody crypto wallet, available as a browser extension and a mobile app on Android and iOS
npm install --save web3 @coinbase/wallet-sdk
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 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:
For more information check the Thirdweb documentation.
The sFUEL Station is a general distribution for the SKALE Network. It supports multiple chains by default as well as both Mainnet and Testnet.
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.
Adding your chain to the sFUEL Station is a three-step process:
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.
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.
[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.
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 is a Typescirpt/Javascript library which implements client for SKALE Interchain Messaging Agent (IMA).
Package Install
npm install --save @skalenetwork/ima-js
Initialization
There are 2 ways to use IMA.js library in your project:
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:
ima.mainnet
- equals to MainnetChain
objectima.schain
- equals to Schain
objectWorking 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);
Detailed documentation about ETH and token transfers using IMA-JS can be found here:
missing link
missing link
missing link
missing link
There are 2 ways to sign a transaction in the current version of IMA-JS:
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
);
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:
For more information about it check the SKALE Documentation
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 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.
This library implements the web3.js library in Swift. It enables interaction with EVM compatible blockchains.
Some of the features are:
For more information check the Web3.Swift documentation page.
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/
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);
The Enkrypt wallet is a multichain non-custodial wallet allowing users to easily manage tokens and access web3 application across multiple blockchains, like SKALE Network!
Enkrypt specifically allows users to perform network changes without confirmation popups.
For more information you can read about Enkrypt here:
https://myetherwallet.gitbook.io/enkrypt-documentation/add-enkrypt-to-dapps
Need revisit with working example
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
npm install @trezor/connect
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 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:
For more information check the following Kethereum Github repository https://github.com/komputing/KEthereum
Library written in dart that enables interaction with EVM compatible blockchains.
Some of the features of the library are:
For more informatio checkout the Web3Dart documentation page.
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 serves as a Web3 SDK tailored for game developers, seamlessly integrating with Unreal Engine and Unity through.
It provides features such as:
For more information checkout the Emergence SDK documentation.
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:
For more information check the Chainsafe documentation.
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:
For more information check the web3j documentation.
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>
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.
To integrate and start using the SDK right away go to the Eidolon documentation Quick Start section
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.
For more information check the Eidolon documentation.
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.
In order to user SKALE Create2 Factory check the SKALE deterministic deployment proxy
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.
The main features of this web3 library are:
For more information check the Nethereum documentation
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);
}
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
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
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();
Set of Javascript libraries enabling interaction with a local or remote Ethereum node through HTTP, IPC, or WebSocket protocols.
Some of the features are:
For more information check the Web3.js documentation.
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 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:
To test out a playground environment, check out https://testnet.portal.skale.space/
npm install --save @skalenetwork/[email protected]
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);
====
You can skip almost all initialization options and set available tokens, chains and theme after Metaport initialization.
When possible, use bridge configurations below. Otherwise, pay close attention to the tokenKeyname and be sure to match it closely across chains.
====
For custom bridge configurations, see xref:_example_metaport_options[Example Metaport Options section below].
For applying already used bridge configurations, use the following network configs:
** For staging, use https://github.com/skalenetwork/bridge-ui/blob/main/env/staging/metaportConfig.json
** For mainnet, use https://github.com/skalenetwork/bridge-ui/blob/main/env/mainnet/metaportConfig.json
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]);
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
}
});
See https://github.com/Dirt-Road-Development/skale-metaport-demo-cra
It has two primary use-cases:
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 | โ | โ |
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.
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:
For more information check the Magic Documentation.
WITH BUG: Can't connect to SKALE Chains. Need to check
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.
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);
In case of encountering polyfill related issues check the Web3auth troubleshooting page about this topic
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:
For more information visit the Mirage documentation
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.
x.x.x.x:x.x.x.x
) and SKALE Chain for full-sync.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.
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"
chmod +x /usr/local/bin/skale
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]
skale sync-node init [ENV_FILE_PATH]
skaled
will download the snapshot and starts catchup blocks (usually 15โ30 minutes)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.
Update full sync SKALE node on current machine
skale sync-node update [ENV_FILEPATH]
Options:
--yes
- update without additional confirmationArguments:
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 commands are not available for a sync node.
Web3.unreal is a plugin that brings web3 functionality to desktop games built with Unreal Engine.
Some of the features are:
For more information check the Web3.Unreal documentation page.
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
npm install --save web3 @portis/web3
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);
https://codesandbox.io/s/portis-wallet-integration-skale-dev-docs-41knv
Not sure if it makes sense here since their product is mostly the wallet a and we already touch on the wallet section @TheGreatAxios
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
npm install --save web3
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!"
);
}
https://codesandbox.io/s/metamask-wallet-integration-skale-dev-docs-k77zj
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
npm install --save web3 @walletconnect/web3-provider
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);
https://codesandbox.io/s/wallet-connect-wallet-integration-skale-dev-docs-forked-5xq08
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/
npm install --save web3 bitski
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");
});
}
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.
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;
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.