@sodax/wallet-sdk-react 1.5.7-beta → 2.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -145
- package/ai-exported/AGENTS.md +122 -0
- package/ai-exported/integration/README.md +102 -0
- package/ai-exported/integration/ai-rules.md +136 -0
- package/ai-exported/integration/architecture.md +181 -0
- package/ai-exported/integration/examples/01-minimal-evm.tsx +75 -0
- package/ai-exported/integration/examples/02-multi-chain-modal.tsx +169 -0
- package/ai-exported/integration/examples/03-nextjs-app-router.tsx +99 -0
- package/ai-exported/integration/examples/04-walletconnect-setup.tsx +89 -0
- package/ai-exported/integration/examples/README.md +29 -0
- package/ai-exported/integration/recipes/batch-operations.md +223 -0
- package/ai-exported/integration/recipes/bridge-to-sdk.md +164 -0
- package/ai-exported/integration/recipes/chain-detection.md +254 -0
- package/ai-exported/integration/recipes/connect-button.md +156 -0
- package/ai-exported/integration/recipes/multi-chain-modal.md +199 -0
- package/ai-exported/integration/recipes/setup.md +158 -0
- package/ai-exported/integration/recipes/sign-message.md +137 -0
- package/ai-exported/integration/recipes/sub-path-imports.md +95 -0
- package/ai-exported/integration/recipes/switch-chain.md +141 -0
- package/ai-exported/integration/recipes/walletconnect-setup.md +139 -0
- package/ai-exported/integration/reference/api-surface.md +175 -0
- package/ai-exported/integration/reference/chain-support.md +78 -0
- package/ai-exported/integration/reference/connectors.md +74 -0
- package/ai-exported/integration/reference/hooks.md +204 -0
- package/ai-exported/integration/reference/wallet-brands.md +106 -0
- package/ai-exported/migration/README.md +49 -0
- package/ai-exported/migration/ai-rules.md +144 -0
- package/ai-exported/migration/breaking-changes.md +305 -0
- package/ai-exported/migration/checklist.md +159 -0
- package/ai-exported/migration/recipes/connect-button.md +166 -0
- package/ai-exported/migration/recipes/multi-chain-modal.md +244 -0
- package/ai-exported/migration/recipes/ssr-setup.md +162 -0
- package/ai-exported/migration/recipes/walletconnect-migration.md +168 -0
- package/ai-exported/migration/reference/components.md +73 -0
- package/ai-exported/migration/reference/config.md +307 -0
- package/ai-exported/migration/reference/hooks.md +278 -0
- package/ai-exported/migration/reference/imports.md +157 -0
- package/dist/XConnector-B9YQTVJ4.d.ts +146 -0
- package/dist/chunk-2BOUGCJ7.mjs +150 -0
- package/dist/chunk-2BOUGCJ7.mjs.map +1 -0
- package/dist/chunk-66BAUK56.mjs +202 -0
- package/dist/chunk-66BAUK56.mjs.map +1 -0
- package/dist/chunk-7ULB6DW4.mjs +102 -0
- package/dist/chunk-7ULB6DW4.mjs.map +1 -0
- package/dist/chunk-BKJB527E.mjs +125 -0
- package/dist/chunk-BKJB527E.mjs.map +1 -0
- package/dist/chunk-BXJLBR4G.mjs +88 -0
- package/dist/chunk-BXJLBR4G.mjs.map +1 -0
- package/dist/chunk-E5IAZ7E6.mjs +186 -0
- package/dist/chunk-E5IAZ7E6.mjs.map +1 -0
- package/dist/chunk-MAQ47Q52.mjs +33 -0
- package/dist/chunk-MAQ47Q52.mjs.map +1 -0
- package/dist/chunk-MXZVF5HR.mjs +34 -0
- package/dist/chunk-MXZVF5HR.mjs.map +1 -0
- package/dist/chunk-N5A2TMF6.mjs +33 -0
- package/dist/chunk-N5A2TMF6.mjs.map +1 -0
- package/dist/chunk-NY7U7OJW.mjs +64 -0
- package/dist/chunk-NY7U7OJW.mjs.map +1 -0
- package/dist/chunk-PJLEJVAU.mjs +140 -0
- package/dist/chunk-PJLEJVAU.mjs.map +1 -0
- package/dist/chunk-PLCA4ZDJ.mjs +1585 -0
- package/dist/chunk-PLCA4ZDJ.mjs.map +1 -0
- package/dist/chunk-TZMKDXFA.mjs +3 -0
- package/dist/chunk-TZMKDXFA.mjs.map +1 -0
- package/dist/chunk-X2MHIWXO.mjs +100 -0
- package/dist/chunk-X2MHIWXO.mjs.map +1 -0
- package/dist/chunk-XZ7CHO2S.mjs +41 -0
- package/dist/chunk-XZ7CHO2S.mjs.map +1 -0
- package/dist/config-OlnzyEUE.d.ts +146 -0
- package/dist/index.cjs +2784 -1594
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +768 -1498
- package/dist/index.mjs +463 -2004
- package/dist/index.mjs.map +1 -1
- package/dist/xchains/bitcoin/index.cjs +1927 -0
- package/dist/xchains/bitcoin/index.cjs.map +1 -0
- package/dist/xchains/bitcoin/index.d.ts +125 -0
- package/dist/xchains/bitcoin/index.mjs +16 -0
- package/dist/xchains/bitcoin/index.mjs.map +1 -0
- package/dist/xchains/evm/index.cjs +316 -0
- package/dist/xchains/evm/index.cjs.map +1 -0
- package/dist/xchains/evm/index.d.ts +39 -0
- package/dist/xchains/evm/index.mjs +5 -0
- package/dist/xchains/evm/index.mjs.map +1 -0
- package/dist/xchains/icon/index.cjs +311 -0
- package/dist/xchains/icon/index.cjs.map +1 -0
- package/dist/xchains/icon/index.d.ts +37 -0
- package/dist/xchains/icon/index.mjs +7 -0
- package/dist/xchains/icon/index.mjs.map +1 -0
- package/dist/xchains/injective/index.cjs +223 -0
- package/dist/xchains/injective/index.cjs.map +1 -0
- package/dist/xchains/injective/index.d.ts +35 -0
- package/dist/xchains/injective/index.mjs +5 -0
- package/dist/xchains/injective/index.mjs.map +1 -0
- package/dist/xchains/near/index.cjs +190 -0
- package/dist/xchains/near/index.cjs.map +1 -0
- package/dist/xchains/near/index.d.ts +34 -0
- package/dist/xchains/near/index.mjs +6 -0
- package/dist/xchains/near/index.mjs.map +1 -0
- package/dist/xchains/solana/index.cjs +186 -0
- package/dist/xchains/solana/index.cjs.map +1 -0
- package/dist/xchains/solana/index.d.ts +26 -0
- package/dist/xchains/solana/index.mjs +7 -0
- package/dist/xchains/solana/index.mjs.map +1 -0
- package/dist/xchains/stacks/index.cjs +240 -0
- package/dist/xchains/stacks/index.cjs.map +1 -0
- package/dist/xchains/stacks/index.d.ts +36 -0
- package/dist/xchains/stacks/index.mjs +5 -0
- package/dist/xchains/stacks/index.mjs.map +1 -0
- package/dist/xchains/stellar/index.cjs +322 -0
- package/dist/xchains/stellar/index.cjs.map +1 -0
- package/dist/xchains/stellar/index.d.ts +44 -0
- package/dist/xchains/stellar/index.mjs +6 -0
- package/dist/xchains/stellar/index.mjs.map +1 -0
- package/dist/xchains/sui/index.cjs +248 -0
- package/dist/xchains/sui/index.cjs.map +1 -0
- package/dist/xchains/sui/index.d.ts +37 -0
- package/dist/xchains/sui/index.mjs +7 -0
- package/dist/xchains/sui/index.mjs.map +1 -0
- package/docs/ADDING_A_NEW_CHAIN.md +440 -0
- package/docs/ARCHITECTURE.md +291 -0
- package/docs/BATCH_OPERATIONS.md +267 -0
- package/docs/CHAIN_DETECTION.md +216 -0
- package/docs/CONFIGURE_PROVIDER.md +360 -0
- package/docs/CONNECTORS.md +247 -0
- package/docs/CONNECT_FLOW.md +276 -0
- package/docs/EVM_SWITCH_CHAIN.md +161 -0
- package/docs/SIGN_MESSAGE.md +213 -0
- package/docs/SUB_PATH_EXPORTS.md +246 -0
- package/docs/WALLETCONNECT.md +154 -0
- package/docs/WALLET_MODAL.md +331 -0
- package/docs/WALLET_PROVIDER_BRIDGE.md +226 -0
- package/package.json +34 -9
- package/skills/SKILLS.md +84 -0
- package/skills/bridge-to-sdk.md +148 -0
- package/skills/connect-button.md +116 -0
- package/skills/evm-only-walletconnect.md +111 -0
- package/skills/multi-chain-modal.md +178 -0
- package/skills/setup.md +107 -0
- package/dist/index.d.cts +0 -1579
- package/src/Hydrate.ts +0 -65
- package/src/SodaxWalletProvider.tsx +0 -97
- package/src/actions/getXChainType.ts +0 -8
- package/src/actions/getXService.ts +0 -33
- package/src/actions/index.ts +0 -2
- package/src/assets/wallets/hana.svg +0 -6
- package/src/assets/wallets/havah.svg +0 -76
- package/src/assets/wallets/keplr.svg +0 -30
- package/src/assets/wallets/metamask.svg +0 -60
- package/src/assets/wallets/phantom.svg +0 -4
- package/src/assets/wallets/sui.svg +0 -20
- package/src/core/XConnector.ts +0 -54
- package/src/core/XService.ts +0 -85
- package/src/core/index.ts +0 -2
- package/src/hooks/index.ts +0 -11
- package/src/hooks/useEthereumChainId.ts +0 -44
- package/src/hooks/useEvmSwitchChain.ts +0 -91
- package/src/hooks/useWalletProvider.ts +0 -206
- package/src/hooks/useXAccount.ts +0 -51
- package/src/hooks/useXAccounts.ts +0 -56
- package/src/hooks/useXBalances.ts +0 -65
- package/src/hooks/useXConnect.ts +0 -118
- package/src/hooks/useXConnection.ts +0 -72
- package/src/hooks/useXConnectors.ts +0 -72
- package/src/hooks/useXDisconnect.ts +0 -73
- package/src/hooks/useXService.ts +0 -8
- package/src/hooks/useXSignMessage.ts +0 -82
- package/src/index.ts +0 -19
- package/src/types/index.ts +0 -22
- package/src/useXWagmiStore.ts +0 -116
- package/src/utils/index.ts +0 -21
- package/src/xchains/bitcoin/BitcoinXConnector.ts +0 -34
- package/src/xchains/bitcoin/BitcoinXService.ts +0 -40
- package/src/xchains/bitcoin/OKXXConnector.ts +0 -117
- package/src/xchains/bitcoin/UnisatXConnector.ts +0 -117
- package/src/xchains/bitcoin/XverseXConnector.ts +0 -232
- package/src/xchains/bitcoin/index.ts +0 -7
- package/src/xchains/bitcoin/useBitcoinXConnectors.ts +0 -14
- package/src/xchains/evm/EvmXConnector.ts +0 -27
- package/src/xchains/evm/EvmXService.ts +0 -211
- package/src/xchains/evm/index.ts +0 -3
- package/src/xchains/icon/IconHanaXConnector.ts +0 -39
- package/src/xchains/icon/IconXService.ts +0 -117
- package/src/xchains/icon/actions.ts +0 -28
- package/src/xchains/icon/iconex/index.tsx +0 -46
- package/src/xchains/icon/index.ts +0 -2
- package/src/xchains/injective/InjectiveXConnector.ts +0 -60
- package/src/xchains/injective/InjectiveXService.ts +0 -62
- package/src/xchains/injective/actions.ts +0 -32
- package/src/xchains/injective/index.ts +0 -2
- package/src/xchains/near/NearXConnector.ts +0 -42
- package/src/xchains/near/NearXService.ts +0 -46
- package/src/xchains/near/useNearXConnectors.ts +0 -23
- package/src/xchains/solana/SolanaXConnector.ts +0 -26
- package/src/xchains/solana/SolanaXService.ts +0 -46
- package/src/xchains/solana/index.ts +0 -2
- package/src/xchains/stacks/StacksXConnector.ts +0 -63
- package/src/xchains/stacks/StacksXService.ts +0 -59
- package/src/xchains/stacks/constants.ts +0 -42
- package/src/xchains/stacks/index.ts +0 -4
- package/src/xchains/stacks/useStacksXConnectors.ts +0 -7
- package/src/xchains/stellar/CustomSorobanServer.ts +0 -93
- package/src/xchains/stellar/StellarWalletsKitXConnector.ts +0 -53
- package/src/xchains/stellar/StellarXService.ts +0 -93
- package/src/xchains/stellar/actions.ts +0 -24
- package/src/xchains/stellar/index.tsx +0 -2
- package/src/xchains/stellar/useStellarXConnectors.ts +0 -21
- package/src/xchains/stellar/utils.ts +0 -49
- package/src/xchains/sui/SuiXConnector.ts +0 -28
- package/src/xchains/sui/SuiXService.ts +0 -66
- package/src/xchains/sui/index.ts +0 -2
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { XService } from '@/core/XService';
|
|
2
|
-
import type { XToken } from '@sodax/types';
|
|
3
|
-
import { NearConnector } from '@hot-labs/near-connect';
|
|
4
|
-
import { JsonRpcProvider } from 'near-api-js';
|
|
5
|
-
|
|
6
|
-
export class NearXService extends XService {
|
|
7
|
-
private static instance: NearXService;
|
|
8
|
-
|
|
9
|
-
public walletSelector: NearConnector;
|
|
10
|
-
|
|
11
|
-
private constructor() {
|
|
12
|
-
super('NEAR');
|
|
13
|
-
|
|
14
|
-
this.walletSelector = new NearConnector({
|
|
15
|
-
network: 'mainnet',
|
|
16
|
-
logger: console,
|
|
17
|
-
autoConnect: true,
|
|
18
|
-
excludedWallets: ['okx-wallet'],
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
public static getInstance(): NearXService {
|
|
23
|
-
if (!NearXService.instance) {
|
|
24
|
-
NearXService.instance = new NearXService();
|
|
25
|
-
}
|
|
26
|
-
return NearXService.instance;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async getBalance(address: string | undefined, xToken: XToken): Promise<bigint> {
|
|
30
|
-
const url = 'https://1rpc.io/near';
|
|
31
|
-
// reference: https://near.github.io/near-api-js/classes/_near-js_providers.json-rpc-provider.JsonRpcProvider.html
|
|
32
|
-
const provider = new JsonRpcProvider({ url });
|
|
33
|
-
|
|
34
|
-
// get native balance
|
|
35
|
-
if (xToken.symbol === 'NEAR') {
|
|
36
|
-
const account = await provider.viewAccount({ accountId: address ?? '' });
|
|
37
|
-
return BigInt(account.amount);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Near Fungible Token Standard(https://github.com/near/NEPs/blob/master/neps/nep-0141.md)
|
|
41
|
-
// get balance of the token
|
|
42
|
-
|
|
43
|
-
const res = await provider.callFunction<number>({ contractId: xToken.address, method: 'ft_balance_of', args: { account_id: address } });
|
|
44
|
-
return BigInt(res ?? 0);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { useXService } from '@/hooks';
|
|
2
|
-
import { type UseQueryResult, useQuery } from '@tanstack/react-query';
|
|
3
|
-
|
|
4
|
-
import { NearXConnector } from './NearXConnector';
|
|
5
|
-
import type { NearXService } from './NearXService';
|
|
6
|
-
|
|
7
|
-
export const useNearXConnectors = (): UseQueryResult<NearXConnector[] | undefined, Error | null> => {
|
|
8
|
-
const xService = useXService('NEAR') as NearXService;
|
|
9
|
-
|
|
10
|
-
return useQuery({
|
|
11
|
-
queryKey: ['near-wallets'],
|
|
12
|
-
queryFn: async () => {
|
|
13
|
-
if (!xService) {
|
|
14
|
-
return [];
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
await xService.walletSelector.whenManifestLoaded;
|
|
18
|
-
const wallets = xService.walletSelector.availableWallets;
|
|
19
|
-
|
|
20
|
-
return wallets.map(wallet => new NearXConnector(wallet));
|
|
21
|
-
},
|
|
22
|
-
});
|
|
23
|
-
};
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import type { XAccount } from '@/types';
|
|
2
|
-
|
|
3
|
-
import { XConnector } from '@/core';
|
|
4
|
-
import { SolanaXService } from './SolanaXService';
|
|
5
|
-
|
|
6
|
-
export class SolanaXConnector extends XConnector {
|
|
7
|
-
wallet: any;
|
|
8
|
-
constructor(wallet: any) {
|
|
9
|
-
super('SOLANA', wallet?.adapter.name, wallet?.adapter.name);
|
|
10
|
-
this.wallet = wallet;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
getXService(): SolanaXService {
|
|
14
|
-
return SolanaXService.getInstance();
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
async connect(): Promise<XAccount | undefined> {
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async disconnect(): Promise<void> {}
|
|
22
|
-
|
|
23
|
-
public get icon() {
|
|
24
|
-
return this.wallet?.adapter.icon;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { XService } from '@/core/XService';
|
|
2
|
-
import { isNativeToken } from '@/utils';
|
|
3
|
-
import type { XToken } from '@sodax/types';
|
|
4
|
-
import { type Connection, PublicKey } from '@solana/web3.js';
|
|
5
|
-
import { getAccount, getAssociatedTokenAddressSync } from '@solana/spl-token';
|
|
6
|
-
import type { WalletContextState } from '@solana/wallet-adapter-react';
|
|
7
|
-
|
|
8
|
-
export class SolanaXService extends XService {
|
|
9
|
-
private static instance: SolanaXService;
|
|
10
|
-
|
|
11
|
-
public connection: Connection | undefined;
|
|
12
|
-
public wallet: WalletContextState | undefined;
|
|
13
|
-
|
|
14
|
-
private constructor() {
|
|
15
|
-
super('SOLANA');
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
public static getInstance(): SolanaXService {
|
|
19
|
-
if (!SolanaXService.instance) {
|
|
20
|
-
SolanaXService.instance = new SolanaXService();
|
|
21
|
-
}
|
|
22
|
-
return SolanaXService.instance;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async getBalance(address: string | undefined, xToken: XToken): Promise<bigint> {
|
|
26
|
-
if (!address) return BigInt(0);
|
|
27
|
-
|
|
28
|
-
const connection = this.connection;
|
|
29
|
-
if (!connection) {
|
|
30
|
-
return BigInt(0);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
try {
|
|
34
|
-
if (isNativeToken(xToken)) {
|
|
35
|
-
const newBalance = await connection.getBalance(new PublicKey(address));
|
|
36
|
-
return BigInt(newBalance);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const tokenAccountPubkey = getAssociatedTokenAddressSync(new PublicKey(xToken.address), new PublicKey(address));
|
|
40
|
-
const tokenAccount = await getAccount(connection, tokenAccountPubkey);
|
|
41
|
-
return BigInt(tokenAccount.amount);
|
|
42
|
-
} catch {
|
|
43
|
-
return BigInt(0);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import type { XAccount } from '@/types';
|
|
2
|
-
import { XConnector } from '@/core';
|
|
3
|
-
import type { StacksProvider } from '@stacks/connect';
|
|
4
|
-
import { request, disconnect } from '@stacks/connect';
|
|
5
|
-
|
|
6
|
-
export interface StacksProviderConfig {
|
|
7
|
-
/** The provider ID matching the window path, e.g. 'LeatherProvider' or 'XverseProviders.BitcoinProvider' */
|
|
8
|
-
id: string;
|
|
9
|
-
name: string;
|
|
10
|
-
icon: string;
|
|
11
|
-
installUrl?: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/** Resolves a provider from `window` by dot-separated ID, matching @stacks/connect-ui's getProviderFromId */
|
|
15
|
-
function getProviderFromId(id: string): StacksProvider | undefined {
|
|
16
|
-
// biome-ignore lint/suspicious/noExplicitAny: window property traversal requires any
|
|
17
|
-
return id.split('.').reduce<any>((acc, part) => acc?.[part], window) as StacksProvider | undefined;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export class StacksXConnector extends XConnector {
|
|
21
|
-
private readonly config: StacksProviderConfig;
|
|
22
|
-
|
|
23
|
-
constructor(config: StacksProviderConfig) {
|
|
24
|
-
super('STACKS', config.name, config.id);
|
|
25
|
-
this.config = config;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async connect(): Promise<XAccount | undefined> {
|
|
29
|
-
const provider = this.getProvider();
|
|
30
|
-
|
|
31
|
-
if (!provider) {
|
|
32
|
-
if (this.config.installUrl) {
|
|
33
|
-
window.open(this.config.installUrl, '_blank');
|
|
34
|
-
}
|
|
35
|
-
return undefined;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const response = await request({ provider }, 'stx_getAddresses');
|
|
39
|
-
// @ts-ignore
|
|
40
|
-
const stxAddress = response.addresses.find(a => a.purpose === 'stacks');
|
|
41
|
-
|
|
42
|
-
if (!stxAddress) {
|
|
43
|
-
return undefined;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return {
|
|
47
|
-
address: stxAddress.address,
|
|
48
|
-
xChainType: this.xChainType,
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async disconnect(): Promise<void> {
|
|
53
|
-
disconnect();
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
public get icon(): string {
|
|
57
|
-
return this.config.icon;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
public getProvider(): StacksProvider | undefined {
|
|
61
|
-
return getProviderFromId(this.config.id);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { XService } from '@/core/XService';
|
|
2
|
-
import type { XToken } from '@sodax/types';
|
|
3
|
-
import { fetchCallReadOnlyFunction, Cl, type UIntCV, type ResponseOkCV } from '@stacks/transactions';
|
|
4
|
-
import { networkFrom, type StacksNetwork } from '@stacks/network';
|
|
5
|
-
|
|
6
|
-
export class StacksXService extends XService {
|
|
7
|
-
private static instance: StacksXService;
|
|
8
|
-
|
|
9
|
-
public network: StacksNetwork | undefined;
|
|
10
|
-
|
|
11
|
-
private constructor() {
|
|
12
|
-
super('STACKS');
|
|
13
|
-
this.network = networkFrom('mainnet');
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
public static getInstance(): StacksXService {
|
|
17
|
-
if (!StacksXService.instance) {
|
|
18
|
-
StacksXService.instance = new StacksXService();
|
|
19
|
-
}
|
|
20
|
-
return StacksXService.instance;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async getBalance(address: string | undefined, xToken: XToken): Promise<bigint> {
|
|
24
|
-
if (!address) return 0n;
|
|
25
|
-
|
|
26
|
-
// native STX balance
|
|
27
|
-
if (xToken.symbol === 'STX') {
|
|
28
|
-
const url = `${this.network?.client.baseUrl}/extended/v1/address/${address}/balances`;
|
|
29
|
-
try {
|
|
30
|
-
const response = await fetch(url);
|
|
31
|
-
if (!response.ok) {
|
|
32
|
-
throw new Error(`Error fetching data: ${response.statusText}`);
|
|
33
|
-
}
|
|
34
|
-
const data = await response.json();
|
|
35
|
-
return BigInt(data.stx.balance);
|
|
36
|
-
} catch (error) {
|
|
37
|
-
console.error('Error fetching STX balance:', error);
|
|
38
|
-
return 0n;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// SIP-010 fungible token balance via read-only contract call
|
|
43
|
-
const [contractAddress, contractName] = xToken.address.split('.');
|
|
44
|
-
try {
|
|
45
|
-
const result = (await fetchCallReadOnlyFunction({
|
|
46
|
-
contractAddress,
|
|
47
|
-
contractName,
|
|
48
|
-
functionName: 'get-balance',
|
|
49
|
-
functionArgs: [Cl.principal(address)],
|
|
50
|
-
network: this.network,
|
|
51
|
-
senderAddress: address,
|
|
52
|
-
})) as ResponseOkCV<UIntCV>;
|
|
53
|
-
return result.value.value as bigint;
|
|
54
|
-
} catch (error) {
|
|
55
|
-
console.error('Error fetching token balance:', error);
|
|
56
|
-
return 0n;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import type { StacksProviderConfig } from './StacksXConnector';
|
|
2
|
-
|
|
3
|
-
// Icons sourced from @stacks/connect DEFAULT_PROVIDERS
|
|
4
|
-
// https://github.com/stx-labs/connect/blob/main/packages/connect/src/providers.ts
|
|
5
|
-
const LEATHER_ICON =
|
|
6
|
-
'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgdmlld0JveD0iMCAwIDEyOCAxMjgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiByeD0iMjYuODM4NyIgZmlsbD0iIzEyMTAwRiIvPgo8cGF0aCBkPSJNNzQuOTE3MSA1Mi43MTE0QzgyLjQ3NjYgNTEuNTQwOCA5My40MDg3IDQzLjU4MDQgOTMuNDA4NyAzNy4zNzYxQzkzLjQwODcgMzUuNTAzMSA5MS44OTY4IDM0LjIxNTQgODkuNjg3MSAzNC4yMTU0Qzg1LjUwMDQgMzQuMjE1NCA3OC40MDYxIDQwLjUzNjggNzQuOTE3MSA1Mi43MTE0Wk0zOS45MTEgODMuNDk5MUMzMC4wMjU2IDgzLjQ5OTEgMjkuMjExNSA5My4zMzI0IDM5LjA5NjkgOTMuMzMyNEM0My41MTYzIDkzLjMzMjQgNDguODY2MSA5MS41NzY0IDUxLjY1NzMgODguNDE1N0M0Ny41ODY4IDg0LjkwMzggNDQuMjE0MSA4My40OTkxIDM5LjkxMSA4My40OTkxWk0xMDIuODI5IDc5LjI4NDhDMTAzLjQxIDk1Ljc5MDcgOTUuMDM2OSAxMDUuMDM5IDgwLjg0ODQgMTA1LjAzOUM3Mi40NzQ4IDEwNS4wMzkgNjguMjg4MSAxMDEuODc4IDU5LjMzMyA5Ni4wMjQ5QzU0LjY4MSAxMDEuMTc2IDQ1Ljg0MjMgMTA1LjAzOSAzOC41MTU0IDEwNS4wMzlDMTMuMjc4NSAxMDUuMDM5IDE0LjMyNTIgNzIuODQ2MyA0MC4wMjczIDcyLjg0NjNDNDUuMzc3MSA3Mi44NDYzIDQ5LjkxMjggNzQuMjUxMSA1NS43Mjc3IDc3Ljg4TDU5LjU2NTYgNjQuNDE3N0M0My43NDg5IDYwLjA4NjQgMzUuODQwNSA0Ny45MTE4IDQzLjYzMjYgMzAuNDY5M0g1Ni4xOTI5QzQ5LjIxNSA0Mi4wNTg2IDUzLjk4MzIgNTEuNjU3OCA2Mi44MjIgNTIuNzExNEM2Ny41OTAzIDM1LjczNzIgNzcuODI0NiAyMi41MDkgOTEuNDMxNiAyMi41MDlDOTkuMTA3NCAyMi41MDkgMTA1LjE1NSAyNy41NDI4IDEwNS4xNTUgMzYuNjczN0MxMDUuMTU1IDUxLjMwNjYgODYuMDgxOSA2My4yNDcxIDcxLjY2MDcgNjQuNDE3N0w2NS43Mjk1IDg1LjM3MjFDNzIuNDc0OCA5My4yMTUzIDkxLjE5OSAxMDAuODI0IDkxLjE5OSA3OS4yODQ4SDEwMi44MjlaIiBmaWxsPSIjRjVGMUVEIi8+Cjwvc3ZnPgo=';
|
|
7
|
-
|
|
8
|
-
const XVERSE_ICON =
|
|
9
|
-
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2MDAiIGhlaWdodD0iNjAwIj48ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGZpbGw9IiMxNzE3MTciIGQ9Ik0wIDBoNjAwdjYwMEgweiIvPjxwYXRoIGZpbGw9IiNGRkYiIGZpbGwtcnVsZT0ibm9uemVybyIgZD0iTTQ0MCA0MzUuNHYtNTFjMC0yLS44LTMuOS0yLjItNS4zTDIyMCAxNjIuMmE3LjYgNy42IDAgMCAwLTUuNC0yLjJoLTUxLjFjLTIuNSAwLTQuNiAyLTQuNiA0LjZ2NDcuM2MwIDIgLjggNCAyLjIgNS40bDc4LjIgNzcuOGE0LjYgNC42IDAgMCAxIDAgNi41bC03OSA3OC43Yy0xIC45LTEuNCAyLTEuNCAzLjJ2NTJjMCAyLjQgMiA0LjUgNC42IDQuNUgyNDljMi42IDAgNC42LTIgNC42LTQuNlY0MDVjMC0xLjIuNS0yLjQgMS40LTMuM2w0Mi40LTQyLjJhNC42IDQuNiAwIDAgMSA2LjQgMGw3OC43IDc4LjRhNy42IDcuNiAwIDAgMCA1LjQgMi4yaDQ3LjVjMi41IDAgNC42LTIgNC42LTQuNloiLz48cGF0aCBmaWxsPSIjRUU3QTMwIiBmaWxsLXJ1bGU9Im5vbnplcm8iIGQ9Ik0zMjUuNiAyMjcuMmg0Mi44YzIuNiAwIDQuNiAyLjEgNC42IDQuNnY0Mi42YzAgNCA1IDYuMSA4IDMuMmw1OC43LTU4LjVjLjgtLjggMS4zLTIgMS4zLTMuMnYtNTEuMmMwLTIuNi0yLTQuNi00LjYtNC42TDM4NCAxNjBjLTEuMiAwLTIuNC41LTMuMyAxLjNsLTU4LjQgNTguMWE0LjYgNC42IDAgMCAwIDMuMiA3LjhaIi8+PC9nPjwvc3ZnPg==';
|
|
10
|
-
|
|
11
|
-
const ASIGNA_ICON =
|
|
12
|
-
'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iIzAwMDEwMCIgZD0iTTAgMGgzMnYzMkgweiIvPjxwYXRoIGZpbGw9InVybCgjYSkiIGQ9Ik0xNS4xMSA1LjU1YTMgMyAwIDAgMC0xLjgyIDEuM2wtLjA1LjA4LS40My43Mi0uMDcuMTEtLjUuODUtLjA1LjA5LTEuMjkgMi4xOC0uMDQuMDctLjQ3LjgtLjA2LjEtLjQ2Ljc4LS4wNy4xMS0xLjYzIDIuNzYtLjA3LjExLS4zOC42Ni0uMDUuMDgtLjczIDEuMjQtLjM1LjYtLjQuNjctLjA1LjA5TDUuMSAyMC43bC0uMTEuMTgtLjE0LjIzLS4wNy4xMy0uMzMuNTUtLjA0LjA3di4wMWExLjI2IDEuMjYgMCAwIDAtLjE0LjQ3IDEuMzEgMS4zMSAwIDAgMCAxLjI0IDEuNGgxLjVsLjA1LS4wNi4wNC0uMDYuODctMS4yMS4wNS0uMDguNzctMS4wNy4wNS0uMDcuNC0uNTcuMDUtLjA2LjI0LS4zNGExLjUyIDEuNTIgMCAwIDEgMS4zOS0uNjIgMS41IDEuNSAwIDAgMSAuNjQuMiAxLjQ3IDEuNDcgMCAwIDEgLjczIDEuMjcgMS40NCAxLjQ0IDAgMCAxLS4yNy44NGwtLjYzLjg4LS4wNS4wNy0uMzIuNDUtLjA2LjA4LS4wOC4xMi0uMTIuMTYtLjA1LjA4aDIuMTNhMi4zMiAyLjMyIDAgMCAwIDEuNzctLjk2bDEuMTgtMS42My43Ny0xLjA4IDEuMy0xLjhhMS4yNCAxLjI0IDAgMCAxIC41NS0uNDNsLjA4LS4wM2ExLjMgMS4zIDAgMCAxIC4zLS4wNiAxLjI4IDEuMjggMCAwIDEgMS4xNS41NGwuMTEuMmExLjEzIDEuMTMgMCAwIDEgLjEuNDEgMS4xOSAxLjE5IDAgMCAxLS4yMy43N2wtLjAzLjA1LS41Ny44LS43Ljk4LS4yNy4zN2ExLjIyIDEuMjIgMCAwIDAtLjIuNSAxLjA1IDEuMDUgMCAwIDAtLjAyLjIzdi4wNmExLjE3IDEuMTcgMCAwIDAgLjE0LjQzbC4wMi4wNS4wNy4xYTEuNDQgMS40NCAwIDAgMCAuMS4xMWwuMDUuMDYuMDEuMDFhMS44IDEuOCAwIDAgMCAuMTQuMWMwIC4wMi4wMi4wMy4wNC4wM2ExIDEgMCAwIDAgLjA4LjA1bC4wNy4wNGExLjI1IDEuMjUgMCAwIDAgLjUuMWg2LjljLjEgMCAuMi0uMDEuMjktLjAzbC4wNi0uMDJhMS4yNyAxLjI3IDAgMCAwIC4yNy0uMS41Ny41NyAwIDAgMCAuMDctLjAzIDEuMjEgMS4yMSAwIDAgMCAuMjYtLjE5bC4wOC0uMDdhLjkyLjkyIDAgMCAwIC4xNS0uMTkgMS41NSAxLjU1IDAgMCAwIC4wOS0uMTdsLjAyLS4wNWExLjIyIDEuMjIgMCAwIDAgLjA4LS4yNnYtLjA0bC4wMi0uMDh2LS4wOGExLjMyIDEuMzIgMCAwIDAtLjItLjc0bC0xLjYtMi42NC0uMDYtLjEtLjItLjMyLS4zMy0uNTR2LS4wMWwtLjA1LS4wOC0xLjMtMi4xNS0uMDctLjEtLjA0LS4wNi0uOC0xLjMyLS4wNC0uMDctLjItLjM0LS4xLS4xNC0uMS0uMTYtLjUzLS45LS4xMy0uMi0uMDktLjE0LTIuMTctMy41Ny0uMDQtLjA3LS43Mi0xLjE5LS4wNS0uMDctLjQtLjY1YTIuNjUgMi42NSAwIDAgMC0uMy0uNCAyLjk2IDIuOTYgMCAwIDAtLjk3LS43NCAzLjA0IDMuMDQgMCAwIDAtMS4zLS4zYy0uMjUgMC0uNS4wNC0uNzQuMVoiLz48cGF0aCBmaWxsPSJ1cmwoI2IpIiBkPSJNMTkgMTYuM2E1LjQ1IDUuNDUgMCAwIDAtLjgzIDEuNTZsLS4wNC4xNWExLjM2IDEuMzYgMCAwIDEgLjI4LS4xNiAxLjI0IDEuMjQgMCAwIDEgLjM4LS4wOGguMWExLjI4IDEuMjggMCAwIDEgMS4wNS41NGMuMDQuMDYuMDguMTMuMS4yYTEuMjQgMS4yNCAwIDAgMSAuMDkuMjcgMS4xOSAxLjE5IDAgMCAxLS4yLjkxbC0uMDQuMDUtLjU3Ljc5LS43Ljk5LS4yNy4zN2ExLjIzIDEuMjMgMCAwIDAtLjIuNDIgMS4wNiAxLjA2IDAgMCAwLS4wMi4zMXYuMDZhMS4xNyAxLjE3IDAgMCAwIC4xNi40Ny45My45MyAwIDAgMCAuMDcuMSAxLjUgMS41IDAgMCAwIC4xLjEybC4wNS4wNmguMDFhMS45NCAxLjk0IDAgMCAwIC4wOS4wOCAxIDEgMCAwIDAgLjE3LjFsLjA3LjA0YTEuMjUgMS4yNSAwIDAgMCAuNS4xaDYuOWMuMSAwIC4yIDAgLjI4LS4wMmwuMDctLjAyYTEuMzIgMS4zMiAwIDAgMCAuMzQtLjEzbC4xNi0uMS4wMy0uMDNhMS4yOSAxLjI5IDAgMCAwIC4yLS4yIDIuNDMgMi40MyAwIDAgMCAuMTItLjE3Yy4wMy0uMDMuMDUtLjA4LjA3LS4xMmwuMDItLjA1YTEuMjEgMS4yMSAwIDAgMCAuMDktLjN2LS4wOGwuMDEtLjA5YTEuMzIgMS4zMiAwIDAgMC0uMi0uNzNsLTEuNi0yLjY0LS4wNi0uMS0uMi0uMzItLjMzLS41NHYtLjAybC0uMDUtLjA3LTEuMy0yLjE1LS4xMi0uMDctLjA3LS4wNGE0Ljk0IDQuOTQgMCAwIDAtMi40Ni0uNjdjLTEuMDMgMC0xLjc2LjU3LTIuMjYgMS4yWiIvPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0xMi4yOSAyMS4wOGMwIC4yOS0uMDkuNTgtLjI3Ljg0bC0xLjMxIDEuODRIN2wyLjUyLTMuNTNhMS41NCAxLjU0IDAgMCAxIDIuMS0uMzZjLjQzLjI4LjY2Ljc0LjY2IDEuMloiLz48cGF0aCBmaWxsPSIjMDAwIiBkPSJNMTEuMTYgMjEuMjVhLjU2LjU2IDAgMCAxLS41Ny41NS41Ni41NiAwIDAgMS0uNTctLjU2LjU2LjU2IDAgMCAxIC41Ny0uNTUuNTYuNTYgMCAwIDEgLjU3LjU2WiIvPjxkZWZzPjxsaW5lYXJHcmFkaWVudCBpZD0iYSIgeDE9IjE1LjIzIiB4Mj0iMTkuMyIgeTE9IjI1Ljc4IiB5Mj0iNi4xMSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIHN0b3AtY29sb3I9IiM2NTIyRjQiLz48c3RvcCBvZmZzZXQ9Ii41NSIgc3RvcC1jb2xvcj0iIzlCNkJGRiIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI0E1ODVGRiIvPjwvbGluZWFyR3JhZGllbnQ+PGxpbmVhckdyYWRpZW50IGlkPSJiIiB4MT0iMjIuNTkiIHgyPSIyNC44IiB5MT0iMjQuNzEiIHkyPSIxNS41MyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIHN0b3AtY29sb3I9IiM0MjFGOEIiLz48c3RvcCBvZmZzZXQ9Ii41NSIgc3RvcC1jb2xvcj0iIzcyMzBGRiIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzk3NzNGRiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjwvc3ZnPg==';
|
|
13
|
-
|
|
14
|
-
const FORDEFI_ICON =
|
|
15
|
-
'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDIiIGhlaWdodD0iNDIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZmlsbD0iIzEwMTExNCIgZD0iTTAgMGg0MnY0MkgweiIvPgogIDxwYXRoIGQ9Ik0xOS40NyAyNi44OUg1djMuNTdhNC41NyA0LjU3IDAgMCAwIDQuNTggNC41N2g1LjgzbDQuMDYtOC4xNFoiIGZpbGw9IiM3OTk0RkYiLz4KICA8cGF0aCBkPSJNNSAxNy40aDI3LjU4bC0zLjIgNi43OEg1VjE3LjRaIiBmaWxsPSIjNDg2REZGIi8+CiAgPHBhdGggZD0iTTE0LjY3IDdINXY3LjY4aDMzVjdoLTkuNjd2NS43NGgtMlY3aC05LjY3djUuNzRoLTEuOTlWN1oiIGZpbGw9IiM1Q0QxRkEiLz4KPC9zdmc+Cg==';
|
|
16
|
-
|
|
17
|
-
export const STACKS_PROVIDERS: StacksProviderConfig[] = [
|
|
18
|
-
{
|
|
19
|
-
id: 'LeatherProvider',
|
|
20
|
-
name: 'Leather',
|
|
21
|
-
icon: LEATHER_ICON,
|
|
22
|
-
installUrl: 'https://chrome.google.com/webstore/detail/hiro-wallet/ldinpeekobnhjjdofggfgjlcehhmanlj',
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
id: 'XverseProviders.BitcoinProvider',
|
|
26
|
-
name: 'Xverse Wallet',
|
|
27
|
-
icon: XVERSE_ICON,
|
|
28
|
-
installUrl: 'https://chrome.google.com/webstore/detail/xverse-wallet/idnnbdplmphpflfnlkomgpfbpcgelopg',
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
id: 'AsignaProvider',
|
|
32
|
-
name: 'Asigna Multisig',
|
|
33
|
-
icon: ASIGNA_ICON,
|
|
34
|
-
installUrl: 'https://stx.asigna.io/',
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
id: 'FordefiProviders.UtxoProvider',
|
|
38
|
-
name: 'Fordefi',
|
|
39
|
-
icon: FORDEFI_ICON,
|
|
40
|
-
installUrl: 'https://chromewebstore.google.com/detail/fordefi/hcmehenccjdmfbojapcbcofkgdpbnlle',
|
|
41
|
-
},
|
|
42
|
-
];
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
|
-
import { StacksXConnector } from './StacksXConnector';
|
|
3
|
-
import { STACKS_PROVIDERS } from './constants';
|
|
4
|
-
|
|
5
|
-
export function useStacksXConnectors(): StacksXConnector[] {
|
|
6
|
-
return useMemo(() => STACKS_PROVIDERS.map(config => new StacksXConnector(config)), []);
|
|
7
|
-
}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type FeeBumpTransaction,
|
|
3
|
-
type Memo,
|
|
4
|
-
type MemoType,
|
|
5
|
-
type Operation,
|
|
6
|
-
SorobanRpc,
|
|
7
|
-
type Transaction,
|
|
8
|
-
} from '@stellar/stellar-sdk';
|
|
9
|
-
|
|
10
|
-
class CustomSorobanServer extends SorobanRpc.Server {
|
|
11
|
-
private readonly customHeaders: Record<string, string>;
|
|
12
|
-
|
|
13
|
-
constructor(serverUrl: string, customHeaders: Record<string, string>) {
|
|
14
|
-
super(serverUrl, {
|
|
15
|
-
allowHttp: true,
|
|
16
|
-
});
|
|
17
|
-
this.customHeaders = customHeaders;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async simulateTransaction(
|
|
21
|
-
tx: Transaction<Memo<MemoType>, Operation[]>,
|
|
22
|
-
): Promise<SorobanRpc.Api.SimulateTransactionResponse> {
|
|
23
|
-
const requestOptions = {
|
|
24
|
-
method: 'POST',
|
|
25
|
-
headers: {
|
|
26
|
-
'Content-Type': 'application/json',
|
|
27
|
-
...this.customHeaders,
|
|
28
|
-
},
|
|
29
|
-
body: JSON.stringify({
|
|
30
|
-
id: 1,
|
|
31
|
-
jsonrpc: '2.0',
|
|
32
|
-
method: 'simulateTransaction',
|
|
33
|
-
params: {
|
|
34
|
-
transaction: tx.toXDR(),
|
|
35
|
-
},
|
|
36
|
-
}),
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const response = await fetch(`${this.serverURL}`, requestOptions);
|
|
40
|
-
if (!response.ok) {
|
|
41
|
-
throw new Error(`HTTP error simulating TX! status: ${response.status}`);
|
|
42
|
-
}
|
|
43
|
-
return response.json().then(json => json.result);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async sendTransaction(tx: Transaction | FeeBumpTransaction): Promise<SorobanRpc.Api.SendTransactionResponse> {
|
|
47
|
-
const requestOptions = {
|
|
48
|
-
method: 'POST',
|
|
49
|
-
headers: {
|
|
50
|
-
'Content-Type': 'application/json',
|
|
51
|
-
...this.customHeaders,
|
|
52
|
-
},
|
|
53
|
-
body: JSON.stringify({
|
|
54
|
-
id: 1,
|
|
55
|
-
jsonrpc: '2.0',
|
|
56
|
-
method: 'sendTransaction',
|
|
57
|
-
params: {
|
|
58
|
-
transaction: tx.toXDR(),
|
|
59
|
-
},
|
|
60
|
-
}),
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
const response = await fetch(`${this.serverURL}`, requestOptions);
|
|
64
|
-
if (!response.ok) {
|
|
65
|
-
throw new Error(`HTTP error submitting TX! status: ${response.status}`);
|
|
66
|
-
}
|
|
67
|
-
return response.json().then(json => json.result);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
async getTransaction(hash: string): Promise<SorobanRpc.Api.GetTransactionResponse> {
|
|
71
|
-
const requestOptions = {
|
|
72
|
-
method: 'POST',
|
|
73
|
-
headers: {
|
|
74
|
-
'Content-Type': 'application/json',
|
|
75
|
-
...this.customHeaders,
|
|
76
|
-
},
|
|
77
|
-
body: JSON.stringify({
|
|
78
|
-
id: 1,
|
|
79
|
-
jsonrpc: '2.0',
|
|
80
|
-
method: 'getTransaction',
|
|
81
|
-
params: { hash },
|
|
82
|
-
}),
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
const response = await fetch(`${this.serverURL}`, requestOptions);
|
|
86
|
-
if (!response.ok) {
|
|
87
|
-
throw new Error(`HTTP error getting TX! status: ${response.status}`);
|
|
88
|
-
}
|
|
89
|
-
return response.json().then(json => json.result);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export default CustomSorobanServer;
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import type { XAccount } from '@/types';
|
|
2
|
-
|
|
3
|
-
import { XConnector } from '@/core';
|
|
4
|
-
import { StellarXService } from './StellarXService';
|
|
5
|
-
|
|
6
|
-
export type StellarWalletType = {
|
|
7
|
-
icon: string;
|
|
8
|
-
id: string;
|
|
9
|
-
isAvailable: boolean;
|
|
10
|
-
name: string;
|
|
11
|
-
type: string;
|
|
12
|
-
url: string;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export class StellarWalletsKitXConnector extends XConnector {
|
|
16
|
-
_wallet: StellarWalletType;
|
|
17
|
-
|
|
18
|
-
constructor(wallet: StellarWalletType) {
|
|
19
|
-
super('STELLAR', wallet.name, wallet.id);
|
|
20
|
-
this._wallet = wallet;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
getXService(): StellarXService {
|
|
24
|
-
return StellarXService.getInstance();
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
async connect(): Promise<XAccount | undefined> {
|
|
28
|
-
const kit = this.getXService().walletsKit;
|
|
29
|
-
|
|
30
|
-
if (!this._wallet) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (!this._wallet.isAvailable && this._wallet.url) {
|
|
35
|
-
window.open(this._wallet.url, '_blank');
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
kit.setWallet(this._wallet.id);
|
|
40
|
-
const { address } = await kit.getAddress();
|
|
41
|
-
|
|
42
|
-
return {
|
|
43
|
-
address: address,
|
|
44
|
-
xChainType: this.xChainType,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async disconnect(): Promise<void> {}
|
|
49
|
-
|
|
50
|
-
public get icon() {
|
|
51
|
-
return this._wallet.icon;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { XService } from '@/core/XService';
|
|
2
|
-
import { StellarWalletsKit, WalletNetwork, allowAllModules } from '@creit.tech/stellar-wallets-kit';
|
|
3
|
-
import * as StellarSdk from '@stellar/stellar-sdk';
|
|
4
|
-
import CustomSorobanServer from './CustomSorobanServer';
|
|
5
|
-
import { getTokenBalance } from './utils';
|
|
6
|
-
import type { XToken } from '@sodax/types';
|
|
7
|
-
|
|
8
|
-
/** Base reserve in stroops (0.5 XLM). Each subentry (trustline, signer, data entry, offer) adds one base reserve. */
|
|
9
|
-
const STELLAR_BASE_RESERVE_STROOPS = 5_000_000;
|
|
10
|
-
|
|
11
|
-
/** Horizon account fields used for minimum balance. Minimum = (2 + subentry_count + num_sponsoring - num_sponsored) * base_reserve + selling_liabilities. */
|
|
12
|
-
interface StellarAccountReserveFields {
|
|
13
|
-
subentry_count?: number;
|
|
14
|
-
num_sponsoring?: number;
|
|
15
|
-
num_sponsored?: number;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/** Parse XLM balance string (e.g. "198.8944970") to stroops (1 XLM = 10^7 stroops). */
|
|
19
|
-
function parseXlmBalanceToStroops(balanceStr: string): bigint {
|
|
20
|
-
const parts = balanceStr.split('.');
|
|
21
|
-
const whole = parts[0] ?? '0';
|
|
22
|
-
const frac = (parts[1] ?? '').padEnd(7, '0').slice(0, 7);
|
|
23
|
-
return BigInt(whole + frac);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export class StellarXService extends XService {
|
|
27
|
-
private static instance: StellarXService;
|
|
28
|
-
|
|
29
|
-
public walletsKit: StellarWalletsKit;
|
|
30
|
-
public server: StellarSdk.Horizon.Server;
|
|
31
|
-
public sorobanServer: CustomSorobanServer;
|
|
32
|
-
|
|
33
|
-
private constructor() {
|
|
34
|
-
super('STELLAR');
|
|
35
|
-
|
|
36
|
-
this.walletsKit = new StellarWalletsKit({
|
|
37
|
-
network: WalletNetwork.PUBLIC,
|
|
38
|
-
modules: allowAllModules(),
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
this.server = new StellarSdk.Horizon.Server('https://horizon.stellar.org', { allowHttp: true });
|
|
42
|
-
this.sorobanServer = new CustomSorobanServer('https://rpc.ankr.com/stellar_soroban', {});
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
public static getInstance(): StellarXService {
|
|
46
|
-
if (!StellarXService.instance) {
|
|
47
|
-
StellarXService.instance = new StellarXService();
|
|
48
|
-
}
|
|
49
|
-
return StellarXService.instance;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async getBalance(address: string | undefined, xToken: XToken): Promise<bigint> {
|
|
53
|
-
if (!address) return BigInt(0);
|
|
54
|
-
|
|
55
|
-
const stellarAccount = await this.server.loadAccount(address);
|
|
56
|
-
|
|
57
|
-
if (xToken.symbol === 'XLM') {
|
|
58
|
-
const xlmBalance = stellarAccount.balances.find(balance => balance.asset_type === 'native');
|
|
59
|
-
if (xlmBalance) {
|
|
60
|
-
const rawBalanceStroops = parseXlmBalanceToStroops(xlmBalance.balance);
|
|
61
|
-
const sellingLiabilitiesStroops = (xlmBalance as { selling_liabilities?: string }).selling_liabilities
|
|
62
|
-
? parseXlmBalanceToStroops((xlmBalance as { selling_liabilities: string }).selling_liabilities)
|
|
63
|
-
: BigInt(0);
|
|
64
|
-
const reserveFields = stellarAccount as unknown as StellarAccountReserveFields;
|
|
65
|
-
const subentryCount = reserveFields.subentry_count ?? 0;
|
|
66
|
-
const numSponsoring = reserveFields.num_sponsoring ?? 0;
|
|
67
|
-
const numSponsored = reserveFields.num_sponsored ?? 0;
|
|
68
|
-
// Minimum balance = (2 + subentry_count + num_sponsoring - num_sponsored) * base_reserve + selling_liabilities.
|
|
69
|
-
// When account has sponsored reserves (num_sponsored > 0), those reserves are paid by the sponsor, so we don't subtract them.
|
|
70
|
-
const reserveCount = Math.max(0, 2 + subentryCount + numSponsoring - numSponsored);
|
|
71
|
-
const minBalanceStroops =
|
|
72
|
-
BigInt(reserveCount) * BigInt(STELLAR_BASE_RESERVE_STROOPS) + sellingLiabilitiesStroops;
|
|
73
|
-
const availableStroops =
|
|
74
|
-
rawBalanceStroops > minBalanceStroops ? rawBalanceStroops - minBalanceStroops : BigInt(0);
|
|
75
|
-
return availableStroops;
|
|
76
|
-
}
|
|
77
|
-
} else {
|
|
78
|
-
try {
|
|
79
|
-
const txBuilder = new StellarSdk.TransactionBuilder(stellarAccount, {
|
|
80
|
-
fee: StellarSdk.BASE_FEE,
|
|
81
|
-
networkPassphrase: StellarSdk.Networks.PUBLIC,
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
const balance = await getTokenBalance(address, xToken.address, txBuilder, this.sorobanServer);
|
|
85
|
-
return balance;
|
|
86
|
-
} catch (e) {
|
|
87
|
-
console.error(`Error while fetching token on Stellar: ${xToken.symbol}, Error: ${e}`);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return BigInt(0);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { useXWagmiStore } from '@/useXWagmiStore';
|
|
2
|
-
import { StellarXService } from './StellarXService';
|
|
3
|
-
|
|
4
|
-
export const reconnectStellar = async () => {
|
|
5
|
-
const stellarConnection = useXWagmiStore.getState().xConnections.STELLAR;
|
|
6
|
-
if (!stellarConnection) return;
|
|
7
|
-
|
|
8
|
-
const recentXConnectorId = stellarConnection.xConnectorId;
|
|
9
|
-
const stellarWalletKit = StellarXService.getInstance().walletsKit;
|
|
10
|
-
stellarWalletKit.setWallet(recentXConnectorId);
|
|
11
|
-
const { address } = await stellarWalletKit.getAddress();
|
|
12
|
-
useXWagmiStore.setState({
|
|
13
|
-
xConnections: {
|
|
14
|
-
...useXWagmiStore.getState().xConnections,
|
|
15
|
-
STELLAR: {
|
|
16
|
-
xAccount: {
|
|
17
|
-
address,
|
|
18
|
-
xChainType: 'STELLAR',
|
|
19
|
-
},
|
|
20
|
-
xConnectorId: recentXConnectorId,
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
});
|
|
24
|
-
};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { useXService } from '@/hooks';
|
|
2
|
-
import { type UseQueryResult, useQuery } from '@tanstack/react-query';
|
|
3
|
-
|
|
4
|
-
import { StellarWalletsKitXConnector, type StellarXService } from '.';
|
|
5
|
-
|
|
6
|
-
export const useStellarXConnectors = (): UseQueryResult<StellarWalletsKitXConnector[] | undefined, Error | null> => {
|
|
7
|
-
const xService = useXService('STELLAR') as StellarXService;
|
|
8
|
-
|
|
9
|
-
return useQuery({
|
|
10
|
-
queryKey: ['stellar-wallets', xService],
|
|
11
|
-
queryFn: async () => {
|
|
12
|
-
if (!xService) {
|
|
13
|
-
return [];
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const wallets = await xService.walletsKit.getSupportedWallets();
|
|
17
|
-
|
|
18
|
-
return wallets.filter(wallet => wallet.isAvailable).map(wallet => new StellarWalletsKitXConnector(wallet));
|
|
19
|
-
},
|
|
20
|
-
});
|
|
21
|
-
};
|