@thirdweb-dev/wallets
Version:
<p align="center"> <br /> <a href="https://thirdweb.com"><img src="https://github.com/thirdweb-dev/js/blob/main/legacy_packages/sdk/logo.svg?raw=true" width="200" alt=""/></a> <br /> </p> <h1 align="center">thirdweb Wallet SDK</h1> <p align="center"> <a h
294 lines (283 loc) • 7.72 kB
JavaScript
import { _ as _defineProperty } from '../../../../dist/defineProperty-7303a112.esm.js';
import { Contract, utils } from 'ethers';
import EventEmitter from 'eventemitter3';
import { isNativeToken, fetchCurrencyValue, normalizePriceValue, getDefaultGasOverrides, NATIVE_TOKEN_ADDRESS } from '@thirdweb-dev/sdk';
const ERC20WithDecimalsAbi = [{
anonymous: false,
inputs: [{
indexed: true,
internalType: "address",
name: "owner",
type: "address"
}, {
indexed: true,
internalType: "address",
name: "spender",
type: "address"
}, {
indexed: false,
internalType: "uint256",
name: "value",
type: "uint256"
}],
name: "Approval",
type: "event"
}, {
anonymous: false,
inputs: [{
indexed: true,
internalType: "address",
name: "from",
type: "address"
}, {
indexed: true,
internalType: "address",
name: "to",
type: "address"
}, {
indexed: false,
internalType: "uint256",
name: "value",
type: "uint256"
}],
name: "Transfer",
type: "event"
}, {
inputs: [{
internalType: "address",
name: "owner",
type: "address"
}, {
internalType: "address",
name: "spender",
type: "address"
}],
name: "allowance",
outputs: [{
internalType: "uint256",
name: "",
type: "uint256"
}],
stateMutability: "view",
type: "function"
}, {
inputs: [{
internalType: "address",
name: "spender",
type: "address"
}, {
internalType: "uint256",
name: "value",
type: "uint256"
}],
name: "approve",
outputs: [{
internalType: "bool",
name: "",
type: "bool"
}],
stateMutability: "nonpayable",
type: "function"
}, {
inputs: [{
internalType: "address",
name: "who",
type: "address"
}],
name: "balanceOf",
outputs: [{
internalType: "uint256",
name: "",
type: "uint256"
}],
stateMutability: "view",
type: "function"
}, {
inputs: [],
name: "totalSupply",
outputs: [{
internalType: "uint256",
name: "",
type: "uint256"
}],
stateMutability: "view",
type: "function"
}, {
inputs: [{
internalType: "address",
name: "to",
type: "address"
}, {
internalType: "uint256",
name: "value",
type: "uint256"
}],
name: "transfer",
outputs: [{
internalType: "bool",
name: "",
type: "bool"
}],
stateMutability: "nonpayable",
type: "function"
}, {
inputs: [{
internalType: "address",
name: "from",
type: "address"
}, {
internalType: "address",
name: "to",
type: "address"
}, {
internalType: "uint256",
name: "value",
type: "uint256"
}],
name: "transferFrom",
outputs: [{
internalType: "bool",
name: "",
type: "bool"
}],
stateMutability: "nonpayable",
type: "function"
}, {
inputs: [],
name: "decimals",
outputs: [{
internalType: "uint8",
name: "",
type: "uint8"
}],
stateMutability: "view",
type: "function"
}];
function createErc20(provider, currencyAddress) {
return new Contract(currencyAddress, ERC20WithDecimalsAbi, provider);
}
// TODO improve this
function chainIdToThirdwebRpc(chainId, clientId) {
return `https://${chainId}.rpc.thirdweb.com${clientId ? `/${clientId}` : ""}${typeof globalThis !== "undefined" && "APP_BUNDLE_ID" in globalThis && !!globalThis.APP_BUNDLE_ID ? `?bundleId=${globalThis.APP_BUNDLE_ID}` : ""}`;
}
/**
* The base class for any wallet in the Wallet SDK, including backend wallets. It contains the functionality common to all wallets.
*
* This wallet is not meant to be used directly, but instead be extended to [build your own wallet](https://portal.thirdweb.com/wallet-sdk/v2/build)
*
* @abstractWallet
*/
class AbstractWallet extends EventEmitter {
constructor() {
super(...arguments);
/**
* @internal
*/
_defineProperty(this, "type", "evm");
}
/**
* Returns an [ethers Signer](https://docs.ethers.org/v5/api/signer/) object of the connected wallet
*/
/**
* Returns the account address of the connected wallet
*/
async getAddress() {
const signer = await this.getSigner();
return signer.getAddress();
}
/**
* Returns the balance of the connected wallet for the specified token address. If no token address is specified, it returns the balance of the native token
*
* @param tokenAddress - The contract address of the token
*/
async getBalance() {
let tokenAddress = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : NATIVE_TOKEN_ADDRESS;
const signer = await this.getSigner();
const address = await this.getAddress();
if (!signer.provider) {
throw new Error("Please connect a provider");
}
let balance;
if (isNativeToken(tokenAddress)) {
balance = await signer.provider.getBalance(address);
} else {
const erc20 = createErc20(signer, tokenAddress);
balance = await erc20.balanceOf(address);
}
// Note: assumes that the native currency decimals is 18, which isn't always correct
return await fetchCurrencyValue(signer.provider, tokenAddress, balance);
}
/**
* Returns the chain id of the network that the wallet is connected to
*/
async getChainId() {
const signer = await this.getSigner();
return signer.getChainId();
}
/**
* Transfers some amount of tokens to the specified address
* @param to - The address to transfer the amount to
* @param amount - The amount to transfer
* @param currencyAddress - The contract address of the token to transfer. If not specified, it defaults to the native token
* @returns The transaction result
*/
async transfer(to, amount) {
let currencyAddress = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : NATIVE_TOKEN_ADDRESS;
const signer = await this.getSigner();
const from = await this.getAddress();
if (!signer.provider) {
throw new Error("Please connect a provider");
}
const value = await normalizePriceValue(signer.provider, amount, currencyAddress);
if (isNativeToken(currencyAddress)) {
const gas = getDefaultGasOverrides(signer.provider);
const tx = await signer.sendTransaction({
from,
to,
value,
...gas
});
return {
receipt: await tx.wait()
};
} else {
const erc20 = createErc20(signer, currencyAddress);
const tx = await erc20.transfer(to, value);
return {
receipt: await tx.wait()
};
}
}
/**
* Sign a message with the connected wallet and return the signature
* @param message - The message to sign
* @returns - The signature
*/
async signMessage(message) {
const signer = await this.getSigner();
return await signer.signMessage(message);
}
/**
* Verify the signature of a message. It returns `true` if the signature is valid, `false` otherwise
* @param message - The message to verify
* @param signature - The signature to verify
* @param address - The address to verify the signature against
* @param chainId - The chain id of the network to verify the signature against, If not specified, it defaults to 1 ( Ethereum mainnet )
*/
async verifySignature(message, signature, address,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_chainId) {
try {
const messageHash = utils.hashMessage(message);
const messageHashBytes = utils.arrayify(messageHash);
const recoveredAddress = utils.recoverAddress(messageHashBytes, signature);
if (recoveredAddress === address) {
return true;
}
} catch {
// no-op
}
return false;
}
}
export { AbstractWallet, chainIdToThirdwebRpc };