Fantom (FTM)
Fantom is a high-performance, scalable, and secure smart-contract platform. It is designed to overcome the limitations of previous generation blockchain platforms. Fantom is permissionless, decentralized, and open-source.
This document is based on the EVMs (Ethereum Virtual Machine) and the Ethereum network.
Detect Ctrl Wallet with Ethereum Base Chain
To detect whether your browser is running Ctrl Wallet, you can use the following code:
if (
(typeof window.ethereum !== "undefined" && window.ethereum?._XDEFI) ||
window.xfi
) {
console.log("Ctrl Wallet detected");
// Your code here
}
Notice: window.ethereum
is a standard Ethereum provider object, and window.ethereum._XDEFI
is a property added by Ctrl Wallet. If window.ethereum
is not available, you can also check window.xfi
which is a global object added by Ctrl Wallet.
The Ctrl Wallet on Ethereum JavaScript provider API is specified by EIP-1193 and EIP-6963. Support window.ethereum
only and removal window.web3
Connect/Disconnect to Ctrl Wallet
To connect to Ctrl Wallet (access the user's [blockchain - like Ethereum] account(s)), you can use the following code:
// Connect & get accounts
window.ethereum.request({method: 'eth_accounts'});
// Alias for connection
window.ethereum.request({method: 'eth_requestAccounts'});
// Check if dapp connected
window.ethereum.isConnected();
// Check if the caller's current permissions
window.ethereum.request({method: 'wallet_getPermissions'});
// Check if request the given permissions
window.ethereum.request({method: 'wallet_requestPermissions'});
To disconnect from Ctrl Wallet, please use:
window.ethereum.disconnect();
Experience functions
When your account is connected to Ctrl Wallet, let's start experiencing more functions.
Get the current account
window.ethereum.request({ method: "eth_accounts" }).then((accounts) => {
if (accounts.length > 0) {
console.log("Current account:", accounts[0]);
// Do something with the account
} else {
console.log("No account connected");
// Do something else
}
});
Above code will return Promise<Array[String]>
with the current account address. If wallet can not be found, return []
instead of throw Error
Check wallet whether it is connected(exists) or not
window.ethereum
.request({ method: "has_wallet", params: ["ethereum"] })
.then(() => {
// Wallet is connected
})
.catch((e) => {
// Wallet not found (not exist)
});
Above code will return Promise<Boolean>
with the current account address. If wallet can not be found, return false
instead of throw Error
Sign Transaction
// Example Sign Transactionconst
const signature = window.ethereum.request({
method: 'eth_signTransaction',
params: [
"from": "string",
"to": "string",
"gas": "string",
"gasPrice": "string",
"value": "string",
"data": "string",
"nonce": "string"
]
});
Above code will return Promise<Signature | RPC: 2.0>
Transfer
window.ethereum.request({
method: "eth_sendTransaction",
params: [
{
from: "string",
to: "string",
gas: "string",
gasPrice: "string",
value: "string",
data: "string",
nonce: "string",
},
],
});
Return Promise<String>
with the transaction hash
Decrypt Message
window.ethereum
.request({ method: "eth_decrypt", params: [encryptedMessage, accounts[0]] })
.then((decryptedMessage) =>
console.log("The decrypted message is:", decryptedMessage),
)
.catch((error) => console.log(error.message));
Above code will return Promise<String>
with the decrypted message
Get Encryption Public Key
Return Promise<String>
with the public key
let encryptionPublicKey;
window.ethereum
.request({
method: "eth_getEncryptionPublicKey",
params: [accounts[0]], // You must have access to the specified account
})
.then((result) => {
encryptionPublicKey = result;
})
.catch((error) => {
if (error.code === 4001) {
// EIP-1193 userRejectedRequest error
console.log("Can't encrypt anything without the key.");
} else {
console.error(error);
}
});
Encrypt Message
const ethUtil = require('ethereumjs-util');
const encryptedMessage = ethUtil.bufferToHex(
Buffer.from(
JSON.stringify(
sigUtil.encrypt(
{
publicKey: encryptionPublicKey,
data: 'Hello, World!,
version: 'x25519-xsalsa20-poly1305',
}
)
),
'utf8'
)
);
Add Ethereum Chain
window.ethereum.request
interface AddEthereumChainParameter {
chainId: string; // A 0x-prefix hex string
chainName: string;
nativeCurrency: {
name: string;
symbol: string; // 2-6 characters long
decimals: 18;
};
rpcUrls: string[];
blockExplorerUrls?: string[];
iconUrls?: string[]; // Currently ignored
}
Return Promise<void>
with the result
Switch Ethereum Chain
Return Promise<void>
with the result, and an error otherwise
try {
await window.await ethereum.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId: '0xf00' }],
});
} catch (switchError) {
if (switchError.code === 4902) {
try {
await ethereum.request({
method: 'wallet_addEthereumChain',
params: [
{
chainId: '0xf00',
chainName: '...',
rpcUrls: ['https://...'] /* ... */,
},
],
});
} catch (addError) {
// handle "add" error
}
}
// handle other "switch" errors
}
Watch Asset
Return true if the token was added, false otherwise
window.ethereum
.request({
method: "wallet_watchAsset",
params: {
type: "ERC20",
options: {
address: "0x1234567890123456789012345678901234567890",
symbol: "FOO",
decimals: 18,
image: "https://example.com/token-image.png",
},
},
})
.then((success) => {
if (success) {
console.log("FOO successfully added to wallet!");
} else {
throw new Error("Something went wrong.");
}
})
.catch(console.error);
RPC Request
Return Promise<Ethereum RPC>
Currently only support HTTP(s) method Reference: RPC Method
window.ethereum.request({method: '<Method>', params: [args1,....]})
Subscription
Support subscribe using JSON-RPC notifications. This allows clients to wait for events instead of polling for them. All results will be released at data
event.
Methods
// For Subscribe
window.ethereum
.request({
method: "eth_subscribe",
params: ["<type>", "<options>"],
})
.then((subscriptionId) => {
console.log("Subscription ID:", subscriptionId);
// Do something with the subscription ID
});
// For Unsubscribe
window.ethereum.request({
method: "eth_unsubscribe",
params: ["<Subscription ID>"],
});
Example
// Subscribe for event
const subscriptionID = window.ethereum.request({method: 'eth_subscribe', params: ["logs", {
address: "0x1234567890123456789012345678901234567890",
topics: ["0x1234567890123456789012345678901234567890123456789012345678901234"]
})
// You can listen for incoming notifications by
window.ethereum.on("data", data => {
// Do the rest of your work with data
})
Events
Currently we only support some action events from Wallet
window.ethereum.on('event_name', callback);
//Example
window.ethereum.on('close', () => window.location.reload());
window.ethereum.on('accountsChanged', () => window.location.reload());
Events supported
Events | Trigger |
---|---|
accountsChanged | Receive when active account changed in Wallet |
networkChanged | Receive when active network changed in Wallet |
chainChanged | Receive when active chain changed in Wallet |
close | Alias for disconnect event |
disconnect | Receive when disconnecting from Wallet |
Methods supported
Methods | Description |
---|---|
on(event, callback) | Add event listener |
off(event, callback) | Remove event listener |