@reclack/walletkit 0.0.0-stage → 0.1.0
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/LICENSE +21 -0
- package/README.md +341 -2
- package/assets/backpack.webp +0 -0
- package/assets/berasig.webp +0 -0
- package/assets/bestwallet.webp +0 -0
- package/assets/bifrostwallet.webp +0 -0
- package/assets/binance.webp +0 -0
- package/assets/bitcoincom.webp +0 -0
- package/assets/bitget.webp +0 -0
- package/assets/bitpay.webp +0 -0
- package/assets/bitski.webp +0 -0
- package/assets/bitverse.webp +0 -0
- package/assets/blockchaincom.webp +0 -0
- package/assets/brave.webp +0 -0
- package/assets/bybit.webp +0 -0
- package/assets/clv.webp +0 -0
- package/assets/coin98.webp +0 -0
- package/assets/coinbase.webp +0 -0
- package/assets/compass.webp +0 -0
- package/assets/core.webp +0 -0
- package/assets/crypto_com.webp +0 -0
- package/assets/ctrl.webp +0 -0
- package/assets/dawn.webp +0 -0
- package/assets/desig.webp +0 -0
- package/assets/enkrypt.webp +0 -0
- package/assets/exodus.webp +0 -0
- package/assets/foxwallet.webp +0 -0
- package/assets/frame.webp +0 -0
- package/assets/frontier.webp +0 -0
- package/assets/gate.webp +0 -0
- package/assets/gemini.webp +0 -0
- package/assets/imtoken.webp +0 -0
- package/assets/iopay.webp +0 -0
- package/assets/kaia.webp +0 -0
- package/assets/kaikas.webp +0 -0
- package/assets/kraken.webp +0 -0
- package/assets/kresuswallet.webp +0 -0
- package/assets/ledger.webp +0 -0
- package/assets/magiceden.webp +0 -0
- package/assets/meco.webp +0 -0
- package/assets/metamask.webp +0 -0
- package/assets/mew.webp +0 -0
- package/assets/nest.webp +0 -0
- package/assets/nova.webp +0 -0
- package/assets/okto.webp +0 -0
- package/assets/okx.webp +0 -0
- package/assets/oneinch.webp +0 -0
- package/assets/onekey.webp +0 -0
- package/assets/phantom.webp +0 -0
- package/assets/rabby.webp +0 -0
- package/assets/rainbow.webp +0 -0
- package/assets/ramper.webp +0 -0
- package/assets/ready.webp +0 -0
- package/assets/ronin.webp +0 -0
- package/assets/safe.webp +0 -0
- package/assets/safepal.webp +0 -0
- package/assets/solflare.webp +0 -0
- package/assets/subwallet.webp +0 -0
- package/assets/taho.webp +0 -0
- package/assets/talisman.webp +0 -0
- package/assets/tokenary.webp +0 -0
- package/assets/tokenpocket.webp +0 -0
- package/assets/trust-wallet.webp +0 -0
- package/assets/uniswap.webp +0 -0
- package/assets/universalprofiles.webp +0 -0
- package/assets/valora.webp +0 -0
- package/assets/wigwam.webp +0 -0
- package/assets/xportal.webp +0 -0
- package/assets/zeal.webp +0 -0
- package/assets/zerion.webp +0 -0
- package/custom-elements.json +207 -0
- package/dist/abi.d.ts +21 -0
- package/dist/abi.d.ts.map +1 -0
- package/dist/abi.js +50 -0
- package/dist/abi.js.map +1 -0
- package/dist/address.d.ts +15 -0
- package/dist/address.d.ts.map +1 -0
- package/dist/address.js +25 -0
- package/dist/address.js.map +1 -0
- package/dist/balance.d.ts +78 -0
- package/dist/balance.d.ts.map +1 -0
- package/dist/balance.js +146 -0
- package/dist/balance.js.map +1 -0
- package/dist/base58.d.ts +15 -0
- package/dist/base58.d.ts.map +1 -0
- package/dist/base58.js +52 -0
- package/dist/base58.js.map +1 -0
- package/dist/catalog-fetch.d.ts +18 -0
- package/dist/catalog-fetch.d.ts.map +1 -0
- package/dist/catalog-fetch.js +85 -0
- package/dist/catalog-fetch.js.map +1 -0
- package/dist/catalog.d.ts +57 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +80 -0
- package/dist/catalog.js.map +1 -0
- package/dist/chains.d.ts +32 -0
- package/dist/chains.d.ts.map +1 -0
- package/dist/chains.js +103 -0
- package/dist/chains.js.map +1 -0
- package/dist/config.d.ts +40 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +44 -0
- package/dist/config.js.map +1 -0
- package/dist/deep-links.d.ts +22 -0
- package/dist/deep-links.d.ts.map +1 -0
- package/dist/deep-links.js +201 -0
- package/dist/deep-links.js.map +1 -0
- package/dist/device.d.ts +23 -0
- package/dist/device.d.ts.map +1 -0
- package/dist/device.js +59 -0
- package/dist/device.js.map +1 -0
- package/dist/element/attributes.d.ts +48 -0
- package/dist/element/element.d.ts +92 -0
- package/dist/element/index.d.ts +4 -0
- package/dist/element/props.d.ts +67 -0
- package/dist/element/ui/app.d.ts +22 -0
- package/dist/element/ui/assets.d.ts +7 -0
- package/dist/element/ui/qr.d.ts +16 -0
- package/dist/element/ui/use-handheld.d.ts +8 -0
- package/dist/element/ui/wallet-connect-panel.d.ts +26 -0
- package/dist/element/ui/wallet-dialog.d.ts +37 -0
- package/dist/element/ui/wallet-list.d.ts +26 -0
- package/dist/element/ui/wallet-mark.d.ts +15 -0
- package/dist/element.js +2079 -0
- package/dist/errors.d.ts +34 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +64 -0
- package/dist/errors.js.map +1 -0
- package/dist/evm.d.ts +49 -0
- package/dist/evm.d.ts.map +1 -0
- package/dist/evm.js +217 -0
- package/dist/evm.js.map +1 -0
- package/dist/icons.d.ts +22 -0
- package/dist/icons.d.ts.map +1 -0
- package/dist/icons.js +98 -0
- package/dist/icons.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/intent.d.ts +60 -0
- package/dist/intent.d.ts.map +1 -0
- package/dist/intent.js +2 -0
- package/dist/intent.js.map +1 -0
- package/dist/kit.d.ts +124 -0
- package/dist/kit.d.ts.map +1 -0
- package/dist/kit.js +362 -0
- package/dist/kit.js.map +1 -0
- package/dist/svm.d.ts +45 -0
- package/dist/svm.d.ts.map +1 -0
- package/dist/svm.js +201 -0
- package/dist/svm.js.map +1 -0
- package/dist/theme.d.ts +101 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +217 -0
- package/dist/theme.js.map +1 -0
- package/dist/types.d.ts +144 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/wallet-standard.d.ts +77 -0
- package/dist/wallet-standard.d.ts.map +1 -0
- package/dist/wallet-standard.js +89 -0
- package/dist/wallet-standard.js.map +1 -0
- package/dist/walletconnect.d.ts +74 -0
- package/dist/walletconnect.d.ts.map +1 -0
- package/dist/walletconnect.js +133 -0
- package/dist/walletconnect.js.map +1 -0
- package/package.json +71 -3
- package/vscode.html-custom-data.json +55 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import type { StandardAccount, StandardWallet } from './wallet-standard.js';
|
|
2
|
+
/**
|
|
3
|
+
* An EIP-1193 provider: the only interface this app talks to.
|
|
4
|
+
*
|
|
5
|
+
* Deliberately hand-typed rather than pulled from a wallet SDK: every wallet
|
|
6
|
+
* below speaks this, and a checkout page that handles other people's money
|
|
7
|
+
* should ship as little third-party code as possible.
|
|
8
|
+
*/
|
|
9
|
+
export interface Eip1193Provider {
|
|
10
|
+
request(args: {
|
|
11
|
+
method: string;
|
|
12
|
+
params?: unknown[] | object;
|
|
13
|
+
}): Promise<unknown>;
|
|
14
|
+
on?(event: string, handler: (...args: unknown[]) => void): void;
|
|
15
|
+
removeListener?(event: string, handler: (...args: unknown[]) => void): void;
|
|
16
|
+
}
|
|
17
|
+
/** A wallet Reclack knows how to name and find. */
|
|
18
|
+
export interface EvmWalletDefinition {
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
/** EIP-6963 reverse-DNS ids, when the wallet announces any. */
|
|
22
|
+
rdns?: string[];
|
|
23
|
+
/**
|
|
24
|
+
* Fallback detector for wallets that inject a global but do not yet
|
|
25
|
+
* announce themselves over EIP-6963.
|
|
26
|
+
*/
|
|
27
|
+
detect?: (win: Window) => Eip1193Provider | undefined;
|
|
28
|
+
/** Where to send someone who does not have it installed. */
|
|
29
|
+
installUrl: string;
|
|
30
|
+
}
|
|
31
|
+
/** A wallet actually available in this browser, ready to connect. */
|
|
32
|
+
export interface DetectedEvmWallet {
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
/** Data-URI supplied by the wallet itself over EIP-6963, when present. */
|
|
36
|
+
icon?: string;
|
|
37
|
+
provider: Eip1193Provider;
|
|
38
|
+
/** True when discovered via EIP-6963 rather than a global sniff. */
|
|
39
|
+
announced: boolean;
|
|
40
|
+
}
|
|
41
|
+
export interface ConnectedEvmWallet {
|
|
42
|
+
walletId: string;
|
|
43
|
+
name: string;
|
|
44
|
+
icon?: string;
|
|
45
|
+
address: string;
|
|
46
|
+
chainId: number;
|
|
47
|
+
provider: Eip1193Provider;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* A Solana wallet's injected provider: the only interface this app talks to.
|
|
51
|
+
*
|
|
52
|
+
* Hand-typed, like the EIP-1193 one above it, and for the same reason: a
|
|
53
|
+
* checkout page handling other people's money should ship as little
|
|
54
|
+
* third-party code as it can. No wallet SDK is needed because the transaction
|
|
55
|
+
* arrives already built, so nothing here constructs one.
|
|
56
|
+
*
|
|
57
|
+
* Every field is optional because wallets disagree about which of these they
|
|
58
|
+
* expose. What they must have is `request`; see signAndSendSvm.
|
|
59
|
+
*/
|
|
60
|
+
export interface SvmProvider {
|
|
61
|
+
publicKey?: unknown;
|
|
62
|
+
request?(args: {
|
|
63
|
+
method: string;
|
|
64
|
+
params?: unknown;
|
|
65
|
+
}): Promise<unknown>;
|
|
66
|
+
connect?(options?: {
|
|
67
|
+
onlyIfTrusted?: boolean;
|
|
68
|
+
}): Promise<unknown>;
|
|
69
|
+
disconnect?(): Promise<void>;
|
|
70
|
+
on?(event: string, handler: (...args: unknown[]) => void): void;
|
|
71
|
+
removeListener?(event: string, handler: (...args: unknown[]) => void): void;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* A Solana wallet Reclack knows how to name and find.
|
|
75
|
+
*
|
|
76
|
+
* Separate from EvmWalletDefinition rather than a family field on it. The two
|
|
77
|
+
* share a name and an install link and nothing else: no EIP-6963
|
|
78
|
+
* announcement, no chain to switch to, a different provider interface and a
|
|
79
|
+
* different address format. One definition covering both would be a struct
|
|
80
|
+
* whose fields are half-populated depending on which family you meant.
|
|
81
|
+
*/
|
|
82
|
+
export interface SvmWalletDefinition {
|
|
83
|
+
id: string;
|
|
84
|
+
name: string;
|
|
85
|
+
installUrl: string;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* A Solana wallet available in this browser, ready to connect.
|
|
89
|
+
*
|
|
90
|
+
* Reached one of two ways, and it matters which. A wallet that registered
|
|
91
|
+
* through the Wallet Standard is driven by its feature objects; one found by
|
|
92
|
+
* sniffing a global is driven by its injected provider. Most wallets that
|
|
93
|
+
* sign Solana announce themselves the first way, including every EVM wallet
|
|
94
|
+
* that has added it, so that is the one to prefer.
|
|
95
|
+
*/
|
|
96
|
+
export interface DetectedSvmWallet {
|
|
97
|
+
id: string;
|
|
98
|
+
name: string;
|
|
99
|
+
icon?: string;
|
|
100
|
+
/** Set when the wallet registered through the Wallet Standard. */
|
|
101
|
+
standard?: StandardWallet;
|
|
102
|
+
/** Set when it was found as an injected global instead. */
|
|
103
|
+
provider?: SvmProvider;
|
|
104
|
+
}
|
|
105
|
+
export interface ConnectedSvmWallet {
|
|
106
|
+
walletId: string;
|
|
107
|
+
name: string;
|
|
108
|
+
icon?: string;
|
|
109
|
+
/** Base58. Never lowercased: the case is part of the key. */
|
|
110
|
+
address: string;
|
|
111
|
+
standard?: StandardWallet;
|
|
112
|
+
/** The account the standard wallet connected, which signing needs back. */
|
|
113
|
+
account?: StandardAccount;
|
|
114
|
+
provider?: SvmProvider;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* The least a wallet picker needs to know about a detected wallet.
|
|
118
|
+
*
|
|
119
|
+
* The picker is shared between families, which have different providers and
|
|
120
|
+
* different connect calls but the same job on screen: name a wallet, show its
|
|
121
|
+
* mark, and hand the whole thing back when it is chosen. Typing the UI
|
|
122
|
+
* against this rather than against either family's wallet keeps one picker
|
|
123
|
+
* instead of two that drift apart.
|
|
124
|
+
*/
|
|
125
|
+
export interface WalletChoice {
|
|
126
|
+
id: string;
|
|
127
|
+
name: string;
|
|
128
|
+
icon?: string;
|
|
129
|
+
}
|
|
130
|
+
/** The chain families a wallet can sign for. */
|
|
131
|
+
export type ChainFamily = 'evm' | 'svm';
|
|
132
|
+
/** The least the picker needs about a wallet that may not be installed. */
|
|
133
|
+
export interface WalletOption {
|
|
134
|
+
id: string;
|
|
135
|
+
name: string;
|
|
136
|
+
installUrl: string;
|
|
137
|
+
/**
|
|
138
|
+
* The wallet's mobile app has a browser of its own, which this checkout
|
|
139
|
+
* can be opened in. Decides how a wallet that injects nothing into an
|
|
140
|
+
* ordinary page is reached: the hand-off carries the checkout to that
|
|
141
|
+
* browser, and only a wallet without one needs a WalletConnect session.
|
|
142
|
+
*/
|
|
143
|
+
browser?: boolean;
|
|
144
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Solana wallet discovery through the Wallet Standard.
|
|
3
|
+
*
|
|
4
|
+
* The Solana equivalent of EIP-6963, and here for the same reason: sniffing
|
|
5
|
+
* globals finds only the wallets that claim one. MetaMask, Brave, Coinbase
|
|
6
|
+
* Wallet and others all sign Solana now, and they announce it this way rather
|
|
7
|
+
* than by injecting `window.solana`, so a list built from globals is a list
|
|
8
|
+
* of three wallets that is wrong about every other.
|
|
9
|
+
*
|
|
10
|
+
* Hand-typed against the protocol rather than pulled from @wallet-standard:
|
|
11
|
+
* the handshake is two events and one method, and a checkout page handling
|
|
12
|
+
* other people's money should ship as little third-party code as it can.
|
|
13
|
+
*
|
|
14
|
+
* The protocol: a wallet already loaded listens for `app-ready` and registers
|
|
15
|
+
* itself with the API it carries; a wallet that loads later dispatches
|
|
16
|
+
* `register-wallet` with a callback for the app to hand that API to. An app
|
|
17
|
+
* must do both or it misses one group or the other.
|
|
18
|
+
*/
|
|
19
|
+
/** One account a wallet has connected. */
|
|
20
|
+
export interface StandardAccount {
|
|
21
|
+
/** Base58, which is what this app wants. */
|
|
22
|
+
address: string;
|
|
23
|
+
chains: readonly string[];
|
|
24
|
+
features: readonly string[];
|
|
25
|
+
}
|
|
26
|
+
interface ConnectFeature {
|
|
27
|
+
connect(input?: {
|
|
28
|
+
silent?: boolean;
|
|
29
|
+
}): Promise<{
|
|
30
|
+
accounts: readonly StandardAccount[];
|
|
31
|
+
}>;
|
|
32
|
+
}
|
|
33
|
+
interface SignAndSendFeature {
|
|
34
|
+
signAndSendTransaction(...inputs: {
|
|
35
|
+
account: StandardAccount;
|
|
36
|
+
chain: string;
|
|
37
|
+
transaction: Uint8Array;
|
|
38
|
+
}[]): Promise<readonly {
|
|
39
|
+
signature: Uint8Array;
|
|
40
|
+
}[]>;
|
|
41
|
+
}
|
|
42
|
+
/** A wallet as the standard describes it. */
|
|
43
|
+
export interface StandardWallet {
|
|
44
|
+
name: string;
|
|
45
|
+
icon?: string;
|
|
46
|
+
version: string;
|
|
47
|
+
chains: readonly string[];
|
|
48
|
+
accounts: readonly StandardAccount[];
|
|
49
|
+
features: Record<string, unknown>;
|
|
50
|
+
}
|
|
51
|
+
export declare const CONNECT = "standard:connect";
|
|
52
|
+
export declare const SIGN_AND_SEND = "solana:signAndSendTransaction";
|
|
53
|
+
/**
|
|
54
|
+
* Whether this wallet can do what a checkout needs: connect, and sign and
|
|
55
|
+
* send a Solana transaction.
|
|
56
|
+
*
|
|
57
|
+
* Both are required. A wallet that can sign but not send would leave this
|
|
58
|
+
* page needing an RPC endpoint and a submission path of its own, which is
|
|
59
|
+
* exactly what the plan was built to avoid.
|
|
60
|
+
*/
|
|
61
|
+
export declare function usable(wallet: StandardWallet): boolean;
|
|
62
|
+
export declare function connectFeature(wallet: StandardWallet): ConnectFeature;
|
|
63
|
+
export declare function signFeature(wallet: StandardWallet): SignAndSendFeature;
|
|
64
|
+
export declare function disconnectFeature(wallet: StandardWallet): {
|
|
65
|
+
disconnect(): Promise<void>;
|
|
66
|
+
} | undefined;
|
|
67
|
+
export declare function eventsFeature(wallet: StandardWallet): {
|
|
68
|
+
on(event: string, listener: () => void): () => void;
|
|
69
|
+
} | undefined;
|
|
70
|
+
/**
|
|
71
|
+
* Collects the wallets registered in this page, now and as they arrive.
|
|
72
|
+
*
|
|
73
|
+
* Returns a cleanup function; callers must call it to drop the listener. The
|
|
74
|
+
* same contract as the EIP-6963 discovery beside it.
|
|
75
|
+
*/
|
|
76
|
+
export declare function discoverStandardWallets(onChange: (wallets: StandardWallet[]) => void): () => void;
|
|
77
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wallet-standard.d.ts","sourceRoot":"","sources":["../src/wallet-standard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,0CAA0C;AAC1C,MAAM,WAAW,eAAe;IAC/B,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;IACzB,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;CAC3B;AAED,UAAU,cAAc;IACvB,OAAO,CAAC,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC;QAC9C,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAA;KACpC,CAAC,CAAA;CACF;AAED,UAAU,kBAAkB;IAC3B,sBAAsB,CACrB,GAAG,MAAM,EAAE;QACV,OAAO,EAAE,eAAe,CAAA;QACxB,KAAK,EAAE,MAAM,CAAA;QACb,WAAW,EAAE,UAAU,CAAA;KACvB,EAAE,GACD,OAAO,CAAC,SAAS;QAAE,SAAS,EAAE,UAAU,CAAA;KAAE,EAAE,CAAC,CAAA;CAChD;AAED,6CAA6C;AAC7C,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;IACzB,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAA;IACpC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACjC;AAED,eAAO,MAAM,OAAO,qBAAqB,CAAA;AACzC,eAAO,MAAM,aAAa,kCAAkC,CAAA;AAI5D;;;;;;;GAOG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAMtD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,cAAc,CAErE;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,kBAAkB,CAEtE;AAED,wBAAgB,iBAAiB,CAChC,MAAM,EAAE,cAAc,GACpB;IAAE,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,GAAG,SAAS,CAE7C;AAED,wBAAgB,aAAa,CAC5B,MAAM,EAAE,cAAc,GACpB;IAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAA;CAAE,GAAG,SAAS,CAIrE;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACtC,QAAQ,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,IAAI,GAC3C,MAAM,IAAI,CAyCZ"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Solana wallet discovery through the Wallet Standard.
|
|
3
|
+
*
|
|
4
|
+
* The Solana equivalent of EIP-6963, and here for the same reason: sniffing
|
|
5
|
+
* globals finds only the wallets that claim one. MetaMask, Brave, Coinbase
|
|
6
|
+
* Wallet and others all sign Solana now, and they announce it this way rather
|
|
7
|
+
* than by injecting `window.solana`, so a list built from globals is a list
|
|
8
|
+
* of three wallets that is wrong about every other.
|
|
9
|
+
*
|
|
10
|
+
* Hand-typed against the protocol rather than pulled from @wallet-standard:
|
|
11
|
+
* the handshake is two events and one method, and a checkout page handling
|
|
12
|
+
* other people's money should ship as little third-party code as it can.
|
|
13
|
+
*
|
|
14
|
+
* The protocol: a wallet already loaded listens for `app-ready` and registers
|
|
15
|
+
* itself with the API it carries; a wallet that loads later dispatches
|
|
16
|
+
* `register-wallet` with a callback for the app to hand that API to. An app
|
|
17
|
+
* must do both or it misses one group or the other.
|
|
18
|
+
*/
|
|
19
|
+
export const CONNECT = 'standard:connect';
|
|
20
|
+
export const SIGN_AND_SEND = 'solana:signAndSendTransaction';
|
|
21
|
+
const DISCONNECT = 'standard:disconnect';
|
|
22
|
+
const EVENTS = 'standard:events';
|
|
23
|
+
/**
|
|
24
|
+
* Whether this wallet can do what a checkout needs: connect, and sign and
|
|
25
|
+
* send a Solana transaction.
|
|
26
|
+
*
|
|
27
|
+
* Both are required. A wallet that can sign but not send would leave this
|
|
28
|
+
* page needing an RPC endpoint and a submission path of its own, which is
|
|
29
|
+
* exactly what the plan was built to avoid.
|
|
30
|
+
*/
|
|
31
|
+
export function usable(wallet) {
|
|
32
|
+
return (Boolean(wallet.features?.[CONNECT])
|
|
33
|
+
&& Boolean(wallet.features?.[SIGN_AND_SEND])
|
|
34
|
+
&& wallet.chains.some((chain) => chain.startsWith('solana:')));
|
|
35
|
+
}
|
|
36
|
+
export function connectFeature(wallet) {
|
|
37
|
+
return wallet.features[CONNECT];
|
|
38
|
+
}
|
|
39
|
+
export function signFeature(wallet) {
|
|
40
|
+
return wallet.features[SIGN_AND_SEND];
|
|
41
|
+
}
|
|
42
|
+
export function disconnectFeature(wallet) {
|
|
43
|
+
return wallet.features[DISCONNECT];
|
|
44
|
+
}
|
|
45
|
+
export function eventsFeature(wallet) {
|
|
46
|
+
return wallet.features[EVENTS];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Collects the wallets registered in this page, now and as they arrive.
|
|
50
|
+
*
|
|
51
|
+
* Returns a cleanup function; callers must call it to drop the listener. The
|
|
52
|
+
* same contract as the EIP-6963 discovery beside it.
|
|
53
|
+
*/
|
|
54
|
+
export function discoverStandardWallets(onChange) {
|
|
55
|
+
const found = new Map();
|
|
56
|
+
function register(...wallets) {
|
|
57
|
+
let added = false;
|
|
58
|
+
for (const wallet of wallets) {
|
|
59
|
+
// Keyed by name: the standard has no stable id, and a wallet
|
|
60
|
+
// registering twice is a duplicate row rather than two wallets.
|
|
61
|
+
if (wallet?.name && !found.has(wallet.name)) {
|
|
62
|
+
found.set(wallet.name, wallet);
|
|
63
|
+
added = true;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (added) {
|
|
67
|
+
onChange([...found.values()]);
|
|
68
|
+
}
|
|
69
|
+
// The standard's register returns an unregister function. Nothing
|
|
70
|
+
// here unregisters anyone, so this is a no-op rather than a lie
|
|
71
|
+
// about what it does.
|
|
72
|
+
return () => undefined;
|
|
73
|
+
}
|
|
74
|
+
const api = Object.freeze({ register });
|
|
75
|
+
function onRegister(event) {
|
|
76
|
+
const callback = event.detail;
|
|
77
|
+
if (typeof callback === 'function') {
|
|
78
|
+
callback(api);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
window.addEventListener('wallet-standard:register-wallet', onRegister);
|
|
82
|
+
// Wakes the wallets that were already loaded when this page was: they
|
|
83
|
+
// listen for this and register themselves in response.
|
|
84
|
+
window.dispatchEvent(new CustomEvent('wallet-standard:app-ready', { detail: api }));
|
|
85
|
+
return () => {
|
|
86
|
+
window.removeEventListener('wallet-standard:register-wallet', onRegister);
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=wallet-standard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wallet-standard.js","sourceRoot":"","sources":["../src/wallet-standard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAoCH,MAAM,CAAC,MAAM,OAAO,GAAG,kBAAkB,CAAA;AACzC,MAAM,CAAC,MAAM,aAAa,GAAG,+BAA+B,CAAA;AAC5D,MAAM,UAAU,GAAG,qBAAqB,CAAA;AACxC,MAAM,MAAM,GAAG,iBAAiB,CAAA;AAEhC;;;;;;;GAOG;AACH,MAAM,UAAU,MAAM,CAAC,MAAsB;IAC5C,OAAO,CACN,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC;WAChC,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,CAAC;WACzC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAC7D,CAAA;AACF,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAsB;IACpD,OAAO,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAmB,CAAA;AAClD,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAsB;IACjD,OAAO,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAuB,CAAA;AAC5D,CAAC;AAED,MAAM,UAAU,iBAAiB,CAChC,MAAsB;IAEtB,OAAO,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAgD,CAAA;AAClF,CAAC;AAED,MAAM,UAAU,aAAa,CAC5B,MAAsB;IAEtB,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAEjB,CAAA;AACb,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CACtC,QAA6C;IAE7C,MAAM,KAAK,GAAG,IAAI,GAAG,EAA0B,CAAA;IAE/C,SAAS,QAAQ,CAAC,GAAG,OAAyB;QAC7C,IAAI,KAAK,GAAG,KAAK,CAAA;QACjB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC9B,6DAA6D;YAC7D,gEAAgE;YAChE,IAAI,MAAM,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC7C,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;gBAC9B,KAAK,GAAG,IAAI,CAAA;YACb,CAAC;QACF,CAAC;QACD,IAAI,KAAK,EAAE,CAAC;YACX,QAAQ,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QAC9B,CAAC;QACD,kEAAkE;QAClE,gEAAgE;QAChE,sBAAsB;QACtB,OAAO,GAAG,EAAE,CAAC,SAAS,CAAA;IACvB,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAA;IAEvC,SAAS,UAAU,CAAC,KAAY;QAC/B,MAAM,QAAQ,GAAI,KAA6C,CAAC,MAAM,CAAA;QACtE,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;YACpC,QAAQ,CAAC,GAAG,CAAC,CAAA;QACd,CAAC;IACF,CAAC;IAED,MAAM,CAAC,gBAAgB,CAAC,iCAAiC,EAAE,UAAU,CAAC,CAAA;IACtE,sEAAsE;IACtE,uDAAuD;IACvD,MAAM,CAAC,aAAa,CACnB,IAAI,WAAW,CAAC,2BAA2B,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAC7D,CAAA;IAED,OAAO,GAAG,EAAE;QACX,MAAM,CAAC,mBAAmB,CAAC,iCAAiC,EAAE,UAAU,CAAC,CAAA;IAC1E,CAAC,CAAA;AACF,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { Eip1193Provider } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Connecting a wallet that puts nothing into the page.
|
|
4
|
+
*
|
|
5
|
+
* Safe, Kraken, BitPay, Bitcoin.com and Blockchain.com inject no provider and
|
|
6
|
+
* have no dapp browser to open this page in. They reach an app over
|
|
7
|
+
* WalletConnect instead: the page and the wallet pass messages through a
|
|
8
|
+
* relay, paired by a code the payer scans or a link their phone opens, and
|
|
9
|
+
* the payment is approved in the wallet.
|
|
10
|
+
*
|
|
11
|
+
* The SDK is loaded only when one of those is chosen. It is far larger than
|
|
12
|
+
* the rest of this checkout put together, and a payer using an extension
|
|
13
|
+
* should never pay for bytes they do not use.
|
|
14
|
+
*
|
|
15
|
+
* What comes back is an ordinary EIP-1193 provider, so everything after the
|
|
16
|
+
* connection, signing, switching network, watching for an account change,
|
|
17
|
+
* is the same code that serves an injected wallet.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* What the wallet prints on its approval screen.
|
|
21
|
+
*
|
|
22
|
+
* Reclack's own by default, branded checkout or not: this names who the
|
|
23
|
+
* session is with, and the session is with Reclack. A host that is not
|
|
24
|
+
* Reclack, a partner embedding this kit, passes its own.
|
|
25
|
+
*
|
|
26
|
+
* The icon was once the USDC mark, which is why a payer approving in Binance
|
|
27
|
+
* was shown a dollar coin above our name: the wallet draws exactly what it is
|
|
28
|
+
* sent. A PNG comes first and the SVG behind it, because wallets take the
|
|
29
|
+
* first icon they can decode and a wallet application draws these with the
|
|
30
|
+
* platform's own image loader rather than a browser, which is not always told
|
|
31
|
+
* about SVG.
|
|
32
|
+
*/
|
|
33
|
+
export interface SessionMetadata {
|
|
34
|
+
name: string;
|
|
35
|
+
description: string;
|
|
36
|
+
url: string;
|
|
37
|
+
icons: string[];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Where the pairing is made, and what the wallet is told about who is asking.
|
|
41
|
+
*
|
|
42
|
+
* The project id is public by design: it identifies the page to the relay and
|
|
43
|
+
* carries no authority. It is an option rather than an environment variable
|
|
44
|
+
* because this package is built once and run by several hosts, each with its
|
|
45
|
+
* own. Without one, WalletConnect is simply not offered.
|
|
46
|
+
*/
|
|
47
|
+
export interface WalletConnectOptions {
|
|
48
|
+
projectId: string;
|
|
49
|
+
metadata?: SessionMetadata;
|
|
50
|
+
}
|
|
51
|
+
/** Reclack's own session metadata, derived from wherever this is served. */
|
|
52
|
+
export declare function defaultMetadata(): SessionMetadata;
|
|
53
|
+
/** Whether a host has given this kit what a session needs. */
|
|
54
|
+
export declare function walletConnectReady(options: WalletConnectOptions | undefined): boolean;
|
|
55
|
+
export interface RemoteSession {
|
|
56
|
+
provider: Eip1193Provider;
|
|
57
|
+
address: string;
|
|
58
|
+
chainId: number;
|
|
59
|
+
/** Ends the session. A pairing the payer walked away from must not linger. */
|
|
60
|
+
close: () => Promise<void>;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Pairs with a wallet and waits for the payer to approve.
|
|
64
|
+
*
|
|
65
|
+
* `onUri` is called once with the pairing string, which is what the code and
|
|
66
|
+
* the link are made of. It arrives before the payer has done anything, so the
|
|
67
|
+
* caller can show it while this promise is still pending.
|
|
68
|
+
*
|
|
69
|
+
* The chain is optional rather than required. A wallet that does not have it
|
|
70
|
+
* would otherwise refuse the pairing outright, which reads as "this wallet is
|
|
71
|
+
* broken"; connecting first and asking it to switch afterwards is the same
|
|
72
|
+
* path an injected wallet on the wrong network already takes.
|
|
73
|
+
*/
|
|
74
|
+
export declare function openWalletConnectSession(options: WalletConnectOptions, chainId: number, onUri: (uri: string) => void): Promise<RemoteSession>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walletconnect.d.ts","sourceRoot":"","sources":["../src/walletconnect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,EAAE,CAAA;CACf;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,oBAAoB;IACpC,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,eAAe,CAAA;CAC1B;AAED,4EAA4E;AAC5E,wBAAgB,eAAe,IAAI,eAAe,CAWjD;AAyBD,8DAA8D;AAC9D,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,oBAAoB,GAAG,SAAS,GAAG,OAAO,CAErF;AAED,MAAM,WAAW,aAAa;IAC7B,QAAQ,EAAE,eAAe,CAAA;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,8EAA8E;IAC9E,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1B;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,wBAAwB,CAC7C,OAAO,EAAE,oBAAoB,EAC7B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC1B,OAAO,CAAC,aAAa,CAAC,CA0FxB"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { WalletError } from "./errors.js";
|
|
2
|
+
/** Reclack's own session metadata, derived from wherever this is served. */
|
|
3
|
+
export function defaultMetadata() {
|
|
4
|
+
// The frame's origin, not the page's, when this runs embedded. That is
|
|
5
|
+
// correct: the icons have to be fetchable, and only this origin is known
|
|
6
|
+
// to serve them.
|
|
7
|
+
const origin = typeof window === "undefined" ? "" : window.location.origin;
|
|
8
|
+
return {
|
|
9
|
+
name: "Reclack",
|
|
10
|
+
description: "Pay using stablecoins",
|
|
11
|
+
url: origin,
|
|
12
|
+
icons: [`${origin}/apple-touch-icon.png`, `${origin}/favicon.svg`],
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* How long to wait for the relay before giving up on it.
|
|
17
|
+
*
|
|
18
|
+
* Neither of the two waits below is the payer's. Reaching the relay and being
|
|
19
|
+
* handed a pairing code happen before anybody is asked to do anything, so a
|
|
20
|
+
* relay that never answers is a failure, not somebody taking their time.
|
|
21
|
+
* Approving in the wallet is the payer's wait and is never timed.
|
|
22
|
+
*
|
|
23
|
+
* Unbounded, this was a spinner that never stopped: a project id the relay
|
|
24
|
+
* refuses, or a blocked WebSocket, and the panel sat on "Preparing a
|
|
25
|
+
* connection..." with nothing to press.
|
|
26
|
+
*/
|
|
27
|
+
const RELAY_TIMEOUT = 12_000;
|
|
28
|
+
/** Rejects if `work` has not settled in time, leaving `work` to its fate. */
|
|
29
|
+
function within(work, ms, message) {
|
|
30
|
+
let timer;
|
|
31
|
+
const limit = new Promise((_, reject) => {
|
|
32
|
+
timer = setTimeout(() => reject(new WalletError(message)), ms);
|
|
33
|
+
});
|
|
34
|
+
return Promise.race([work, limit]).finally(() => clearTimeout(timer));
|
|
35
|
+
}
|
|
36
|
+
/** Whether a host has given this kit what a session needs. */
|
|
37
|
+
export function walletConnectReady(options) {
|
|
38
|
+
return Boolean(options?.projectId?.trim());
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Pairs with a wallet and waits for the payer to approve.
|
|
42
|
+
*
|
|
43
|
+
* `onUri` is called once with the pairing string, which is what the code and
|
|
44
|
+
* the link are made of. It arrives before the payer has done anything, so the
|
|
45
|
+
* caller can show it while this promise is still pending.
|
|
46
|
+
*
|
|
47
|
+
* The chain is optional rather than required. A wallet that does not have it
|
|
48
|
+
* would otherwise refuse the pairing outright, which reads as "this wallet is
|
|
49
|
+
* broken"; connecting first and asking it to switch afterwards is the same
|
|
50
|
+
* path an injected wallet on the wrong network already takes.
|
|
51
|
+
*/
|
|
52
|
+
export async function openWalletConnectSession(options, chainId, onUri) {
|
|
53
|
+
if (!walletConnectReady(options)) {
|
|
54
|
+
throw new Error("WalletConnect is not configured for this checkout.");
|
|
55
|
+
}
|
|
56
|
+
const { EthereumProvider } = await import("@walletconnect/ethereum-provider");
|
|
57
|
+
// Bounded: init opens the relay socket, and a socket that cannot be
|
|
58
|
+
// opened leaves this pending rather than throwing.
|
|
59
|
+
const provider = await within(EthereumProvider.init({
|
|
60
|
+
projectId: options.projectId.trim(),
|
|
61
|
+
optionalChains: [chainId],
|
|
62
|
+
// Our own code and our own panel. The bundled modal would be a second
|
|
63
|
+
// design to keep in step with this one, and it is most of the weight.
|
|
64
|
+
showQrModal: false,
|
|
65
|
+
// What the wallet prints on the approval screen. See SessionMetadata.
|
|
66
|
+
metadata: options.metadata ?? defaultMetadata(),
|
|
67
|
+
}), RELAY_TIMEOUT, "Could not reach the connection service. Check your network and try again.");
|
|
68
|
+
const close = async () => {
|
|
69
|
+
try {
|
|
70
|
+
await provider.disconnect();
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// Already gone, or the relay is unreachable. Nothing to undo.
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
// A session the browser still holds from a previous visit. Reusing it
|
|
77
|
+
// saves the payer scanning anything, which is the whole point of the
|
|
78
|
+
// wallet having remembered it.
|
|
79
|
+
if (provider.session && provider.accounts.length > 0) {
|
|
80
|
+
return {
|
|
81
|
+
provider: provider,
|
|
82
|
+
address: provider.accounts[0],
|
|
83
|
+
chainId: provider.chainId,
|
|
84
|
+
close,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
// Two waits, and only the first is bounded. The code has to arrive before
|
|
88
|
+
// anybody can scan it; what happens after is the payer deciding, and a
|
|
89
|
+
// wallet may sit on that for as long as they like.
|
|
90
|
+
let issued = false;
|
|
91
|
+
const handleUri = (uri) => {
|
|
92
|
+
issued = true;
|
|
93
|
+
onUri(uri);
|
|
94
|
+
};
|
|
95
|
+
provider.on("display_uri", handleUri);
|
|
96
|
+
const approved = provider.connect();
|
|
97
|
+
// Nothing rethrows this on its own: it is raced below, and an unhandled
|
|
98
|
+
// rejection here would be reported before the race reports it.
|
|
99
|
+
approved.catch(() => undefined);
|
|
100
|
+
let watchdog;
|
|
101
|
+
try {
|
|
102
|
+
await Promise.race([
|
|
103
|
+
approved,
|
|
104
|
+
new Promise((_, reject) => {
|
|
105
|
+
watchdog = setTimeout(() => {
|
|
106
|
+
if (!issued) {
|
|
107
|
+
reject(new WalletError("The connection code did not arrive. Try again."));
|
|
108
|
+
}
|
|
109
|
+
}, RELAY_TIMEOUT);
|
|
110
|
+
}),
|
|
111
|
+
]);
|
|
112
|
+
}
|
|
113
|
+
catch (failure) {
|
|
114
|
+
await close();
|
|
115
|
+
throw failure;
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
clearTimeout(watchdog);
|
|
119
|
+
provider.removeListener("display_uri", handleUri);
|
|
120
|
+
}
|
|
121
|
+
const address = provider.accounts[0];
|
|
122
|
+
if (!address) {
|
|
123
|
+
await close();
|
|
124
|
+
throw new Error("No account was shared by the wallet.");
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
provider: provider,
|
|
128
|
+
address,
|
|
129
|
+
chainId: provider.chainId,
|
|
130
|
+
close,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=walletconnect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walletconnect.js","sourceRoot":"","sources":["../src/walletconnect.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,74 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reclack/walletkit",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Connect a wallet, read an address, read a balance. Framework-free, no wallet SDK, no dependencies.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Reclack",
|
|
7
|
+
"homepage": "https://github.com/reclack/walletkit#readme",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/reclack/walletkit.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/reclack/walletkit/issues"
|
|
14
|
+
},
|
|
15
|
+
"type": "module",
|
|
16
|
+
"sideEffects": [
|
|
17
|
+
"./dist/element.js",
|
|
18
|
+
"./src/element/index.ts"
|
|
19
|
+
],
|
|
20
|
+
"keywords": [
|
|
21
|
+
"wallet",
|
|
22
|
+
"ethereum",
|
|
23
|
+
"solana",
|
|
24
|
+
"eip-1193",
|
|
25
|
+
"eip-6963",
|
|
26
|
+
"walletconnect",
|
|
27
|
+
"stablecoin",
|
|
28
|
+
"usdc"
|
|
29
|
+
],
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"default": "./dist/index.js"
|
|
34
|
+
},
|
|
35
|
+
"./assets/*": "./assets/*",
|
|
36
|
+
"./package.json": "./package.json",
|
|
37
|
+
"./element": {
|
|
38
|
+
"types": "./dist/element/index.d.ts",
|
|
39
|
+
"default": "./dist/element.js"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"files": [
|
|
43
|
+
"dist",
|
|
44
|
+
"assets",
|
|
45
|
+
"custom-elements.json",
|
|
46
|
+
"vscode.html-custom-data.json",
|
|
47
|
+
"README.md",
|
|
48
|
+
"LICENSE"
|
|
49
|
+
],
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public"
|
|
52
|
+
},
|
|
53
|
+
"engines": {
|
|
54
|
+
"node": ">=18"
|
|
55
|
+
},
|
|
56
|
+
"dependencies": {
|
|
57
|
+
"@walletconnect/ethereum-provider": "2.26.0"
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@preact/preset-vite": "^2.10.6",
|
|
61
|
+
"preact": "^10.29.8",
|
|
62
|
+
"typescript": "~5.9.3",
|
|
63
|
+
"uqr": "^0.1.3",
|
|
64
|
+
"vite": "^8.3.7",
|
|
65
|
+
"vitest": "^3.2.4"
|
|
66
|
+
},
|
|
67
|
+
"customElements": "custom-elements.json",
|
|
68
|
+
"scripts": {
|
|
69
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json && tsc -p tsconfig.element.json && vite build",
|
|
70
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
71
|
+
"test": "vitest run",
|
|
72
|
+
"playground": "node playground/build.mjs"
|
|
73
|
+
}
|
|
6
74
|
}
|