@swapkit/wallets 4.8.0 → 4.8.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/package.json +6 -14
- package/src/bitget.ts +1 -0
- package/src/coinbase/index.ts +54 -0
- package/src/coinbase/signer.ts +99 -0
- package/src/cosmostation.ts +1 -0
- package/src/ctrl.ts +1 -0
- package/src/evm-extensions.ts +1 -0
- package/src/index.ts +3 -0
- package/src/keepkey-bex.ts +1 -0
- package/src/keepkey.ts +1 -0
- package/src/keplr.ts +1 -0
- package/src/keystore-helpers.ts +93 -0
- package/src/keystore.ts +193 -0
- package/src/ledger.ts +1 -0
- package/src/near-wallet-selector/index.ts +116 -0
- package/src/okx.ts +1 -0
- package/src/onekey.ts +1 -0
- package/src/passkeys/index.ts +183 -0
- package/src/phantom.ts +1 -0
- package/src/polkadotjs.ts +1 -0
- package/src/radix/index.ts +95 -0
- package/src/talisman.ts +1 -0
- package/src/trezor.ts +1 -0
- package/src/tronlink.ts +1 -0
- package/src/types.ts +137 -0
- package/src/utils.ts +58 -0
- package/src/vultisig.ts +1 -0
- package/src/walletconnect/constants.ts +105 -0
- package/src/walletconnect/evmSigner.ts +116 -0
- package/src/walletconnect/helpers.ts +76 -0
- package/src/walletconnect/index.ts +409 -0
- package/src/walletconnect/namespaces.ts +80 -0
- package/src/walletconnect/types.ts +6 -0
- package/src/xaman/helpers.ts +89 -0
- package/src/xaman/index.ts +63 -0
- package/src/xaman/types.ts +35 -0
- package/src/xaman/walletMethods.ts +117 -0
package/package.json
CHANGED
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
"@swapkit/toolboxes": "^4.15.0",
|
|
19
19
|
"@swapkit/utxo-signer": "^2.1.1",
|
|
20
20
|
"@swapkit/wallet-core": "^4.2.0",
|
|
21
|
-
"@swapkit/wallet-extensions": "
|
|
22
|
-
"@swapkit/wallet-hardware": "
|
|
21
|
+
"@swapkit/wallet-extensions": "4.5.2",
|
|
22
|
+
"@swapkit/wallet-hardware": "4.8.2",
|
|
23
23
|
"@walletconnect/modal": "~2.7.0",
|
|
24
24
|
"@walletconnect/sign-client": "~2.23.0",
|
|
25
25
|
"cosmjs-types": "~0.10.1",
|
|
@@ -205,20 +205,12 @@
|
|
|
205
205
|
"types": "./dist/types/xaman/index.d.ts"
|
|
206
206
|
}
|
|
207
207
|
},
|
|
208
|
-
"files": [
|
|
209
|
-
"dist/"
|
|
210
|
-
],
|
|
208
|
+
"files": ["dist/", "src/"],
|
|
211
209
|
"homepage": "https://github.com/swapkit/wallets",
|
|
212
210
|
"license": "SEE LICENSE IN LICENSE",
|
|
213
211
|
"name": "@swapkit/wallets",
|
|
214
|
-
"publishConfig": {
|
|
215
|
-
|
|
216
|
-
},
|
|
217
|
-
"repository": {
|
|
218
|
-
"directory": "packages/wallets",
|
|
219
|
-
"type": "git",
|
|
220
|
-
"url": "git+https://github.com/swapkit/wallets.git"
|
|
221
|
-
},
|
|
212
|
+
"publishConfig": { "access": "public" },
|
|
213
|
+
"repository": { "directory": "packages/wallets", "type": "git", "url": "git+https://github.com/swapkit/wallets.git" },
|
|
222
214
|
"scripts": {
|
|
223
215
|
"build": "bun run ./build.ts",
|
|
224
216
|
"build:clean": "rm -rf dist && bun run ./build.ts",
|
|
@@ -227,5 +219,5 @@
|
|
|
227
219
|
"type-check:go": "tsgo"
|
|
228
220
|
},
|
|
229
221
|
"type": "module",
|
|
230
|
-
"version": "4.8.
|
|
222
|
+
"version": "4.8.1"
|
|
231
223
|
}
|
package/src/bitget.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@swapkit/wallet-extensions/bitget";
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Chain, ChainToChainId, filterSupportedChains, SKConfig, WalletOption } from "@swapkit/helpers";
|
|
2
|
+
import { createWallet, getWalletSupportedChains } from "@swapkit/wallet-core";
|
|
3
|
+
|
|
4
|
+
import { getWalletMethods } from "./signer";
|
|
5
|
+
|
|
6
|
+
export const coinbaseWallet = createWallet({
|
|
7
|
+
connect: ({ addChain, walletType, supportedChains }) =>
|
|
8
|
+
async function connectCoinbaseWallet(chains: Chain[]) {
|
|
9
|
+
const { createCoinbaseWalletSDK } = await import("@coinbase/wallet-sdk");
|
|
10
|
+
|
|
11
|
+
const filteredChains = filterSupportedChains({ chains, supportedChains, walletType });
|
|
12
|
+
|
|
13
|
+
const coinbaseConfig = SKConfig.get("integrations").coinbase || { appName: "Swapkit Playground" };
|
|
14
|
+
|
|
15
|
+
const coinbaseSdk = createCoinbaseWalletSDK({
|
|
16
|
+
...coinbaseConfig,
|
|
17
|
+
appChainIds: filteredChains.map((chain) => Number(ChainToChainId[chain])),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
await Promise.all(
|
|
21
|
+
filteredChains.map(async (chain) => {
|
|
22
|
+
const walletMethods = await getWalletMethods({ chain, coinbaseSdk });
|
|
23
|
+
|
|
24
|
+
addChain({ ...walletMethods, chain, walletType });
|
|
25
|
+
}),
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
return true;
|
|
29
|
+
},
|
|
30
|
+
directSigningSupport: {
|
|
31
|
+
[Chain.Arbitrum]: true,
|
|
32
|
+
[Chain.Avalanche]: true,
|
|
33
|
+
[Chain.Base]: true,
|
|
34
|
+
[Chain.BinanceSmartChain]: true,
|
|
35
|
+
[Chain.Ethereum]: true,
|
|
36
|
+
[Chain.Optimism]: true,
|
|
37
|
+
[Chain.Polygon]: true,
|
|
38
|
+
[Chain.XLayer]: true,
|
|
39
|
+
},
|
|
40
|
+
name: "connectCoinbaseWallet",
|
|
41
|
+
supportedChains: [
|
|
42
|
+
Chain.Arbitrum,
|
|
43
|
+
Chain.Avalanche,
|
|
44
|
+
Chain.Base,
|
|
45
|
+
Chain.BinanceSmartChain,
|
|
46
|
+
Chain.Ethereum,
|
|
47
|
+
Chain.Optimism,
|
|
48
|
+
Chain.Polygon,
|
|
49
|
+
Chain.XLayer,
|
|
50
|
+
],
|
|
51
|
+
walletType: WalletOption.COINBASE_MOBILE,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
export const COINBASE_SUPPORTED_CHAINS = getWalletSupportedChains(coinbaseWallet);
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { CoinbaseWalletProvider } from "@coinbase/wallet-sdk";
|
|
2
|
+
import type { createCoinbaseWalletSDK } from "@coinbase/wallet-sdk/dist/createCoinbaseWalletSDK.js";
|
|
3
|
+
import { Chain, SwapKitError } from "@swapkit/helpers";
|
|
4
|
+
import type { Provider, TypedDataDomain, TypedDataField } from "ethers";
|
|
5
|
+
|
|
6
|
+
async function getCoinbaseMobileSigner(walletProvider: CoinbaseWalletProvider, provider?: Provider) {
|
|
7
|
+
const { AbstractSigner } = await import("ethers");
|
|
8
|
+
|
|
9
|
+
class CoinbaseMobileSigner extends AbstractSigner {
|
|
10
|
+
#coinbaseProvider: CoinbaseWalletProvider;
|
|
11
|
+
|
|
12
|
+
constructor(coinbaseProvider: CoinbaseWalletProvider, provider?: Provider) {
|
|
13
|
+
super(provider);
|
|
14
|
+
this.#coinbaseProvider = coinbaseProvider;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async getAddress() {
|
|
18
|
+
const accounts = await this.#coinbaseProvider.request<string[]>({ method: "eth_requestAccounts" });
|
|
19
|
+
|
|
20
|
+
if (!accounts[0]) throw new SwapKitError("wallet_coinbase_no_accounts");
|
|
21
|
+
|
|
22
|
+
return accounts[0];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async signTransaction() {
|
|
26
|
+
return await this.#coinbaseProvider.request<string>({ method: "eth_signTransaction" });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async signMessage(message: string | Uint8Array) {
|
|
30
|
+
return await this.#coinbaseProvider.request<string>({
|
|
31
|
+
method: "personal_sign",
|
|
32
|
+
params: [message, await this.getAddress()],
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async signTypedData(
|
|
37
|
+
domain: TypedDataDomain,
|
|
38
|
+
types: Record<string, TypedDataField[]>,
|
|
39
|
+
value: Record<string, unknown>,
|
|
40
|
+
explicitPrimaryType?: string,
|
|
41
|
+
) {
|
|
42
|
+
const { buildEIP712DomainType } = await import("@swapkit/toolboxes/evm");
|
|
43
|
+
const { TypedDataEncoder } = await import("ethers");
|
|
44
|
+
const address = await this.getAddress();
|
|
45
|
+
|
|
46
|
+
const { EIP712Domain: _, ...filteredTypes } = types;
|
|
47
|
+
const primaryType = explicitPrimaryType ?? TypedDataEncoder.from(filteredTypes).primaryType;
|
|
48
|
+
|
|
49
|
+
const payload = {
|
|
50
|
+
domain,
|
|
51
|
+
message: value,
|
|
52
|
+
primaryType,
|
|
53
|
+
types: { EIP712Domain: buildEIP712DomainType(domain), ...filteredTypes },
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
return await this.#coinbaseProvider.request<string>({
|
|
57
|
+
method: "eth_signTypedData_v4",
|
|
58
|
+
params: [address, JSON.stringify(payload)],
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
connect(provider: Provider) {
|
|
63
|
+
return new CoinbaseMobileSigner(this.#coinbaseProvider, provider);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return new CoinbaseMobileSigner(walletProvider, provider);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export const getWalletMethods = async ({
|
|
71
|
+
chain,
|
|
72
|
+
coinbaseSdk,
|
|
73
|
+
}: {
|
|
74
|
+
chain: Chain;
|
|
75
|
+
coinbaseSdk: ReturnType<typeof createCoinbaseWalletSDK>;
|
|
76
|
+
}) => {
|
|
77
|
+
switch (chain) {
|
|
78
|
+
case Chain.Ethereum:
|
|
79
|
+
case Chain.Avalanche:
|
|
80
|
+
case Chain.Arbitrum:
|
|
81
|
+
case Chain.Optimism:
|
|
82
|
+
case Chain.Polygon:
|
|
83
|
+
case Chain.Base:
|
|
84
|
+
case Chain.BinanceSmartChain: {
|
|
85
|
+
const walletProvider = coinbaseSdk.getProvider() as CoinbaseWalletProvider;
|
|
86
|
+
const { getEvmToolboxAsync, getProvider } = await import("@swapkit/toolboxes/evm");
|
|
87
|
+
|
|
88
|
+
const provider = await getProvider(chain);
|
|
89
|
+
const signer = await getCoinbaseMobileSigner(walletProvider, provider);
|
|
90
|
+
const toolbox = await getEvmToolboxAsync(chain, { provider, signer });
|
|
91
|
+
const address = await signer.getAddress();
|
|
92
|
+
|
|
93
|
+
return { ...toolbox, address };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
default:
|
|
97
|
+
throw new SwapKitError("wallet_coinbase_chain_not_supported", { chain });
|
|
98
|
+
}
|
|
99
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@swapkit/wallet-extensions/cosmostation";
|
package/src/ctrl.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@swapkit/wallet-extensions/ctrl";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@swapkit/wallet-extensions/evm-extensions";
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@swapkit/wallet-extensions/keepkey-bex";
|
package/src/keepkey.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@swapkit/wallet-hardware/keepkey";
|
package/src/keplr.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@swapkit/wallet-extensions/keplr";
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { createCipheriv, createDecipheriv, pbkdf2Sync, randomBytes } from "node:crypto";
|
|
2
|
+
import { generateMnemonic, validateMnemonic } from "@scure/bip39";
|
|
3
|
+
import { wordlist } from "@scure/bip39/wordlists/english.js";
|
|
4
|
+
|
|
5
|
+
export type Keystore = {
|
|
6
|
+
version: number;
|
|
7
|
+
meta: string;
|
|
8
|
+
crypto: {
|
|
9
|
+
cipher: string;
|
|
10
|
+
cipherparams: { iv: string };
|
|
11
|
+
ciphertext: string;
|
|
12
|
+
kdf: string;
|
|
13
|
+
kdfparams: { prf: string; dklen: number; salt: string; c: number };
|
|
14
|
+
mac: string;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
async function blake256(initData: Buffer | string) {
|
|
19
|
+
const { blake2b } = await import("@noble/hashes/blake2.js");
|
|
20
|
+
const data = initData instanceof Buffer ? initData : Buffer.from(initData as string, "hex");
|
|
21
|
+
|
|
22
|
+
const hash = blake2b(data, { dkLen: 32 });
|
|
23
|
+
|
|
24
|
+
return Array.from(hash as Uint8Array)
|
|
25
|
+
.map((byte) => (byte < 0x10 ? `0${byte.toString(16)}` : byte.toString(16)))
|
|
26
|
+
.join("");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function encryptToKeyStore(phrase: string, password: string) {
|
|
30
|
+
const cipher = "aes-128-ctr";
|
|
31
|
+
const iv = randomBytes(16);
|
|
32
|
+
const salt = randomBytes(32);
|
|
33
|
+
const kdfParams = { c: 262144, dklen: 32, prf: "hmac-sha256", salt: salt.toString("hex") };
|
|
34
|
+
|
|
35
|
+
const derivedKey = pbkdf2Sync(password, salt, kdfParams.c, kdfParams.dklen, "sha256");
|
|
36
|
+
const cipherIV = createCipheriv(cipher, derivedKey.subarray(0, 16), iv);
|
|
37
|
+
const ciphertext = Buffer.concat([cipherIV.update(Buffer.from(phrase, "utf8")), cipherIV.final()]);
|
|
38
|
+
const initData = Buffer.concat([derivedKey.subarray(16, 32), Buffer.from(ciphertext)]);
|
|
39
|
+
const mac = await blake256(initData);
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
crypto: {
|
|
43
|
+
cipher,
|
|
44
|
+
cipherparams: { iv: iv.toString("hex") },
|
|
45
|
+
ciphertext: ciphertext.toString("hex"),
|
|
46
|
+
kdf: "pbkdf2",
|
|
47
|
+
kdfparams: kdfParams,
|
|
48
|
+
mac,
|
|
49
|
+
},
|
|
50
|
+
meta: "xchain-keystore",
|
|
51
|
+
version: 1,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function generatePhrase(size: 12 | 24 = 12) {
|
|
56
|
+
return generateMnemonic(wordlist, size === 12 ? 128 : 256);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function validatePhrase(phrase: string) {
|
|
60
|
+
return validateMnemonic(phrase, wordlist);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export async function decryptFromKeystore(keystore: Keystore, password: string) {
|
|
64
|
+
const { SwapKitError } = await import("@swapkit/helpers");
|
|
65
|
+
|
|
66
|
+
switch (keystore.version) {
|
|
67
|
+
case 1: {
|
|
68
|
+
const kdfParams = keystore.crypto.kdfparams;
|
|
69
|
+
const salt = Buffer.from(kdfParams.salt, "hex");
|
|
70
|
+
const derivedKey = pbkdf2Sync(password, salt, kdfParams.c, kdfParams.dklen, "sha256");
|
|
71
|
+
|
|
72
|
+
const ciphertext = Buffer.from(keystore.crypto.ciphertext, "hex");
|
|
73
|
+
const initData = Buffer.concat([derivedKey.subarray(16, 32), ciphertext]);
|
|
74
|
+
const mac = await blake256(initData);
|
|
75
|
+
|
|
76
|
+
if (mac !== keystore.crypto.mac) {
|
|
77
|
+
throw new SwapKitError("wallet_keystore_invalid_password");
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const decipher = createDecipheriv(
|
|
81
|
+
keystore.crypto.cipher,
|
|
82
|
+
derivedKey.subarray(0, 16),
|
|
83
|
+
Buffer.from(keystore.crypto.cipherparams.iv, "hex"),
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const phrase = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
|
|
87
|
+
return phrase.toString("utf8");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
default:
|
|
91
|
+
throw new SwapKitError("wallet_keystore_unsupported_version");
|
|
92
|
+
}
|
|
93
|
+
}
|
package/src/keystore.ts
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type AssetValue,
|
|
3
|
+
Chain,
|
|
4
|
+
CosmosChains,
|
|
5
|
+
type DerivationPathArray,
|
|
6
|
+
EVMChains,
|
|
7
|
+
filterSupportedChains,
|
|
8
|
+
NetworkDerivationPath,
|
|
9
|
+
type UTXOChain,
|
|
10
|
+
UTXOChains,
|
|
11
|
+
updateDerivationPath,
|
|
12
|
+
WalletOption,
|
|
13
|
+
} from "@swapkit/helpers";
|
|
14
|
+
import type { DerivedAddress, FullWallet } from "@swapkit/toolboxes";
|
|
15
|
+
import { createWallet, getWalletSupportedChains } from "@swapkit/wallet-core";
|
|
16
|
+
|
|
17
|
+
export {
|
|
18
|
+
decryptFromKeystore,
|
|
19
|
+
encryptToKeyStore,
|
|
20
|
+
generatePhrase,
|
|
21
|
+
type Keystore,
|
|
22
|
+
validatePhrase,
|
|
23
|
+
} from "./keystore-helpers";
|
|
24
|
+
|
|
25
|
+
type UTXOToolboxWithHD = {
|
|
26
|
+
deriveAddressAtIndex: (params: { index: number; change?: boolean }) => DerivedAddress | undefined;
|
|
27
|
+
getExtendedPublicKey: () => string | undefined;
|
|
28
|
+
getBalance: (address: string) => Promise<AssetValue[]>;
|
|
29
|
+
resolveDerivationIndex?: (params: {
|
|
30
|
+
address: string;
|
|
31
|
+
gapLimit?: number;
|
|
32
|
+
}) => { index: number; change: boolean } | undefined;
|
|
33
|
+
transferFromMultipleAddresses?: (params: {
|
|
34
|
+
utxos: Array<{
|
|
35
|
+
hash: string;
|
|
36
|
+
index: number;
|
|
37
|
+
value: number;
|
|
38
|
+
txHex?: string;
|
|
39
|
+
derivationIndex: number;
|
|
40
|
+
isChange: boolean;
|
|
41
|
+
address: string;
|
|
42
|
+
}>;
|
|
43
|
+
recipient: string;
|
|
44
|
+
assetValue: AssetValue;
|
|
45
|
+
memo?: string;
|
|
46
|
+
feeRate?: number;
|
|
47
|
+
}) => Promise<string>;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
function isUTXOToolboxWithHD(toolbox: unknown): toolbox is UTXOToolboxWithHD {
|
|
51
|
+
return (
|
|
52
|
+
typeof toolbox === "object" &&
|
|
53
|
+
toolbox !== null &&
|
|
54
|
+
"deriveAddressAtIndex" in toolbox &&
|
|
55
|
+
typeof (toolbox as UTXOToolboxWithHD).deriveAddressAtIndex === "function" &&
|
|
56
|
+
"getExtendedPublicKey" in toolbox &&
|
|
57
|
+
typeof (toolbox as UTXOToolboxWithHD).getExtendedPublicKey === "function" &&
|
|
58
|
+
"getBalance" in toolbox &&
|
|
59
|
+
typeof (toolbox as UTXOToolboxWithHD).getBalance === "function"
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function createHDWalletMethods(chain: UTXOChain, toolbox: UTXOToolboxWithHD) {
|
|
64
|
+
const { createHDWalletHelpers, getUtxoApi } = await import("@swapkit/toolboxes/utxo");
|
|
65
|
+
|
|
66
|
+
function deriveAddresses(params: { count: number; startIndex?: number; change?: boolean }) {
|
|
67
|
+
const { count, startIndex = 0, change = false } = params;
|
|
68
|
+
if (count < 1 || count > 1000) throw new RangeError(`count must be between 1 and 1000, got ${count}`);
|
|
69
|
+
if (startIndex < 0) throw new RangeError(`startIndex must be non-negative, got ${startIndex}`);
|
|
70
|
+
|
|
71
|
+
const addresses: DerivedAddress[] = [];
|
|
72
|
+
for (let i = 0; i < count; i++) {
|
|
73
|
+
const derived = toolbox.deriveAddressAtIndex({ change, index: startIndex + i });
|
|
74
|
+
if (derived) addresses.push(derived);
|
|
75
|
+
}
|
|
76
|
+
return addresses;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const { scanForAddresses, getAggregatedBalance, getAggregatedUtxos } = createHDWalletHelpers({
|
|
80
|
+
chain,
|
|
81
|
+
deriveAddress: (params) => toolbox.deriveAddressAtIndex(params),
|
|
82
|
+
getBalance: toolbox.getBalance,
|
|
83
|
+
getUtxos: (address: string) => getUtxoApi(chain).getUtxos({ address, fetchTxHex: true }),
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
return { deriveAddresses, getAggregatedBalance, getAggregatedUtxos, scanForAddresses };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export const keystoreWallet = createWallet({
|
|
90
|
+
connect: ({ addChain }) =>
|
|
91
|
+
async function connectKeystore(
|
|
92
|
+
chains: Chain[],
|
|
93
|
+
phrase: string,
|
|
94
|
+
derivationPathMapOrIndex?: { [chain in Chain]?: DerivationPathArray } | number,
|
|
95
|
+
) {
|
|
96
|
+
const wallets = await createKeystoreWallet({ chains, derivationPathMapOrIndex, phrase });
|
|
97
|
+
|
|
98
|
+
for (const wallet of Object.values(wallets)) {
|
|
99
|
+
addChain({ ...wallet, chain: wallet.chain, walletType: WalletOption.KEYSTORE });
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return true;
|
|
103
|
+
},
|
|
104
|
+
// Keystore holds the private key — direct signing works for every supported chain.
|
|
105
|
+
directSigningSupport: {
|
|
106
|
+
...Object.fromEntries(EVMChains.map((chain) => [chain, true])),
|
|
107
|
+
...Object.fromEntries(UTXOChains.map((chain) => [chain, true])),
|
|
108
|
+
...Object.fromEntries(CosmosChains.filter((chain) => chain !== Chain.Harbor).map((chain) => [chain, true])),
|
|
109
|
+
[Chain.Aptos]: true,
|
|
110
|
+
[Chain.Cardano]: true,
|
|
111
|
+
[Chain.Near]: true,
|
|
112
|
+
[Chain.Ripple]: true,
|
|
113
|
+
[Chain.Solana]: true,
|
|
114
|
+
[Chain.Stellar]: true,
|
|
115
|
+
[Chain.Sui]: true,
|
|
116
|
+
[Chain.Ton]: true,
|
|
117
|
+
[Chain.Tron]: true,
|
|
118
|
+
},
|
|
119
|
+
name: "connectKeystore",
|
|
120
|
+
supportedChains: [
|
|
121
|
+
...EVMChains,
|
|
122
|
+
...UTXOChains,
|
|
123
|
+
...CosmosChains.filter((chain) => chain !== Chain.Harbor),
|
|
124
|
+
Chain.Aptos,
|
|
125
|
+
Chain.Cardano,
|
|
126
|
+
Chain.Ripple,
|
|
127
|
+
Chain.Solana,
|
|
128
|
+
Chain.Stellar,
|
|
129
|
+
Chain.Sui,
|
|
130
|
+
Chain.Ton,
|
|
131
|
+
Chain.Tron,
|
|
132
|
+
Chain.Near,
|
|
133
|
+
],
|
|
134
|
+
walletType: WalletOption.KEYSTORE,
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
export const KEYSTORE_SUPPORTED_CHAINS = getWalletSupportedChains(keystoreWallet);
|
|
138
|
+
|
|
139
|
+
export async function createKeystoreWallet<T extends Chain[]>({
|
|
140
|
+
chains,
|
|
141
|
+
phrase,
|
|
142
|
+
derivationPathMapOrIndex,
|
|
143
|
+
}: {
|
|
144
|
+
chains: T;
|
|
145
|
+
phrase: string;
|
|
146
|
+
derivationPathMapOrIndex?: { [chain in Chain]?: DerivationPathArray } | number;
|
|
147
|
+
}) {
|
|
148
|
+
const filteredChains = filterSupportedChains({
|
|
149
|
+
chains,
|
|
150
|
+
supportedChains: KEYSTORE_SUPPORTED_CHAINS,
|
|
151
|
+
walletType: WalletOption.KEYSTORE,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const wallets = await Promise.all(
|
|
155
|
+
filteredChains.map(async (chain) => {
|
|
156
|
+
const { getToolbox } = await import("@swapkit/toolboxes");
|
|
157
|
+
|
|
158
|
+
const derivationPathIndex = typeof derivationPathMapOrIndex === "number" ? derivationPathMapOrIndex : 0;
|
|
159
|
+
const derivationPathFromMap =
|
|
160
|
+
derivationPathMapOrIndex && typeof derivationPathMapOrIndex === "object"
|
|
161
|
+
? derivationPathMapOrIndex[chain]
|
|
162
|
+
: undefined;
|
|
163
|
+
|
|
164
|
+
const derivationArrayToUpdate = NetworkDerivationPath[chain].slice(
|
|
165
|
+
0,
|
|
166
|
+
chain === Chain.Solana ? 4 : 5,
|
|
167
|
+
) as DerivationPathArray;
|
|
168
|
+
|
|
169
|
+
const derivationPath: DerivationPathArray =
|
|
170
|
+
derivationPathFromMap || updateDerivationPath(derivationArrayToUpdate, { index: derivationPathIndex });
|
|
171
|
+
|
|
172
|
+
const toolbox = await getToolbox(chain, { derivationPath, phrase });
|
|
173
|
+
const address = (await toolbox.getAddress()) || "";
|
|
174
|
+
|
|
175
|
+
const hdWalletMethods =
|
|
176
|
+
UTXOChains.includes(chain as UTXOChain) && isUTXOToolboxWithHD(toolbox)
|
|
177
|
+
? await createHDWalletMethods(chain as UTXOChain, toolbox)
|
|
178
|
+
: {};
|
|
179
|
+
|
|
180
|
+
const wallet = { ...toolbox, ...hdWalletMethods, address, chain };
|
|
181
|
+
|
|
182
|
+
return wallet;
|
|
183
|
+
}),
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
return wallets.reduce(
|
|
187
|
+
(acc, wallet) => {
|
|
188
|
+
acc[wallet.chain as T[number]] = wallet as FullWallet[T[number]];
|
|
189
|
+
return acc;
|
|
190
|
+
},
|
|
191
|
+
{} as { [key in T[number]]: FullWallet[key] },
|
|
192
|
+
);
|
|
193
|
+
}
|
package/src/ledger.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@swapkit/wallet-hardware/ledger";
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { Wallet, WalletModuleFactory } from "@near-wallet-selector/core";
|
|
2
|
+
import "@near-wallet-selector/modal-ui-js/styles.css";
|
|
3
|
+
import type { Transaction } from "@near-js/transactions";
|
|
4
|
+
import { Chain, filterSupportedChains, SKConfig, SwapKitError, WalletOption } from "@swapkit/helpers";
|
|
5
|
+
import { getNearToolbox } from "@swapkit/toolboxes/near";
|
|
6
|
+
import { createWallet, getWalletSupportedChains } from "@swapkit/wallet-core";
|
|
7
|
+
|
|
8
|
+
function createNearSigner(wallet: Wallet) {
|
|
9
|
+
return {
|
|
10
|
+
getAddress: async () => {
|
|
11
|
+
const accounts = await wallet.getAccounts();
|
|
12
|
+
const accountId = accounts[0]?.accountId;
|
|
13
|
+
|
|
14
|
+
if (!accountId) {
|
|
15
|
+
throw new SwapKitError("wallet_connection_rejected_by_user");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return accountId;
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
getPublicKey: () => {
|
|
22
|
+
throw new SwapKitError("wallet_near_method_not_supported");
|
|
23
|
+
},
|
|
24
|
+
signAndSendTransactions: async (transactions: { transactions: Transaction[] }) => {
|
|
25
|
+
const result = await wallet.signAndSendTransactions(transactions);
|
|
26
|
+
return result?.[0]?.transaction_outcome.id || "";
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
signDelegateAction: () => {
|
|
30
|
+
throw new SwapKitError("wallet_near_method_not_supported");
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
signNep413Message: () => {
|
|
34
|
+
throw new SwapKitError("wallet_near_method_not_supported");
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
signTransaction: (params: Transaction) => {
|
|
38
|
+
if (!wallet.signTransaction) {
|
|
39
|
+
throw new SwapKitError("wallet_near_method_not_supported");
|
|
40
|
+
}
|
|
41
|
+
return wallet.signTransaction(params);
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function waitForWalletSelection(selector: any, modal: any) {
|
|
47
|
+
return new Promise<void>((resolve) => {
|
|
48
|
+
const subscription = selector.store.observable.subscribe((state: any) => {
|
|
49
|
+
if (state.selectedWalletId) {
|
|
50
|
+
subscription.unsubscribe();
|
|
51
|
+
modal.hide();
|
|
52
|
+
resolve();
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
modal.show();
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function getWalletMethods(walletFactories?: WalletModuleFactory[]) {
|
|
61
|
+
const { setupWalletSelector } = await import("@near-wallet-selector/core");
|
|
62
|
+
const { setupModal } = await import("@near-wallet-selector/modal-ui-js");
|
|
63
|
+
|
|
64
|
+
const contractId = SKConfig.get("integrations")?.nearWalletSelector?.contractId || "";
|
|
65
|
+
const selector = await setupWalletSelector({ modules: [...(walletFactories || [])], network: "mainnet" });
|
|
66
|
+
|
|
67
|
+
const isSignedIn = selector.isSignedIn();
|
|
68
|
+
|
|
69
|
+
if (!isSignedIn) {
|
|
70
|
+
// Only show modal if not already connected
|
|
71
|
+
const modal = setupModal(selector, { contractId, description: "Connect your NEAR wallet to SwapKit" });
|
|
72
|
+
|
|
73
|
+
await waitForWalletSelection(selector, modal);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const wallet = await selector.wallet();
|
|
77
|
+
const signer = createNearSigner(wallet);
|
|
78
|
+
const toolbox = await getNearToolbox({ signer });
|
|
79
|
+
const address = await signer.getAddress();
|
|
80
|
+
|
|
81
|
+
const disconnect = async () => {
|
|
82
|
+
try {
|
|
83
|
+
await wallet.signOut();
|
|
84
|
+
} catch (error) {
|
|
85
|
+
throw new SwapKitError("wallet_connection_rejected_by_user", error);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
return { ...toolbox, address, disconnect };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export const walletSelectorWallet = createWallet({
|
|
93
|
+
connect: ({ addChain, supportedChains, walletType }) =>
|
|
94
|
+
async function connectWalletSelector(chains: Chain[], walletFactories?: WalletModuleFactory[]) {
|
|
95
|
+
const filteredChains = filterSupportedChains({ chains, supportedChains, walletType });
|
|
96
|
+
|
|
97
|
+
if (filteredChains.length === 0) {
|
|
98
|
+
throw new SwapKitError("wallet_chain_not_supported", {
|
|
99
|
+
chain: chains[0],
|
|
100
|
+
wallet: WalletOption.WALLET_SELECTOR,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const walletMethods = await getWalletMethods(walletFactories);
|
|
105
|
+
|
|
106
|
+
addChain({ ...walletMethods, balance: [], chain: Chain.Near, walletType });
|
|
107
|
+
|
|
108
|
+
return true;
|
|
109
|
+
},
|
|
110
|
+
directSigningSupport: { [Chain.Near]: true },
|
|
111
|
+
name: "connectWalletSelector",
|
|
112
|
+
supportedChains: [Chain.Near],
|
|
113
|
+
walletType: WalletOption.WALLET_SELECTOR,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
export const WALLET_SELECTOR_SUPPORTED_CHAINS = getWalletSupportedChains(walletSelectorWallet);
|
package/src/okx.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@swapkit/wallet-extensions/okx";
|
package/src/onekey.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@swapkit/wallet-extensions/onekey";
|