@sodax/wallet-sdk-react 1.5.7-beta → 2.0.0-rc.10
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 +107 -142
- package/dist/XConnector-12q0OVe5.d.ts +146 -0
- package/dist/chunk-7V7O3Q7Y.mjs +62 -0
- package/dist/chunk-C6M34IVL.mjs +86 -0
- package/dist/chunk-DQTYAMKF.mjs +1609 -0
- package/dist/chunk-FSOGMSJH.mjs +39 -0
- package/dist/chunk-IFXZQW4C.mjs +98 -0
- package/dist/chunk-JQ4H4GJ5.mjs +100 -0
- package/dist/chunk-LKSSME2J.mjs +31 -0
- package/dist/chunk-MWWVB7TD.mjs +123 -0
- package/dist/chunk-NAKCAL2M.mjs +32 -0
- package/dist/chunk-OPYSVPRW.mjs +144 -0
- package/dist/chunk-QMXBY3UI.mjs +1 -0
- package/dist/chunk-TACW7Z4D.mjs +31 -0
- package/dist/chunk-WPZOLGVB.mjs +148 -0
- package/dist/chunk-X7BHR7WS.mjs +200 -0
- package/dist/chunk-Z5GXDHGL.mjs +190 -0
- package/dist/config-DEsqgrG1.d.ts +151 -0
- package/dist/index.d.ts +768 -1498
- package/dist/index.mjs +453 -2005
- package/dist/xchains/bitcoin/index.d.ts +125 -0
- package/dist/xchains/bitcoin/index.mjs +14 -0
- package/dist/xchains/evm/index.d.ts +39 -0
- package/dist/xchains/evm/index.mjs +3 -0
- package/dist/xchains/icon/index.d.ts +37 -0
- package/dist/xchains/icon/index.mjs +5 -0
- package/dist/xchains/injective/index.d.ts +35 -0
- package/dist/xchains/injective/index.mjs +3 -0
- package/dist/xchains/near/index.d.ts +34 -0
- package/dist/xchains/near/index.mjs +4 -0
- package/dist/xchains/solana/index.d.ts +26 -0
- package/dist/xchains/solana/index.mjs +5 -0
- package/dist/xchains/stacks/index.d.ts +42 -0
- package/dist/xchains/stacks/index.mjs +3 -0
- package/dist/xchains/stellar/index.d.ts +44 -0
- package/dist/xchains/stellar/index.mjs +4 -0
- package/dist/xchains/sui/index.d.ts +37 -0
- package/dist/xchains/sui/index.mjs +5 -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 +218 -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 +56 -22
- package/dist/index.cjs +0 -2147
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -1579
- package/dist/index.mjs.map +0 -1
- 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,117 +0,0 @@
|
|
|
1
|
-
import type { XAccount } from '@/types';
|
|
2
|
-
import { detectBitcoinAddressType, type IBitcoinWalletProvider, type AddressType } from '@sodax/types';
|
|
3
|
-
import { BitcoinXConnector } from './BitcoinXConnector';
|
|
4
|
-
|
|
5
|
-
// Minimal Unisat window API types
|
|
6
|
-
interface UnisatWallet {
|
|
7
|
-
getAccounts(): Promise<string[]>;
|
|
8
|
-
getPublicKey(): Promise<string>;
|
|
9
|
-
signPsbt(psbtHex: string, options?: { autoFinalized?: boolean }): Promise<string>;
|
|
10
|
-
signMessage(message: string, type?: 'bip322-simple' | 'ecdsa'): Promise<string>;
|
|
11
|
-
requestAccounts(): Promise<string[]>;
|
|
12
|
-
sendBitcoin(address: string, satoshis: number): Promise<string>;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
declare global {
|
|
16
|
-
interface Window {
|
|
17
|
-
unisat?: UnisatWallet;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
class UnisatWalletProvider implements IBitcoinWalletProvider {
|
|
22
|
-
private unisat: UnisatWallet;
|
|
23
|
-
private cachedAddress: string;
|
|
24
|
-
|
|
25
|
-
constructor(unisat: UnisatWallet, address: string) {
|
|
26
|
-
this.unisat = unisat;
|
|
27
|
-
this.cachedAddress = address;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async getWalletAddress(): Promise<string> {
|
|
31
|
-
try {
|
|
32
|
-
const accounts = await this.unisat.getAccounts();
|
|
33
|
-
if (accounts[0]) this.cachedAddress = accounts[0];
|
|
34
|
-
} catch {
|
|
35
|
-
// wallet locked — fall through to cached address
|
|
36
|
-
}
|
|
37
|
-
return this.cachedAddress;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async getPublicKey(): Promise<string> {
|
|
41
|
-
return this.unisat.getPublicKey();
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async getAddressType(_address: string): Promise<AddressType> {
|
|
45
|
-
const address = await this.getWalletAddress();
|
|
46
|
-
return detectBitcoinAddressType(address);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async signTransaction(psbtBase64: string, finalize = false): Promise<string> {
|
|
50
|
-
// Convert base64 → hex for Unisat, then back
|
|
51
|
-
const psbtHex = Buffer.from(psbtBase64, 'base64').toString('hex');
|
|
52
|
-
const signedHex = await this.unisat.signPsbt(psbtHex, { autoFinalized: finalize });
|
|
53
|
-
// Return as hex (BTCWalletProvider.signTransaction expects this)
|
|
54
|
-
return signedHex;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
async signEcdsaMessage(message: string): Promise<string> {
|
|
58
|
-
return this.unisat.signMessage(message, 'ecdsa');
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async signBip322Message(message: string): Promise<string> {
|
|
62
|
-
return this.unisat.signMessage(message, 'bip322-simple');
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async sendBitcoin(toAddress: string, satoshis: bigint): Promise<string> {
|
|
66
|
-
if (satoshis > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
67
|
-
throw new Error(`Amount ${satoshis} satoshis exceeds safe integer range`);
|
|
68
|
-
}
|
|
69
|
-
return this.unisat.sendBitcoin(toAddress, Number(satoshis));
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export class UnisatXConnector extends BitcoinXConnector {
|
|
74
|
-
private walletProvider: UnisatWalletProvider | undefined;
|
|
75
|
-
|
|
76
|
-
constructor() {
|
|
77
|
-
super('Unisat', 'unisat');
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
public static isAvailable(): boolean {
|
|
81
|
-
return typeof window !== 'undefined' && !!window.unisat;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
public get icon(): string {
|
|
85
|
-
return 'https://avatars.githubusercontent.com/u/125119198?s=200&v=4';
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
async connect(): Promise<XAccount | undefined> {
|
|
89
|
-
if (!window.unisat) {
|
|
90
|
-
throw new Error('Unisat wallet is not installed');
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const accounts = await window.unisat.requestAccounts();
|
|
94
|
-
const address = accounts[0];
|
|
95
|
-
if (!address) return undefined;
|
|
96
|
-
|
|
97
|
-
this.walletProvider = new UnisatWalletProvider(window.unisat, address);
|
|
98
|
-
|
|
99
|
-
return {
|
|
100
|
-
address,
|
|
101
|
-
xChainType: 'BITCOIN',
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
async disconnect(): Promise<void> {
|
|
106
|
-
this.walletProvider = undefined;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
getWalletProvider(): IBitcoinWalletProvider | undefined {
|
|
110
|
-
return this.walletProvider;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
recreateWalletProvider(xAccount: XAccount): IBitcoinWalletProvider | undefined {
|
|
114
|
-
if (!window.unisat || !xAccount.address) return undefined;
|
|
115
|
-
return new UnisatWalletProvider(window.unisat, xAccount.address);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
import type { XAccount } from '@/types';
|
|
2
|
-
import { detectBitcoinAddressType, type IBitcoinWalletProvider, type AddressType, type BtcWalletAddressType } from '@sodax/types';
|
|
3
|
-
import { AddressPurpose, MessageSigningProtocols } from 'sats-connect';
|
|
4
|
-
import { BitcoinXConnector } from './BitcoinXConnector';
|
|
5
|
-
|
|
6
|
-
// sats-connect types
|
|
7
|
-
interface SignPsbtResult {
|
|
8
|
-
psbt: string; // base64 signed PSBT
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
interface GetAccountsResult {
|
|
12
|
-
address: string;
|
|
13
|
-
publicKey: string;
|
|
14
|
-
purpose: string;
|
|
15
|
-
addressType: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
interface SignMessageResult {
|
|
19
|
-
signature: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class XverseWalletProvider implements IBitcoinWalletProvider {
|
|
24
|
-
private address: string;
|
|
25
|
-
private publicKey: string;
|
|
26
|
-
|
|
27
|
-
constructor(address: string, publicKey: string) {
|
|
28
|
-
this.address = address;
|
|
29
|
-
this.publicKey = publicKey;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async getWalletAddress(): Promise<string> {
|
|
33
|
-
return this.address;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async getPublicKey(): Promise<string> {
|
|
37
|
-
return this.publicKey;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async getAddressType(_address: string): Promise<AddressType> {
|
|
41
|
-
return detectBitcoinAddressType(this.address);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Parse a base64-encoded PSBT to count the number of inputs.
|
|
46
|
-
* Reads the unsigned transaction from the PSBT global section.
|
|
47
|
-
*/
|
|
48
|
-
private countPsbtInputs(psbtBase64: string): number {
|
|
49
|
-
const data = Buffer.from(psbtBase64, 'base64');
|
|
50
|
-
// Skip 5-byte magic (0x70736274FF = "psbt" + separator)
|
|
51
|
-
let offset = 5;
|
|
52
|
-
|
|
53
|
-
// Global section: first key-value pair should be key 0x00 (unsigned tx)
|
|
54
|
-
const keyLen = data[offset++] ?? 0;
|
|
55
|
-
if (keyLen !== 1 || data[offset++] !== 0x00) {
|
|
56
|
-
return 1; // fallback: assume 1 input
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Read value length (compact size)
|
|
60
|
-
const firstByte = data[offset++] ?? 0;
|
|
61
|
-
if (firstByte === 0xfd) offset += 2;
|
|
62
|
-
else if (firstByte === 0xfe) offset += 4;
|
|
63
|
-
else if (firstByte === 0xff) offset += 8;
|
|
64
|
-
// else firstByte IS the length (< 0xfd), no extra bytes
|
|
65
|
-
|
|
66
|
-
// Unsigned tx: skip 4-byte version
|
|
67
|
-
offset += 4;
|
|
68
|
-
|
|
69
|
-
// Read input count (varint)
|
|
70
|
-
const inputByte = data[offset] ?? 0;
|
|
71
|
-
if (inputByte < 0xfd) return inputByte;
|
|
72
|
-
return 1; // fallback for unusual cases
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
async signTransaction(psbtBase64: string, finalize = false): Promise<string> {
|
|
76
|
-
const { request } = await import('sats-connect');
|
|
77
|
-
|
|
78
|
-
const inputCount = this.countPsbtInputs(psbtBase64);
|
|
79
|
-
const signingIndexes = Array.from({ length: inputCount }, (_, i) => i);
|
|
80
|
-
|
|
81
|
-
const response = await request('signPsbt', {
|
|
82
|
-
psbt: psbtBase64,
|
|
83
|
-
broadcast: false,
|
|
84
|
-
signInputs: {
|
|
85
|
-
[this.address]: signingIndexes,
|
|
86
|
-
},
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
if (response.status === 'error') {
|
|
90
|
-
throw new Error(response.error?.message || 'Xverse PSBT signing failed');
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const result = response.result as SignPsbtResult;
|
|
94
|
-
|
|
95
|
-
if (finalize) {
|
|
96
|
-
// Return hex for broadcast
|
|
97
|
-
return Buffer.from(result.psbt, 'base64').toString('hex');
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Return base64 signed PSBT (partially signed)
|
|
101
|
-
return result.psbt;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
async signEcdsaMessage(message: string): Promise<string> {
|
|
105
|
-
const { request } = await import('sats-connect');
|
|
106
|
-
|
|
107
|
-
const response = await request('signMessage', {
|
|
108
|
-
address: this.address,
|
|
109
|
-
message,
|
|
110
|
-
protocol: MessageSigningProtocols.ECDSA,
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
if (response.status === 'error') {
|
|
114
|
-
throw new Error(response.error?.message || 'Xverse ECDSA signing failed');
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
return (response.result as SignMessageResult).signature;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
async signBip322Message(message: string): Promise<string> {
|
|
121
|
-
const { request } = await import('sats-connect');
|
|
122
|
-
|
|
123
|
-
const response = await request('signMessage', {
|
|
124
|
-
address: this.address,
|
|
125
|
-
message,
|
|
126
|
-
protocol: MessageSigningProtocols.BIP322,
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
if (response.status === 'error') {
|
|
130
|
-
throw new Error(response.error?.message || 'Xverse BIP322 signing failed');
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
return (response.result as SignMessageResult).signature;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
async sendBitcoin(toAddress: string, satoshis: bigint): Promise<string> {
|
|
137
|
-
const { request } = await import('sats-connect');
|
|
138
|
-
|
|
139
|
-
const response = await request('sendTransfer', {
|
|
140
|
-
recipients: [
|
|
141
|
-
{
|
|
142
|
-
address: toAddress,
|
|
143
|
-
amount: Number(satoshis),
|
|
144
|
-
},
|
|
145
|
-
],
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
if (response.status === 'error') {
|
|
149
|
-
throw new Error(response.error?.message || 'Xverse sendTransfer failed');
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
return (response.result as { txid: string }).txid;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const XVERSE_ADDRESS_TYPE_KEY = 'xverse-address-type';
|
|
157
|
-
|
|
158
|
-
export class XverseXConnector extends BitcoinXConnector {
|
|
159
|
-
private walletProvider: XverseWalletProvider | undefined;
|
|
160
|
-
|
|
161
|
-
/** Address purpose used when connecting. Taproot (Ordinals) by default to match Radfi. */
|
|
162
|
-
public addressPurpose: AddressPurpose;
|
|
163
|
-
|
|
164
|
-
constructor() {
|
|
165
|
-
super('Xverse', 'xverse');
|
|
166
|
-
// Restore saved preference, default to Taproot
|
|
167
|
-
const saved = typeof window !== 'undefined' ? localStorage.getItem(XVERSE_ADDRESS_TYPE_KEY) : null;
|
|
168
|
-
this.addressPurpose = saved === 'segwit' ? AddressPurpose.Payment : AddressPurpose.Ordinals;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/** Set address purpose and persist to localStorage. */
|
|
172
|
-
public setAddressPurpose(type: BtcWalletAddressType): void {
|
|
173
|
-
this.addressPurpose = type === 'taproot' ? AddressPurpose.Ordinals : AddressPurpose.Payment;
|
|
174
|
-
if (typeof window !== 'undefined') {
|
|
175
|
-
localStorage.setItem(XVERSE_ADDRESS_TYPE_KEY, type);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
public static isAvailable(): boolean {
|
|
180
|
-
return typeof window !== 'undefined' && !!window.BitcoinProvider;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
public get icon(): string {
|
|
184
|
-
return 'https://cdn.brandfetch.io/iddzGN5Rcv/w/400/h/400/theme/dark/icon.jpeg?c=1bxid64Mup7aczewSAYMX&t=1771902357797';
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
async connect(): Promise<XAccount | undefined> {
|
|
188
|
-
if (!XverseXConnector.isAvailable()) {
|
|
189
|
-
throw new Error('Xverse wallet is not installed');
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const { request } = await import('sats-connect');
|
|
193
|
-
|
|
194
|
-
const response = await request('getAccounts', {
|
|
195
|
-
purposes: [this.addressPurpose],
|
|
196
|
-
message: 'Connect to Sodax',
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
if (response.status === 'error') {
|
|
200
|
-
throw new Error(response.error?.message || 'Xverse connection failed');
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
const accounts = response.result as GetAccountsResult[];
|
|
204
|
-
const paymentAccount = accounts.find(a => a.purpose === this.addressPurpose) || accounts[0];
|
|
205
|
-
|
|
206
|
-
if (!paymentAccount) return undefined;
|
|
207
|
-
|
|
208
|
-
this.walletProvider = new XverseWalletProvider(
|
|
209
|
-
paymentAccount.address,
|
|
210
|
-
paymentAccount.publicKey,
|
|
211
|
-
);
|
|
212
|
-
|
|
213
|
-
return {
|
|
214
|
-
address: paymentAccount.address,
|
|
215
|
-
publicKey: paymentAccount.publicKey,
|
|
216
|
-
xChainType: 'BITCOIN',
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
async disconnect(): Promise<void> {
|
|
221
|
-
this.walletProvider = undefined;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
getWalletProvider(): IBitcoinWalletProvider | undefined {
|
|
225
|
-
return this.walletProvider;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
recreateWalletProvider(xAccount: XAccount): IBitcoinWalletProvider | undefined {
|
|
229
|
-
if (!xAccount.address || !xAccount.publicKey) return undefined;
|
|
230
|
-
return new XverseWalletProvider(xAccount.address, xAccount.publicKey);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export { BitcoinXService } from './BitcoinXService';
|
|
2
|
-
export { BitcoinXConnector } from './BitcoinXConnector';
|
|
3
|
-
export { UnisatXConnector } from './UnisatXConnector';
|
|
4
|
-
export { XverseXConnector } from './XverseXConnector';
|
|
5
|
-
export type { BtcWalletAddressType } from '@sodax/types';
|
|
6
|
-
export { OKXXConnector } from './OKXXConnector';
|
|
7
|
-
export { useBitcoinXConnectors } from './useBitcoinXConnectors';
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
|
-
import type { BitcoinXConnector } from './BitcoinXConnector';
|
|
3
|
-
import { useXService } from '../../hooks';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Hook to return available Bitcoin wallet connectors from the globally registered xService.
|
|
7
|
-
*/
|
|
8
|
-
export function useBitcoinXConnectors(): BitcoinXConnector[] {
|
|
9
|
-
const xService = useXService('BITCOIN');
|
|
10
|
-
|
|
11
|
-
return useMemo(() => {
|
|
12
|
-
return (xService?.getXConnectors() || []) as BitcoinXConnector[];
|
|
13
|
-
}, [xService]);
|
|
14
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { XConnector } from '@/core/XConnector';
|
|
2
|
-
import type { XAccount } from '@/types';
|
|
3
|
-
import type { Connector } from 'wagmi';
|
|
4
|
-
|
|
5
|
-
export class EvmXConnector extends XConnector {
|
|
6
|
-
connector: Connector;
|
|
7
|
-
|
|
8
|
-
constructor(connector: Connector) {
|
|
9
|
-
super('EVM', connector.name, connector.id);
|
|
10
|
-
this.connector = connector;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
async connect(): Promise<XAccount | undefined> {
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
async disconnect(): Promise<void> {
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
public get id() {
|
|
22
|
-
return this.connector.id;
|
|
23
|
-
}
|
|
24
|
-
public get icon() {
|
|
25
|
-
return this.connector.icon;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
import { XService } from '@/core/XService';
|
|
2
|
-
import {
|
|
3
|
-
ARBITRUM_MAINNET_CHAIN_ID,
|
|
4
|
-
AVALANCHE_MAINNET_CHAIN_ID,
|
|
5
|
-
BASE_MAINNET_CHAIN_ID,
|
|
6
|
-
BSC_MAINNET_CHAIN_ID,
|
|
7
|
-
ETHEREUM_MAINNET_CHAIN_ID,
|
|
8
|
-
HYPEREVM_MAINNET_CHAIN_ID,
|
|
9
|
-
KAIA_MAINNET_CHAIN_ID,
|
|
10
|
-
LIGHTLINK_MAINNET_CHAIN_ID,
|
|
11
|
-
OPTIMISM_MAINNET_CHAIN_ID,
|
|
12
|
-
POLYGON_MAINNET_CHAIN_ID,
|
|
13
|
-
REDBELLY_MAINNET_CHAIN_ID,
|
|
14
|
-
SONIC_MAINNET_CHAIN_ID,
|
|
15
|
-
type RpcConfig,
|
|
16
|
-
type XToken,
|
|
17
|
-
} from '@sodax/types';
|
|
18
|
-
import { getWagmiChainId, isNativeToken } from '@/utils';
|
|
19
|
-
|
|
20
|
-
import { type Address, type Chain, defineChain, erc20Abi } from 'viem';
|
|
21
|
-
import { getPublicClient } from 'wagmi/actions';
|
|
22
|
-
import { type Config, createConfig, http, createStorage, cookieStorage } from 'wagmi';
|
|
23
|
-
import {
|
|
24
|
-
mainnet,
|
|
25
|
-
avalanche,
|
|
26
|
-
base,
|
|
27
|
-
optimism,
|
|
28
|
-
polygon,
|
|
29
|
-
arbitrum,
|
|
30
|
-
bsc,
|
|
31
|
-
sonic,
|
|
32
|
-
lightlinkPhoenix,
|
|
33
|
-
redbellyMainnet,
|
|
34
|
-
kaia,
|
|
35
|
-
} from 'wagmi/chains';
|
|
36
|
-
import type { WagmiOptions } from '@/SodaxWalletProvider';
|
|
37
|
-
|
|
38
|
-
// HyperEVM chain is not supported by viem, so we need to define it manually
|
|
39
|
-
export const hyper = /*#__PURE__*/ defineChain({
|
|
40
|
-
id: 999,
|
|
41
|
-
name: 'HyperEVM',
|
|
42
|
-
nativeCurrency: {
|
|
43
|
-
decimals: 18,
|
|
44
|
-
name: 'HYPE',
|
|
45
|
-
symbol: 'HYPE',
|
|
46
|
-
},
|
|
47
|
-
rpcUrls: {
|
|
48
|
-
default: { http: ['https://rpc.hyperliquid.xyz/evm'] },
|
|
49
|
-
},
|
|
50
|
-
blockExplorers: {
|
|
51
|
-
default: {
|
|
52
|
-
name: 'HyperEVMScan',
|
|
53
|
-
url: 'https://hyperevmscan.io/',
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
contracts: {
|
|
57
|
-
multicall3: {
|
|
58
|
-
address: '0xcA11bde05977b3631167028862bE2a173976CA11',
|
|
59
|
-
blockCreated: 13051,
|
|
60
|
-
},
|
|
61
|
-
},
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
export const createWagmiConfig = (config: RpcConfig, options?: WagmiOptions) => {
|
|
65
|
-
return createConfig({
|
|
66
|
-
chains: [
|
|
67
|
-
mainnet,
|
|
68
|
-
avalanche,
|
|
69
|
-
arbitrum,
|
|
70
|
-
base,
|
|
71
|
-
bsc,
|
|
72
|
-
sonic,
|
|
73
|
-
optimism,
|
|
74
|
-
polygon,
|
|
75
|
-
hyper,
|
|
76
|
-
lightlinkPhoenix,
|
|
77
|
-
kaia,
|
|
78
|
-
redbellyMainnet,
|
|
79
|
-
],
|
|
80
|
-
ssr: options?.ssr,
|
|
81
|
-
transports: {
|
|
82
|
-
[mainnet.id]: http(config[ETHEREUM_MAINNET_CHAIN_ID]),
|
|
83
|
-
[avalanche.id]: http(config[AVALANCHE_MAINNET_CHAIN_ID]),
|
|
84
|
-
[arbitrum.id]: http(config[ARBITRUM_MAINNET_CHAIN_ID]),
|
|
85
|
-
[base.id]: http(config[BASE_MAINNET_CHAIN_ID]),
|
|
86
|
-
[bsc.id]: http(config[BSC_MAINNET_CHAIN_ID]),
|
|
87
|
-
[sonic.id]: http(config[SONIC_MAINNET_CHAIN_ID]),
|
|
88
|
-
[optimism.id]: http(config[OPTIMISM_MAINNET_CHAIN_ID]),
|
|
89
|
-
[polygon.id]: http(config[POLYGON_MAINNET_CHAIN_ID]),
|
|
90
|
-
[hyper.id]: http(config[HYPEREVM_MAINNET_CHAIN_ID]),
|
|
91
|
-
[lightlinkPhoenix.id]: http(config[LIGHTLINK_MAINNET_CHAIN_ID]),
|
|
92
|
-
[redbellyMainnet.id]: http(config[REDBELLY_MAINNET_CHAIN_ID]),
|
|
93
|
-
[kaia.id]: http(config[KAIA_MAINNET_CHAIN_ID]),
|
|
94
|
-
},
|
|
95
|
-
storage: createStorage({
|
|
96
|
-
storage: cookieStorage,
|
|
97
|
-
key: 'sodax',
|
|
98
|
-
}),
|
|
99
|
-
});
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Service class for handling EVM chain interactions.
|
|
104
|
-
* Implements singleton pattern and provides methods for wallet/chain operations.
|
|
105
|
-
*/
|
|
106
|
-
|
|
107
|
-
export class EvmXService extends XService {
|
|
108
|
-
private static instance: EvmXService;
|
|
109
|
-
public wagmiConfig: Config | undefined;
|
|
110
|
-
|
|
111
|
-
private constructor() {
|
|
112
|
-
super('EVM');
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
getXConnectors() {
|
|
116
|
-
return [];
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
public static getInstance(): EvmXService {
|
|
120
|
-
if (!EvmXService.instance) {
|
|
121
|
-
EvmXService.instance = new EvmXService();
|
|
122
|
-
}
|
|
123
|
-
return EvmXService.instance;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// get erc20 token balance in a chain (evm chain only)
|
|
127
|
-
async _getTokenBalance(address: string | undefined, chainId: number, tokenAddress: string): Promise<bigint> {
|
|
128
|
-
const publicClient = getPublicClient(this.wagmiConfig as Config, { chainId: chainId });
|
|
129
|
-
if (!publicClient) throw new Error('Public client not found');
|
|
130
|
-
const balance = await publicClient.readContract({
|
|
131
|
-
abi: erc20Abi,
|
|
132
|
-
address: tokenAddress as `0x${string}`,
|
|
133
|
-
functionName: 'balanceOf',
|
|
134
|
-
args: [address as `0x${string}`],
|
|
135
|
-
});
|
|
136
|
-
return balance || 0n;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
//get native balance of the chain (evm chain only)
|
|
140
|
-
async _getChainBalance(address: string | undefined, chainId: number) {
|
|
141
|
-
const balance = await getPublicClient(this.wagmiConfig as Config, { chainId: chainId })?.getBalance({
|
|
142
|
-
address: address as Address,
|
|
143
|
-
});
|
|
144
|
-
return balance || 0n;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
async getBalance(address: string | undefined, xToken: XToken): Promise<bigint> {
|
|
148
|
-
if (!address) return 0n;
|
|
149
|
-
if (!this.wagmiConfig) return 0n;
|
|
150
|
-
|
|
151
|
-
const chainId = getWagmiChainId(xToken.xChainId);
|
|
152
|
-
|
|
153
|
-
if (isNativeToken(xToken)) {
|
|
154
|
-
return this._getChainBalance(address, chainId);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
throw new Error(`Unsupported token: ${xToken.symbol}`);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
async getBalances(address: string | undefined, xTokens: XToken[]) {
|
|
161
|
-
if (!address) return {};
|
|
162
|
-
if (!this.wagmiConfig) return {};
|
|
163
|
-
|
|
164
|
-
const nativeTokenBalancePromises = xTokens
|
|
165
|
-
.filter(xToken => isNativeToken(xToken))
|
|
166
|
-
.map(async xToken => {
|
|
167
|
-
const balance = await this.getBalance(address, xToken);
|
|
168
|
-
return { symbol: xToken.symbol, address: xToken.address, balance };
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
const nativeTokenBalances = await Promise.all(nativeTokenBalancePromises);
|
|
172
|
-
const tokenMap = nativeTokenBalances.reduce((map, { address, balance }) => {
|
|
173
|
-
if (balance) map[address] = balance;
|
|
174
|
-
return map;
|
|
175
|
-
}, {});
|
|
176
|
-
|
|
177
|
-
const nonNativeXTokens = xTokens.filter(xToken => !isNativeToken(xToken));
|
|
178
|
-
const xChainId = xTokens[0].xChainId;
|
|
179
|
-
const viemChain: Chain = this.wagmiConfig.chains.find(chain => chain.id === getWagmiChainId(xChainId)) as Chain;
|
|
180
|
-
const chainId = getWagmiChainId(xChainId);
|
|
181
|
-
|
|
182
|
-
const publicClient = getPublicClient(this.wagmiConfig, { chainId: chainId });
|
|
183
|
-
if (!publicClient) throw new Error('Public client not found');
|
|
184
|
-
|
|
185
|
-
if (viemChain?.contracts?.multicall3) {
|
|
186
|
-
//multicall supports
|
|
187
|
-
const result = await publicClient.multicall({
|
|
188
|
-
contracts: nonNativeXTokens.map(token => ({
|
|
189
|
-
abi: erc20Abi,
|
|
190
|
-
address: token.address as `0x${string}`,
|
|
191
|
-
functionName: 'balanceOf',
|
|
192
|
-
args: [address],
|
|
193
|
-
})),
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
return nonNativeXTokens.reduce((acc, token, index) => {
|
|
197
|
-
acc[token.address] = result?.[index]?.result?.toString() || '0';
|
|
198
|
-
return acc;
|
|
199
|
-
}, tokenMap);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
const nonNativeTokenBalances: bigint[] = await Promise.all(
|
|
203
|
-
nonNativeXTokens.map(token => this._getTokenBalance(address, chainId, token.address)),
|
|
204
|
-
);
|
|
205
|
-
|
|
206
|
-
return nonNativeXTokens.reduce((acc, token, idx) => {
|
|
207
|
-
acc[token.address] = nonNativeTokenBalances[idx] || '0';
|
|
208
|
-
return acc;
|
|
209
|
-
}, tokenMap);
|
|
210
|
-
}
|
|
211
|
-
}
|
package/src/xchains/evm/index.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import type { XAccount } from '@/types';
|
|
2
|
-
import { ICONexRequestEventType, ICONexResponseEventType, request } from './iconex';
|
|
3
|
-
|
|
4
|
-
import { XConnector } from '@/core/XConnector';
|
|
5
|
-
|
|
6
|
-
export class IconHanaXConnector extends XConnector {
|
|
7
|
-
constructor() {
|
|
8
|
-
super('ICON', 'Hana Wallet', 'hana');
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
async connect(): Promise<XAccount | undefined> {
|
|
12
|
-
const { hanaWallet } = window as any;
|
|
13
|
-
if (window && !hanaWallet && !hanaWallet?.isAvailable) {
|
|
14
|
-
window.open('https://chromewebstore.google.com/detail/hana-wallet/jfdlamikmbghhapbgfoogdffldioobgl', '_blank');
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const detail = await request({
|
|
19
|
-
type: ICONexRequestEventType.REQUEST_ADDRESS,
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
if (detail?.type === ICONexResponseEventType.RESPONSE_ADDRESS) {
|
|
23
|
-
return {
|
|
24
|
-
address: detail?.payload,
|
|
25
|
-
xChainType: this.xChainType,
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return undefined;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async disconnect(): Promise<void> {
|
|
33
|
-
console.log('HanaIconXConnector disconnected');
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
public get icon() {
|
|
37
|
-
return 'https://raw.githubusercontent.com/balancednetwork/icons/master/wallets/hana.svg';
|
|
38
|
-
}
|
|
39
|
-
}
|