@reown/appkit-controllers
Version:
#### 🔗 [Website](https://reown.com/appkit)
478 lines • 16.9 kB
JavaScript
import { proxy } from 'valtio/vanilla';
import { ConstantsUtil } from '../utils/ConstantsUtil.js';
import { CoreHelperUtil } from '../utils/CoreHelperUtil.js';
import { FetchUtil } from '../utils/FetchUtil.js';
import { StorageUtil } from '../utils/StorageUtil.js';
import { AccountController } from './AccountController.js';
import { ChainController } from './ChainController.js';
import { OptionsController } from './OptionsController.js';
import { SnackController } from './SnackController.js';
const DEFAULT_OPTIONS = {
purchaseCurrencies: [
{
id: '2b92315d-eab7-5bef-84fa-089a131333f5',
name: 'USD Coin',
symbol: 'USDC',
networks: [
{
name: 'ethereum-mainnet',
display_name: 'Ethereum',
chain_id: '1',
contract_address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
},
{
name: 'polygon-mainnet',
display_name: 'Polygon',
chain_id: '137',
contract_address: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174'
}
]
},
{
id: '2b92315d-eab7-5bef-84fa-089a131333f5',
name: 'Ether',
symbol: 'ETH',
networks: [
{
name: 'ethereum-mainnet',
display_name: 'Ethereum',
chain_id: '1',
contract_address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'
},
{
name: 'polygon-mainnet',
display_name: 'Polygon',
chain_id: '137',
contract_address: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174'
}
]
}
],
paymentCurrencies: [
{
id: 'USD',
payment_method_limits: [
{
id: 'card',
min: '10.00',
max: '7500.00'
},
{
id: 'ach_bank_account',
min: '10.00',
max: '25000.00'
}
]
},
{
id: 'EUR',
payment_method_limits: [
{
id: 'card',
min: '10.00',
max: '7500.00'
},
{
id: 'ach_bank_account',
min: '10.00',
max: '25000.00'
}
]
}
]
};
// -- Helpers ------------------------------------------- //
const baseUrl = CoreHelperUtil.getBlockchainApiUrl();
// -- State --------------------------------------------- //
const state = proxy({
clientId: null,
api: new FetchUtil({ baseUrl, clientId: null }),
supportedChains: { http: [], ws: [] }
});
// -- Controller ---------------------------------------- //
export const BlockchainApiController = {
state,
async get(request) {
const { st, sv } = BlockchainApiController.getSdkProperties();
const projectId = OptionsController.state.projectId;
const params = {
...(request.params || {}),
st,
sv,
projectId
};
return state.api.get({
...request,
params
});
},
getSdkProperties() {
const { sdkType, sdkVersion } = OptionsController.state;
return {
st: sdkType || 'unknown',
sv: sdkVersion || 'unknown'
};
},
async isNetworkSupported(networkId) {
if (!networkId) {
return false;
}
try {
if (!state.supportedChains.http.length) {
await BlockchainApiController.getSupportedNetworks();
}
}
catch (e) {
return false;
}
return state.supportedChains.http.includes(networkId);
},
async getSupportedNetworks() {
try {
const supportedChains = await BlockchainApiController.get({
path: 'v1/supported-chains'
});
state.supportedChains = supportedChains;
return supportedChains;
}
catch {
return state.supportedChains;
}
},
async fetchIdentity({ address, caipNetworkId }) {
const isSupported = await BlockchainApiController.isNetworkSupported(caipNetworkId);
if (!isSupported) {
return { avatar: '', name: '' };
}
const identityCache = StorageUtil.getIdentityFromCacheForAddress(address);
if (identityCache) {
return identityCache;
}
const result = await BlockchainApiController.get({
path: `/v1/identity/${address}`,
params: {
sender: ChainController.state.activeCaipAddress
? CoreHelperUtil.getPlainAddress(ChainController.state.activeCaipAddress)
: undefined
}
});
StorageUtil.updateIdentityCache({
address,
identity: result,
timestamp: Date.now()
});
return result;
},
async fetchTransactions({ account, cursor, onramp, signal, cache, chainId }) {
const isSupported = await BlockchainApiController.isNetworkSupported(ChainController.state.activeCaipNetwork?.caipNetworkId);
if (!isSupported) {
return { data: [], next: undefined };
}
return BlockchainApiController.get({
path: `/v1/account/${account}/history`,
params: {
cursor,
onramp,
chainId
},
signal,
cache
});
},
async fetchSwapQuote({ amount, userAddress, from, to, gasPrice }) {
const isSupported = await BlockchainApiController.isNetworkSupported(ChainController.state.activeCaipNetwork?.caipNetworkId);
if (!isSupported) {
return { quotes: [] };
}
return BlockchainApiController.get({
path: `/v1/convert/quotes`,
headers: {
'Content-Type': 'application/json'
},
params: {
amount,
userAddress,
from,
to,
gasPrice
}
});
},
async fetchSwapTokens({ chainId }) {
const isSupported = await BlockchainApiController.isNetworkSupported(ChainController.state.activeCaipNetwork?.caipNetworkId);
if (!isSupported) {
return { tokens: [] };
}
return BlockchainApiController.get({
path: `/v1/convert/tokens`,
params: { chainId }
});
},
async fetchTokenPrice({ addresses }) {
const isSupported = await BlockchainApiController.isNetworkSupported(ChainController.state.activeCaipNetwork?.caipNetworkId);
if (!isSupported) {
return { fungibles: [] };
}
return state.api.post({
path: '/v1/fungible/price',
body: {
currency: 'usd',
addresses,
projectId: OptionsController.state.projectId
},
headers: {
'Content-Type': 'application/json'
}
});
},
async fetchSwapAllowance({ tokenAddress, userAddress }) {
const isSupported = await BlockchainApiController.isNetworkSupported(ChainController.state.activeCaipNetwork?.caipNetworkId);
if (!isSupported) {
return { allowance: '0' };
}
return BlockchainApiController.get({
path: `/v1/convert/allowance`,
params: {
tokenAddress,
userAddress
},
headers: {
'Content-Type': 'application/json'
}
});
},
async fetchGasPrice({ chainId }) {
const { st, sv } = BlockchainApiController.getSdkProperties();
const isSupported = await BlockchainApiController.isNetworkSupported(ChainController.state.activeCaipNetwork?.caipNetworkId);
if (!isSupported) {
throw new Error('Network not supported for Gas Price');
}
return BlockchainApiController.get({
path: `/v1/convert/gas-price`,
headers: {
'Content-Type': 'application/json'
},
params: {
chainId,
st,
sv
}
});
},
async generateSwapCalldata({ amount, from, to, userAddress, disableEstimate }) {
const isSupported = await BlockchainApiController.isNetworkSupported(ChainController.state.activeCaipNetwork?.caipNetworkId);
if (!isSupported) {
throw new Error('Network not supported for Swaps');
}
return state.api.post({
path: '/v1/convert/build-transaction',
headers: {
'Content-Type': 'application/json'
},
body: {
amount,
eip155: {
slippage: ConstantsUtil.CONVERT_SLIPPAGE_TOLERANCE
},
projectId: OptionsController.state.projectId,
from,
to,
userAddress,
disableEstimate
}
});
},
async generateApproveCalldata({ from, to, userAddress }) {
const { st, sv } = BlockchainApiController.getSdkProperties();
const isSupported = await BlockchainApiController.isNetworkSupported(ChainController.state.activeCaipNetwork?.caipNetworkId);
if (!isSupported) {
throw new Error('Network not supported for Swaps');
}
return BlockchainApiController.get({
path: `/v1/convert/build-approve`,
headers: {
'Content-Type': 'application/json'
},
params: {
userAddress,
from,
to,
st,
sv
}
});
},
async getBalance(address, chainId, forceUpdate) {
const { st, sv } = BlockchainApiController.getSdkProperties();
const isSupported = await BlockchainApiController.isNetworkSupported(ChainController.state.activeCaipNetwork?.caipNetworkId);
if (!isSupported) {
SnackController.showError('Token Balance Unavailable');
return { balances: [] };
}
const caipAddress = `${chainId}:${address}`;
const cachedBalance = StorageUtil.getBalanceCacheForCaipAddress(caipAddress);
if (cachedBalance) {
return cachedBalance;
}
const balance = await BlockchainApiController.get({
path: `/v1/account/${address}/balance`,
params: {
currency: 'usd',
chainId,
forceUpdate,
st,
sv
}
});
StorageUtil.updateBalanceCache({
caipAddress,
balance,
timestamp: Date.now()
});
return balance;
},
async lookupEnsName(name) {
const isSupported = await BlockchainApiController.isNetworkSupported(ChainController.state.activeCaipNetwork?.caipNetworkId);
if (!isSupported) {
return { addresses: {}, attributes: [] };
}
return BlockchainApiController.get({
path: `/v1/profile/account/${name}`,
params: { apiVersion: '2' }
});
},
async reverseLookupEnsName({ address }) {
const isSupported = await BlockchainApiController.isNetworkSupported(ChainController.state.activeCaipNetwork?.caipNetworkId);
if (!isSupported) {
return [];
}
return BlockchainApiController.get({
path: `/v1/profile/reverse/${address}`,
params: {
sender: AccountController.state.address,
apiVersion: '2'
}
});
},
async getEnsNameSuggestions(name) {
const isSupported = await BlockchainApiController.isNetworkSupported(ChainController.state.activeCaipNetwork?.caipNetworkId);
if (!isSupported) {
return { suggestions: [] };
}
return BlockchainApiController.get({
path: `/v1/profile/suggestions/${name}`,
params: { zone: 'reown.id' }
});
},
async registerEnsName({ coinType, address, message, signature }) {
const isSupported = await BlockchainApiController.isNetworkSupported(ChainController.state.activeCaipNetwork?.caipNetworkId);
if (!isSupported) {
return { success: false };
}
return state.api.post({
path: `/v1/profile/account`,
body: { coin_type: coinType, address, message, signature },
headers: {
'Content-Type': 'application/json'
}
});
},
async generateOnRampURL({ destinationWallets, partnerUserId, defaultNetwork, purchaseAmount, paymentAmount }) {
const isSupported = await BlockchainApiController.isNetworkSupported(ChainController.state.activeCaipNetwork?.caipNetworkId);
if (!isSupported) {
return '';
}
const response = await state.api.post({
path: `/v1/generators/onrampurl`,
params: {
projectId: OptionsController.state.projectId
},
body: {
destinationWallets,
defaultNetwork,
partnerUserId,
defaultExperience: 'buy',
presetCryptoAmount: purchaseAmount,
presetFiatAmount: paymentAmount
}
});
return response.url;
},
async getOnrampOptions() {
const isSupported = await BlockchainApiController.isNetworkSupported(ChainController.state.activeCaipNetwork?.caipNetworkId);
if (!isSupported) {
return { paymentCurrencies: [], purchaseCurrencies: [] };
}
try {
const response = await BlockchainApiController.get({
path: `/v1/onramp/options`
});
return response;
}
catch (e) {
return DEFAULT_OPTIONS;
}
},
async getOnrampQuote({ purchaseCurrency, paymentCurrency, amount, network }) {
try {
const isSupported = await BlockchainApiController.isNetworkSupported(ChainController.state.activeCaipNetwork?.caipNetworkId);
if (!isSupported) {
return null;
}
const response = await state.api.post({
path: `/v1/onramp/quote`,
params: {
projectId: OptionsController.state.projectId
},
body: {
purchaseCurrency,
paymentCurrency,
amount,
network
}
});
return response;
}
catch (e) {
// Mocking response as 1:1 until endpoint is ready
return {
coinbaseFee: { amount, currency: paymentCurrency.id },
networkFee: { amount, currency: paymentCurrency.id },
paymentSubtotal: { amount, currency: paymentCurrency.id },
paymentTotal: { amount, currency: paymentCurrency.id },
purchaseAmount: { amount, currency: paymentCurrency.id },
quoteId: 'mocked-quote-id'
};
}
},
async getSmartSessions(caipAddress) {
const isSupported = await BlockchainApiController.isNetworkSupported(ChainController.state.activeCaipNetwork?.caipNetworkId);
if (!isSupported) {
return [];
}
return BlockchainApiController.get({
path: `/v1/sessions/${caipAddress}`
});
},
async revokeSmartSession(address, pci, signature) {
const isSupported = await BlockchainApiController.isNetworkSupported(ChainController.state.activeCaipNetwork?.caipNetworkId);
if (!isSupported) {
return { success: false };
}
return state.api.post({
path: `/v1/sessions/${address}/revoke`,
params: {
projectId: OptionsController.state.projectId
},
body: {
pci,
signature
}
});
},
setClientId(clientId) {
state.clientId = clientId;
state.api = new FetchUtil({ baseUrl, clientId });
}
};
//# sourceMappingURL=BlockchainApiController.js.map