@hot-labs/kit 1.0.33

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.
Files changed (300) hide show
  1. package/.eslintrc.cjs +11 -0
  2. package/.github/workflows/deploy-example.yml +55 -0
  3. package/.github/workflows/release.yml +74 -0
  4. package/.prettierrc +4 -0
  5. package/.prototools +2 -0
  6. package/.vscode/settings.json +3 -0
  7. package/CHANGELOG.md +1 -0
  8. package/README.md +67 -0
  9. package/build/GoogleConnector.d.ts +20 -0
  10. package/build/GoogleConnector.js +76 -0
  11. package/build/GoogleConnector.js.map +1 -0
  12. package/build/HotConnector.d.ts +91 -0
  13. package/build/HotConnector.js +285 -0
  14. package/build/HotConnector.js.map +1 -0
  15. package/build/OmniConnector.d.ts +95 -0
  16. package/build/OmniConnector.js +123 -0
  17. package/build/OmniConnector.js.map +1 -0
  18. package/build/OmniWallet.d.ts +57 -0
  19. package/build/OmniWallet.js +56 -0
  20. package/build/OmniWallet.js.map +1 -0
  21. package/build/cosmos/connector.d.ts +53 -0
  22. package/build/cosmos/connector.js +207 -0
  23. package/build/cosmos/connector.js.map +1 -0
  24. package/build/cosmos/wallet.d.ts +28 -0
  25. package/build/cosmos/wallet.js +59 -0
  26. package/build/cosmos/wallet.js.map +1 -0
  27. package/build/events.d.ts +42 -0
  28. package/build/events.js +64 -0
  29. package/build/events.js.map +1 -0
  30. package/build/evm/abi.d.ts +17 -0
  31. package/build/evm/abi.js +38 -0
  32. package/build/evm/abi.js.map +1 -0
  33. package/build/evm/connector.d.ts +35 -0
  34. package/build/evm/connector.js +124 -0
  35. package/build/evm/connector.js.map +1 -0
  36. package/build/evm/wallet.d.ts +47 -0
  37. package/build/evm/wallet.js +136 -0
  38. package/build/evm/wallet.js.map +1 -0
  39. package/build/exchange.d.ts +63 -0
  40. package/build/exchange.js +384 -0
  41. package/build/exchange.js.map +1 -0
  42. package/build/hot-wallet/evm.d.ts +1 -0
  43. package/build/hot-wallet/evm.js +33 -0
  44. package/build/hot-wallet/evm.js.map +1 -0
  45. package/build/hot-wallet/hot.d.ts +3 -0
  46. package/build/hot-wallet/hot.js +40 -0
  47. package/build/hot-wallet/hot.js.map +1 -0
  48. package/build/hot-wallet/index.d.ts +4 -0
  49. package/build/hot-wallet/index.js +5 -0
  50. package/build/hot-wallet/index.js.map +1 -0
  51. package/build/hot-wallet/solana/account.d.ts +11 -0
  52. package/build/hot-wallet/solana/account.js +42 -0
  53. package/build/hot-wallet/solana/account.js.map +1 -0
  54. package/build/hot-wallet/solana/index.d.ts +1 -0
  55. package/build/hot-wallet/solana/index.js +85 -0
  56. package/build/hot-wallet/solana/index.js.map +1 -0
  57. package/build/hot-wallet/solana/register.d.ts +2 -0
  58. package/build/hot-wallet/solana/register.js +41 -0
  59. package/build/hot-wallet/solana/register.js.map +1 -0
  60. package/build/hot-wallet/solana/solana-wallet.d.ts +34 -0
  61. package/build/hot-wallet/solana/solana-wallet.js +223 -0
  62. package/build/hot-wallet/solana/solana-wallet.js.map +1 -0
  63. package/build/hot-wallet/solana/utils.d.ts +32 -0
  64. package/build/hot-wallet/solana/utils.js +36 -0
  65. package/build/hot-wallet/solana/utils.js.map +1 -0
  66. package/build/hot-wallet/stellar.d.ts +38 -0
  67. package/build/hot-wallet/stellar.js +32 -0
  68. package/build/hot-wallet/stellar.js.map +1 -0
  69. package/build/hot-wallet/ton.d.ts +1 -0
  70. package/build/hot-wallet/ton.js +49 -0
  71. package/build/hot-wallet/ton.js.map +1 -0
  72. package/build/hot-wallet/wallet.d.ts +1 -0
  73. package/build/hot-wallet/wallet.js +40 -0
  74. package/build/hot-wallet/wallet.js.map +1 -0
  75. package/build/index.d.ts +24 -0
  76. package/build/index.js +25 -0
  77. package/build/index.js.map +1 -0
  78. package/build/near/connector.d.ts +28 -0
  79. package/build/near/connector.js +56 -0
  80. package/build/near/connector.js.map +1 -0
  81. package/build/near/wallet.d.ts +62 -0
  82. package/build/near/wallet.js +233 -0
  83. package/build/near/wallet.js.map +1 -0
  84. package/build/omni/Intents.d.ts +93 -0
  85. package/build/omni/Intents.js +395 -0
  86. package/build/omni/Intents.js.map +1 -0
  87. package/build/omni/bridge.d.ts +3 -0
  88. package/build/omni/bridge.js +34 -0
  89. package/build/omni/bridge.js.map +1 -0
  90. package/build/omni/config.d.ts +99 -0
  91. package/build/omni/config.js +126 -0
  92. package/build/omni/config.js.map +1 -0
  93. package/build/omni/defaultTokens.d.ts +17 -0
  94. package/build/omni/defaultTokens.js +1079 -0
  95. package/build/omni/defaultTokens.js.map +1 -0
  96. package/build/omni/index.d.ts +8 -0
  97. package/build/omni/index.js +9 -0
  98. package/build/omni/index.js.map +1 -0
  99. package/build/omni/nearRpc.d.ts +24 -0
  100. package/build/omni/nearRpc.js +167 -0
  101. package/build/omni/nearRpc.js.map +1 -0
  102. package/build/omni/recipient.d.ts +10 -0
  103. package/build/omni/recipient.js +40 -0
  104. package/build/omni/recipient.js.map +1 -0
  105. package/build/omni/token.d.ts +36 -0
  106. package/build/omni/token.js +136 -0
  107. package/build/omni/token.js.map +1 -0
  108. package/build/omni/tokens.d.ts +14 -0
  109. package/build/omni/tokens.js +57 -0
  110. package/build/omni/tokens.js.map +1 -0
  111. package/build/omni/types.d.ts +41 -0
  112. package/build/omni/types.js +2 -0
  113. package/build/omni/types.js.map +1 -0
  114. package/build/omni/utils.d.ts +24 -0
  115. package/build/omni/utils.js +150 -0
  116. package/build/omni/utils.js.map +1 -0
  117. package/build/settings.d.ts +5 -0
  118. package/build/settings.js +6 -0
  119. package/build/settings.js.map +1 -0
  120. package/build/solana/connector.d.ts +31 -0
  121. package/build/solana/connector.js +138 -0
  122. package/build/solana/connector.js.map +1 -0
  123. package/build/solana/protocol.d.ts +25 -0
  124. package/build/solana/protocol.js +56 -0
  125. package/build/solana/protocol.js.map +1 -0
  126. package/build/solana/wallet.d.ts +47 -0
  127. package/build/solana/wallet.js +188 -0
  128. package/build/solana/wallet.js.map +1 -0
  129. package/build/solana/wallets.d.ts +102 -0
  130. package/build/solana/wallets.js +150 -0
  131. package/build/solana/wallets.js.map +1 -0
  132. package/build/stellar/connector.d.ts +25 -0
  133. package/build/stellar/connector.js +56 -0
  134. package/build/stellar/connector.js.map +1 -0
  135. package/build/stellar/wallet.d.ts +70 -0
  136. package/build/stellar/wallet.js +225 -0
  137. package/build/stellar/wallet.js.map +1 -0
  138. package/build/storage.d.ts +10 -0
  139. package/build/storage.js +12 -0
  140. package/build/storage.js.map +1 -0
  141. package/build/ton/connector.d.ts +25 -0
  142. package/build/ton/connector.js +119 -0
  143. package/build/ton/connector.js.map +1 -0
  144. package/build/ton/utils.d.ts +45 -0
  145. package/build/ton/utils.js +64 -0
  146. package/build/ton/utils.js.map +1 -0
  147. package/build/ton/wallet.d.ts +70 -0
  148. package/build/ton/wallet.js +154 -0
  149. package/build/ton/wallet.js.map +1 -0
  150. package/build/ui/Popup.d.ts +10 -0
  151. package/build/ui/Popup.js +38 -0
  152. package/build/ui/Popup.js.map +1 -0
  153. package/build/ui/connect/AuthPopup.d.ts +2 -0
  154. package/build/ui/connect/AuthPopup.js +48 -0
  155. package/build/ui/connect/AuthPopup.js.map +1 -0
  156. package/build/ui/connect/ConnectWallet.d.ts +9 -0
  157. package/build/ui/connect/ConnectWallet.js +22 -0
  158. package/build/ui/connect/ConnectWallet.js.map +1 -0
  159. package/build/ui/connect/LogoutPopup.d.ts +10 -0
  160. package/build/ui/connect/LogoutPopup.js +8 -0
  161. package/build/ui/connect/LogoutPopup.js.map +1 -0
  162. package/build/ui/connect/WCPopup.d.ts +13 -0
  163. package/build/ui/connect/WCPopup.js +81 -0
  164. package/build/ui/connect/WCPopup.js.map +1 -0
  165. package/build/ui/connect/WCRequest.d.ts +9 -0
  166. package/build/ui/connect/WCRequest.js +13 -0
  167. package/build/ui/connect/WCRequest.js.map +1 -0
  168. package/build/ui/connect/WalletPicker.d.ts +11 -0
  169. package/build/ui/connect/WalletPicker.js +48 -0
  170. package/build/ui/connect/WalletPicker.js.map +1 -0
  171. package/build/ui/icons/arrow-right.d.ts +1 -0
  172. package/build/ui/icons/arrow-right.js +5 -0
  173. package/build/ui/icons/arrow-right.js.map +1 -0
  174. package/build/ui/icons/exchange.d.ts +6 -0
  175. package/build/ui/icons/exchange.js +6 -0
  176. package/build/ui/icons/exchange.js.map +1 -0
  177. package/build/ui/icons/logout.d.ts +1 -0
  178. package/build/ui/icons/logout.js +3 -0
  179. package/build/ui/icons/logout.js.map +1 -0
  180. package/build/ui/icons/pending.d.ts +1 -0
  181. package/build/ui/icons/pending.js +5 -0
  182. package/build/ui/icons/pending.js.map +1 -0
  183. package/build/ui/icons/qr.d.ts +1 -0
  184. package/build/ui/icons/qr.js +5 -0
  185. package/build/ui/icons/qr.js.map +1 -0
  186. package/build/ui/icons/search.d.ts +1 -0
  187. package/build/ui/icons/search.js +5 -0
  188. package/build/ui/icons/search.js.map +1 -0
  189. package/build/ui/icons/switch.d.ts +1 -0
  190. package/build/ui/icons/switch.js +5 -0
  191. package/build/ui/icons/switch.js.map +1 -0
  192. package/build/ui/icons/wallet.d.ts +1 -0
  193. package/build/ui/icons/wallet.js +5 -0
  194. package/build/ui/icons/wallet.js.map +1 -0
  195. package/build/ui/payment/Bridge.d.ts +27 -0
  196. package/build/ui/payment/Bridge.js +340 -0
  197. package/build/ui/payment/Bridge.js.map +1 -0
  198. package/build/ui/payment/DepositQR.d.ts +9 -0
  199. package/build/ui/payment/DepositQR.js +56 -0
  200. package/build/ui/payment/DepositQR.js.map +1 -0
  201. package/build/ui/payment/Payment.d.ts +16 -0
  202. package/build/ui/payment/Payment.js +50 -0
  203. package/build/ui/payment/Payment.js.map +1 -0
  204. package/build/ui/payment/Profile.d.ts +7 -0
  205. package/build/ui/payment/Profile.js +88 -0
  206. package/build/ui/payment/Profile.js.map +1 -0
  207. package/build/ui/payment/SelectRecipient.d.ts +14 -0
  208. package/build/ui/payment/SelectRecipient.js +68 -0
  209. package/build/ui/payment/SelectRecipient.js.map +1 -0
  210. package/build/ui/payment/SelectSender.d.ts +13 -0
  211. package/build/ui/payment/SelectSender.js +23 -0
  212. package/build/ui/payment/SelectSender.js.map +1 -0
  213. package/build/ui/payment/SelectToken.d.ts +13 -0
  214. package/build/ui/payment/SelectToken.js +92 -0
  215. package/build/ui/payment/SelectToken.js.map +1 -0
  216. package/build/ui/payment/TokenCard.d.ts +23 -0
  217. package/build/ui/payment/TokenCard.js +50 -0
  218. package/build/ui/payment/TokenCard.js.map +1 -0
  219. package/build/ui/router.d.ts +37 -0
  220. package/build/ui/router.js +56 -0
  221. package/build/ui/router.js.map +1 -0
  222. package/build/ui/styles.d.ts +11 -0
  223. package/build/ui/styles.js +273 -0
  224. package/build/ui/styles.js.map +1 -0
  225. package/package.json +60 -0
  226. package/skill.md +989 -0
  227. package/src/GoogleConnector.ts +102 -0
  228. package/src/HotConnector.ts +344 -0
  229. package/src/OmniConnector.ts +161 -0
  230. package/src/OmniWallet.ts +94 -0
  231. package/src/cosmos/connector.ts +242 -0
  232. package/src/cosmos/wallet.ts +77 -0
  233. package/src/events.ts +66 -0
  234. package/src/evm/abi.ts +39 -0
  235. package/src/evm/connector.ts +139 -0
  236. package/src/evm/wallet.ts +156 -0
  237. package/src/exchange.ts +426 -0
  238. package/src/hot-wallet/evm.ts +38 -0
  239. package/src/hot-wallet/hot.ts +39 -0
  240. package/src/hot-wallet/index.ts +4 -0
  241. package/src/hot-wallet/solana/account.ts +52 -0
  242. package/src/hot-wallet/solana/index.ts +98 -0
  243. package/src/hot-wallet/solana/register.ts +48 -0
  244. package/src/hot-wallet/solana/solana-wallet.ts +280 -0
  245. package/src/hot-wallet/solana/utils.ts +56 -0
  246. package/src/hot-wallet/stellar.ts +39 -0
  247. package/src/hot-wallet/ton.ts +56 -0
  248. package/src/hot-wallet/wallet.ts +44 -0
  249. package/src/index.ts +30 -0
  250. package/src/near/connector.ts +71 -0
  251. package/src/near/wallet.ts +255 -0
  252. package/src/omni/Intents.ts +454 -0
  253. package/src/omni/bridge.ts +38 -0
  254. package/src/omni/config.ts +130 -0
  255. package/src/omni/defaultTokens.ts +1078 -0
  256. package/src/omni/index.ts +8 -0
  257. package/src/omni/nearRpc.ts +187 -0
  258. package/src/omni/recipient.ts +41 -0
  259. package/src/omni/token.ts +125 -0
  260. package/src/omni/tokens.ts +68 -0
  261. package/src/omni/types.ts +46 -0
  262. package/src/omni/utils.ts +163 -0
  263. package/src/settings.ts +5 -0
  264. package/src/solana/connector.ts +151 -0
  265. package/src/solana/protocol.ts +66 -0
  266. package/src/solana/wallet.ts +230 -0
  267. package/src/solana/wallets.ts +243 -0
  268. package/src/stellar/connector.ts +69 -0
  269. package/src/stellar/wallet.ts +267 -0
  270. package/src/storage.ts +19 -0
  271. package/src/ton/connector.ts +138 -0
  272. package/src/ton/utils.ts +73 -0
  273. package/src/ton/wallet.ts +178 -0
  274. package/src/ui/Popup.tsx +62 -0
  275. package/src/ui/connect/AuthPopup.tsx +78 -0
  276. package/src/ui/connect/ConnectWallet.tsx +63 -0
  277. package/src/ui/connect/LogoutPopup.tsx +20 -0
  278. package/src/ui/connect/WCPopup.tsx +122 -0
  279. package/src/ui/connect/WCRequest.tsx +28 -0
  280. package/src/ui/connect/WalletPicker.tsx +92 -0
  281. package/src/ui/icons/arrow-right.tsx +8 -0
  282. package/src/ui/icons/exchange.tsx +17 -0
  283. package/src/ui/icons/logout.tsx +18 -0
  284. package/src/ui/icons/pending.tsx +18 -0
  285. package/src/ui/icons/qr.tsx +12 -0
  286. package/src/ui/icons/search.tsx +18 -0
  287. package/src/ui/icons/switch.tsx +10 -0
  288. package/src/ui/icons/wallet.tsx +18 -0
  289. package/src/ui/payment/Bridge.tsx +582 -0
  290. package/src/ui/payment/DepositQR.tsx +88 -0
  291. package/src/ui/payment/Payment.tsx +78 -0
  292. package/src/ui/payment/Profile.tsx +140 -0
  293. package/src/ui/payment/SelectRecipient.tsx +111 -0
  294. package/src/ui/payment/SelectSender.tsx +60 -0
  295. package/src/ui/payment/SelectToken.tsx +134 -0
  296. package/src/ui/payment/TokenCard.tsx +83 -0
  297. package/src/ui/router.tsx +92 -0
  298. package/src/ui/styles.ts +284 -0
  299. package/tsconfig.json +22 -0
  300. package/vite.config.ts +17 -0
@@ -0,0 +1,52 @@
1
+ import { SolanaSignAndSendTransaction, SolanaSignMessage, SolanaSignTransaction } from "@solana/wallet-standard-features";
2
+ import type { WalletAccount } from "@wallet-standard/base";
3
+ import { SOLANA_CHAINS } from "./utils";
4
+
5
+ const chains = SOLANA_CHAINS;
6
+ const features = [SolanaSignAndSendTransaction, SolanaSignTransaction, SolanaSignMessage] as const;
7
+
8
+ export class GhostWalletAccount implements WalletAccount {
9
+ readonly #address: WalletAccount["address"];
10
+ readonly #publicKey: WalletAccount["publicKey"];
11
+ readonly #chains: WalletAccount["chains"];
12
+ readonly #features: WalletAccount["features"];
13
+ readonly #label: WalletAccount["label"];
14
+ readonly #icon: WalletAccount["icon"];
15
+
16
+ get address() {
17
+ return this.#address;
18
+ }
19
+
20
+ get publicKey() {
21
+ return this.#publicKey.slice();
22
+ }
23
+
24
+ get chains() {
25
+ return this.#chains.slice();
26
+ }
27
+
28
+ get features() {
29
+ return this.#features.slice();
30
+ }
31
+
32
+ get label() {
33
+ return this.#label;
34
+ }
35
+
36
+ get icon() {
37
+ return this.#icon;
38
+ }
39
+
40
+ constructor({ address, publicKey, label, icon }: Omit<WalletAccount, "chains" | "features">) {
41
+ if (new.target === GhostWalletAccount) {
42
+ Object.freeze(this);
43
+ }
44
+
45
+ this.#address = address;
46
+ this.#publicKey = publicKey;
47
+ this.#chains = chains;
48
+ this.#features = features;
49
+ this.#label = label;
50
+ this.#icon = icon;
51
+ }
52
+ }
@@ -0,0 +1,98 @@
1
+ import { Transaction, VersionedTransaction, PublicKey } from "@solana/web3.js";
2
+
3
+ import { isInjected, requestHot } from "../hot";
4
+ import { registerWallet } from "./register";
5
+ import { GhostWallet } from "./solana-wallet";
6
+
7
+ const deserializeTransaction = (base64: string | Buffer) => {
8
+ let buf = Buffer.alloc(0);
9
+ if (Buffer.isBuffer(base64)) {
10
+ buf = Buffer.from(base64);
11
+ } else {
12
+ const parts = base64.split(",");
13
+ if (parts.every((t) => !isNaN(Number(t)))) buf = Buffer.from(new Uint8Array(parts.map((t) => Number(t))));
14
+ else buf = Buffer.from(base64, "base64");
15
+ }
16
+
17
+ try {
18
+ return VersionedTransaction.deserialize(buf);
19
+ } catch (e) {
20
+ return Transaction.from(buf);
21
+ }
22
+ };
23
+
24
+ const hotSolana = {
25
+ publicKey: null as PublicKey | null,
26
+
27
+ async connect(options: any) {
28
+ const { publicKey } = await requestHot("solana:connect", options);
29
+ hotSolana.publicKey = new PublicKey(publicKey);
30
+ return { publicKey: hotSolana.publicKey };
31
+ },
32
+
33
+ async disconnect() {
34
+ return await requestHot("solana:disconnect", {});
35
+ },
36
+
37
+ async signAllTransactions(transactions: any[]) {
38
+ const result = await requestHot("solana:signAllTransactions", {
39
+ transactions: transactions.map((t) => t.serialize().toString("base64")),
40
+ });
41
+
42
+ return result.transactions.map((t: any) => deserializeTransaction(t));
43
+ },
44
+
45
+ async signTransaction(transaction: any) {
46
+ const result = await requestHot("solana:signAllTransactions", {
47
+ transactions: [transaction.serialize().toString("base64")],
48
+ });
49
+
50
+ return deserializeTransaction(result.transactions[0]) as any;
51
+ },
52
+
53
+ async signAndSendTransaction(transaction: any, options: any) {
54
+ const result = await requestHot("solana:signAndSendTransaction", {
55
+ transaction: transaction.serialize().toString("base64"),
56
+ options,
57
+ });
58
+
59
+ return { signature: result.signature };
60
+ },
61
+
62
+ async signIn(input: any) {
63
+ throw "Not supported";
64
+ return await requestHot("solana:signIn", input);
65
+ },
66
+
67
+ async signMessage(message: string) {
68
+ const result = await requestHot("solana:signMessage", { message: Buffer.from(message).toString("base64") });
69
+ return { signature: Buffer.from(result.signature, "base64") };
70
+ },
71
+
72
+ off() {
73
+ //HOT.unsubscribe(`solana:${event}`, listener);
74
+ },
75
+
76
+ on() {
77
+ // HOT.subscribe(`solana:${event}`, listener);
78
+ },
79
+ };
80
+
81
+ /*
82
+ HOT.subscribe("solana:accountChanged", (publicKey: string | null) => {
83
+ hotSolana.publicKey = publicKey ? new PublicKey(publicKey) : null;
84
+ });
85
+ */
86
+
87
+ if (isInjected()) {
88
+ registerWallet(new GhostWallet(hotSolana));
89
+
90
+ // New wallets no longer need to register wallet globals - and can
91
+ // ignore the code below. However if you have legacy apps relying on globals,
92
+ // this is the safest way to attach the reference to the window, guarding against errors.
93
+ try {
94
+ Object.defineProperty(window, "hotSolana", { value: hotSolana });
95
+ } catch (error) {
96
+ //
97
+ }
98
+ }
@@ -0,0 +1,48 @@
1
+ import type { Wallet, WalletEventsWindow, WindowRegisterWalletEvent, WindowRegisterWalletEventCallback } from "@wallet-standard/base";
2
+
3
+ export function registerWallet(wallet: Wallet): void {
4
+ const callback: WindowRegisterWalletEventCallback = ({ register }) => register(wallet);
5
+ try {
6
+ (window as WalletEventsWindow).dispatchEvent(new RegisterWalletEvent(callback));
7
+ } catch (error) {
8
+ console.error(error);
9
+ }
10
+
11
+ try {
12
+ (window as WalletEventsWindow).addEventListener("wallet-standard:app-ready", ({ detail: api }) => callback(api));
13
+ } catch (error) {
14
+ console.error(error);
15
+ }
16
+ }
17
+
18
+ class RegisterWalletEvent extends Event implements WindowRegisterWalletEvent {
19
+ readonly #detail: WindowRegisterWalletEventCallback;
20
+
21
+ get detail() {
22
+ return this.#detail;
23
+ }
24
+
25
+ get type() {
26
+ return "wallet-standard:register-wallet" as const;
27
+ }
28
+
29
+ constructor(callback: WindowRegisterWalletEventCallback) {
30
+ super("wallet-standard:register-wallet", { bubbles: false, cancelable: false, composed: false });
31
+ this.#detail = callback;
32
+ }
33
+
34
+ /** @deprecated */
35
+ preventDefault(): never {
36
+ throw new Error("preventDefault cannot be called");
37
+ }
38
+
39
+ /** @deprecated */
40
+ stopImmediatePropagation(): never {
41
+ throw new Error("stopImmediatePropagation cannot be called");
42
+ }
43
+
44
+ /** @deprecated */
45
+ stopPropagation(): never {
46
+ throw new Error("stopPropagation cannot be called");
47
+ }
48
+ }
@@ -0,0 +1,280 @@
1
+ import {
2
+ SolanaSignAndSendTransaction,
3
+ type SolanaSignAndSendTransactionFeature,
4
+ type SolanaSignAndSendTransactionMethod,
5
+ type SolanaSignAndSendTransactionOutput,
6
+ SolanaSignIn,
7
+ type SolanaSignInFeature,
8
+ type SolanaSignInMethod,
9
+ type SolanaSignInOutput,
10
+ SolanaSignMessage,
11
+ type SolanaSignMessageFeature,
12
+ type SolanaSignMessageMethod,
13
+ type SolanaSignMessageOutput,
14
+ SolanaSignTransaction,
15
+ type SolanaSignTransactionFeature,
16
+ type SolanaSignTransactionMethod,
17
+ type SolanaSignTransactionOutput,
18
+ } from "@solana/wallet-standard-features";
19
+ import { Transaction, VersionedTransaction } from "@solana/web3.js";
20
+ import type { Wallet } from "@wallet-standard/base";
21
+ import {
22
+ StandardConnect,
23
+ type StandardConnectFeature,
24
+ type StandardConnectMethod,
25
+ StandardDisconnect,
26
+ type StandardDisconnectFeature,
27
+ type StandardDisconnectMethod,
28
+ StandardEvents,
29
+ type StandardEventsFeature,
30
+ type StandardEventsListeners,
31
+ type StandardEventsNames,
32
+ type StandardEventsOnMethod,
33
+ } from "@wallet-standard/features";
34
+ import { base58 } from "@scure/base";
35
+
36
+ import { GhostWalletAccount } from "./account";
37
+ import { SOLANA_CHAINS, GhostFeature, GhostNamespace, isVersionedTransaction, SolanaChain, isSolanaChain, bytesEqual } from "./utils";
38
+
39
+ export class GhostWallet implements Wallet {
40
+ _account: GhostWalletAccount | null = null;
41
+ readonly _listeners: { [E in StandardEventsNames]?: StandardEventsListeners[E][] } = {};
42
+ readonly _version = "1.0.0" as const;
43
+ readonly _name = "HOT Wallet" as const;
44
+ readonly _icon = "https://storage.herewallet.app/logo.png";
45
+ readonly _ghost: any;
46
+
47
+ get version() {
48
+ return this._version;
49
+ }
50
+
51
+ get name() {
52
+ return this._name;
53
+ }
54
+
55
+ get icon() {
56
+ return this._icon as any;
57
+ }
58
+
59
+ get chains() {
60
+ return SOLANA_CHAINS.slice();
61
+ }
62
+
63
+ get features(): StandardConnectFeature & StandardDisconnectFeature & StandardEventsFeature & SolanaSignAndSendTransactionFeature & SolanaSignTransactionFeature & SolanaSignMessageFeature & SolanaSignInFeature & GhostFeature {
64
+ return {
65
+ [StandardConnect]: {
66
+ version: "1.0.0",
67
+ connect: this._connect,
68
+ },
69
+ [StandardDisconnect]: {
70
+ version: "1.0.0",
71
+ disconnect: this._disconnect,
72
+ },
73
+ [StandardEvents]: {
74
+ version: "1.0.0",
75
+ on: this._on,
76
+ },
77
+ [SolanaSignAndSendTransaction]: {
78
+ version: "1.0.0",
79
+ supportedTransactionVersions: ["legacy", 0],
80
+ signAndSendTransaction: this._signAndSendTransaction,
81
+ },
82
+ [SolanaSignTransaction]: {
83
+ version: "1.0.0",
84
+ supportedTransactionVersions: ["legacy", 0],
85
+ signTransaction: this._signTransaction,
86
+ },
87
+ [SolanaSignMessage]: {
88
+ version: "1.0.0",
89
+ signMessage: this._signMessage,
90
+ },
91
+ [SolanaSignIn]: {
92
+ version: "1.0.0",
93
+ signIn: this._signIn,
94
+ },
95
+ [GhostNamespace]: {
96
+ ghost: this._ghost,
97
+ },
98
+ };
99
+ }
100
+
101
+ get accounts() {
102
+ return this._account ? [this._account] : [];
103
+ }
104
+
105
+ constructor(ghost: any) {
106
+ this._ghost = ghost;
107
+ ghost.on("connect", this._connected, this);
108
+ ghost.on("disconnect", this._disconnected, this);
109
+ ghost.on("accountChanged", this._reconnected, this);
110
+ this._connected();
111
+ }
112
+
113
+ _on: StandardEventsOnMethod = (event, listener) => {
114
+ this._listeners[event]?.push(listener) || (this._listeners[event] = [listener]);
115
+ return (): void => this._off(event, listener);
116
+ };
117
+
118
+ _emit<E extends StandardEventsNames>(event: E, ...args: Parameters<StandardEventsListeners[E]>): void {
119
+ // eslint-disable-next-line prefer-spread
120
+ this._listeners[event]?.forEach((listener) => listener.apply(null, args));
121
+ }
122
+
123
+ _off<E extends StandardEventsNames>(event: E, listener: StandardEventsListeners[E]): void {
124
+ this._listeners[event] = this._listeners[event]?.filter((existingListener) => listener !== existingListener);
125
+ }
126
+
127
+ _connected = () => {
128
+ const address = this._ghost.publicKey?.toBase58();
129
+ if (address) {
130
+ const publicKey = this._ghost.publicKey!.toBytes();
131
+
132
+ const account = this._account;
133
+ if (!account || account.address !== address || !bytesEqual(account.publicKey, publicKey)) {
134
+ this._account = new GhostWalletAccount({ address, publicKey });
135
+ this._emit("change", { accounts: this.accounts });
136
+ }
137
+ }
138
+ };
139
+
140
+ _disconnected = () => {
141
+ if (this._account) {
142
+ this._account = null;
143
+ this._emit("change", { accounts: this.accounts });
144
+ }
145
+ };
146
+
147
+ _reconnected = () => {
148
+ if (this._ghost.publicKey) {
149
+ this._connected();
150
+ } else {
151
+ this._disconnected();
152
+ }
153
+ };
154
+
155
+ _connect: StandardConnectMethod = async ({ silent } = {}) => {
156
+ if (!this._account) await this._ghost.connect(silent ? { onlyIfTrusted: true } : undefined);
157
+ this._connected();
158
+ return { accounts: this.accounts };
159
+ };
160
+
161
+ _disconnect: StandardDisconnectMethod = async () => {
162
+ await this._ghost.disconnect();
163
+ };
164
+
165
+ _signAndSendTransaction: SolanaSignAndSendTransactionMethod = async (...inputs) => {
166
+ if (!this._account) throw new Error("not connected");
167
+
168
+ const outputs: SolanaSignAndSendTransactionOutput[] = [];
169
+
170
+ if (inputs.length === 1) {
171
+ const { transaction, account, options } = inputs[0]!;
172
+ const { minContextSlot, preflightCommitment, skipPreflight, maxRetries } = options || {};
173
+ if (account !== this._account) throw new Error("invalid account");
174
+
175
+ const { signature } = await this._ghost.signAndSendTransaction(VersionedTransaction.deserialize(transaction), {
176
+ preflightCommitment,
177
+ minContextSlot,
178
+ maxRetries,
179
+ skipPreflight,
180
+ });
181
+
182
+ outputs.push({ signature: base58.decode(signature) });
183
+ } else if (inputs.length > 1) {
184
+ for (const input of inputs) {
185
+ outputs.push(...(await this._signAndSendTransaction(input)));
186
+ }
187
+ }
188
+
189
+ return outputs;
190
+ };
191
+
192
+ _signTransaction: SolanaSignTransactionMethod = async (...inputs) => {
193
+ if (!this._account) throw new Error("not connected");
194
+
195
+ const outputs: SolanaSignTransactionOutput[] = [];
196
+
197
+ if (inputs.length === 1) {
198
+ const { transaction, account, chain } = inputs[0]!;
199
+ if (account !== this._account) throw new Error("invalid account");
200
+ if (chain && !isSolanaChain(chain)) throw new Error("invalid chain");
201
+
202
+ const signedTransaction = await this._ghost.signTransaction(VersionedTransaction.deserialize(transaction));
203
+
204
+ const serializedTransaction = isVersionedTransaction(signedTransaction)
205
+ ? signedTransaction.serialize()
206
+ : (signedTransaction as Transaction).serialize({
207
+ requireAllSignatures: false,
208
+ verifySignatures: false,
209
+ });
210
+
211
+ outputs.push({ signedTransaction: serializedTransaction });
212
+ } else if (inputs.length > 1) {
213
+ let chain: SolanaChain | undefined = undefined;
214
+ for (const input of inputs) {
215
+ if (input.account !== this._account) throw new Error("invalid account");
216
+ if (input.chain) {
217
+ if (!isSolanaChain(input.chain)) throw new Error("invalid chain");
218
+ if (chain) {
219
+ if (input.chain !== chain) throw new Error("conflicting chain");
220
+ } else {
221
+ chain = input.chain;
222
+ }
223
+ }
224
+ }
225
+
226
+ const transactions = inputs.map(({ transaction }) => VersionedTransaction.deserialize(transaction));
227
+ const signedTransactions = await this._ghost.signAllTransactions(transactions);
228
+
229
+ outputs.push(
230
+ ...signedTransactions.map((signedTransaction: any) => {
231
+ const serializedTransaction = isVersionedTransaction(signedTransaction)
232
+ ? signedTransaction.serialize()
233
+ : (signedTransaction as Transaction).serialize({
234
+ requireAllSignatures: false,
235
+ verifySignatures: false,
236
+ });
237
+
238
+ return { signedTransaction: serializedTransaction };
239
+ })
240
+ );
241
+ }
242
+
243
+ return outputs;
244
+ };
245
+
246
+ _signMessage: SolanaSignMessageMethod = async (...inputs) => {
247
+ if (!this._account) throw new Error("not connected");
248
+
249
+ const outputs: SolanaSignMessageOutput[] = [];
250
+
251
+ if (inputs.length === 1) {
252
+ const { message, account } = inputs[0]!;
253
+ if (account !== this._account) throw new Error("invalid account");
254
+
255
+ const { signature } = await this._ghost.signMessage(message);
256
+
257
+ outputs.push({ signedMessage: message, signature });
258
+ } else if (inputs.length > 1) {
259
+ for (const input of inputs) {
260
+ outputs.push(...(await this._signMessage(input)));
261
+ }
262
+ }
263
+
264
+ return outputs;
265
+ };
266
+
267
+ _signIn: SolanaSignInMethod = async (...inputs) => {
268
+ const outputs: SolanaSignInOutput[] = [];
269
+
270
+ if (inputs.length > 1) {
271
+ for (const input of inputs) {
272
+ outputs.push(await this._ghost.signIn(input));
273
+ }
274
+ } else {
275
+ return [await this._ghost.signIn(inputs[0])];
276
+ }
277
+
278
+ return outputs;
279
+ };
280
+ }
@@ -0,0 +1,56 @@
1
+ import { Transaction, VersionedTransaction } from "@solana/web3.js";
2
+ import type { IdentifierString } from "@wallet-standard/base";
3
+
4
+ interface Indexed<T> {
5
+ length: number;
6
+ [index: number]: T;
7
+ }
8
+
9
+ export function bytesEqual(a: Uint8Array, b: Uint8Array): boolean {
10
+ return arraysEqual(a, b);
11
+ }
12
+
13
+ export function arraysEqual<T>(a: Indexed<T>, b: Indexed<T>): boolean {
14
+ if (a === b) return true;
15
+
16
+ const length = a.length;
17
+ if (length !== b.length) return false;
18
+
19
+ for (let i = 0; i < length; i++) {
20
+ if (a[i] !== b[i]) return false;
21
+ }
22
+
23
+ return true;
24
+ }
25
+
26
+ export const GhostNamespace = "hot:";
27
+ export type GhostFeature = { [GhostNamespace]: { ghost: any } };
28
+
29
+ /** Solana Mainnet (beta) cluster, e.g. https://api.mainnet-beta.solana.com */
30
+ export const SOLANA_MAINNET_CHAIN = "solana:mainnet";
31
+
32
+ /** Solana Devnet cluster, e.g. https://api.devnet.solana.com */
33
+ export const SOLANA_DEVNET_CHAIN = "solana:devnet";
34
+
35
+ /** Solana Testnet cluster, e.g. https://api.testnet.solana.com */
36
+ export const SOLANA_TESTNET_CHAIN = "solana:testnet";
37
+
38
+ /** Solana Localnet cluster, e.g. http://localhost:8899 */
39
+ export const SOLANA_LOCALNET_CHAIN = "solana:localnet";
40
+
41
+ /** Array of all Solana clusters */
42
+ export const SOLANA_CHAINS = ["solana:mainnet", "solana:mainnet-beta"] as const;
43
+
44
+ /** Type of all Solana clusters */
45
+ export type SolanaChain = (typeof SOLANA_CHAINS)[number];
46
+
47
+ /**
48
+ * Check if a chain corresponds with one of the Solana clusters.
49
+ */
50
+ export function isSolanaChain(chain: IdentifierString): chain is SolanaChain {
51
+ return SOLANA_CHAINS.includes(chain as SolanaChain);
52
+ }
53
+
54
+ export function isVersionedTransaction(transaction: Transaction | VersionedTransaction): transaction is VersionedTransaction {
55
+ return "version" in transaction;
56
+ }
@@ -0,0 +1,39 @@
1
+ import { type ModuleInterface, ModuleType, WalletNetwork } from "@creit.tech/stellar-wallets-kit";
2
+ import { requestHot } from "./hot";
3
+
4
+ export const HOTWALLET_ID: string = "hot-wallet";
5
+
6
+ /**
7
+ * **IMPORTANT**: This module requires that you have a "global" and a "Buffer" polyfill in your app, if not provided then this module will break your app.
8
+ */
9
+ export class HotWalletModule implements ModuleInterface {
10
+ moduleType: ModuleType = ModuleType.HOT_WALLET;
11
+ productId: string = HOTWALLET_ID;
12
+ productName: string = "HOT Wallet";
13
+ productUrl: string = "https://hot-labs.org/wallet";
14
+ productIcon: string = "https://storage.herewallet.app/logo.png";
15
+
16
+ async isAvailable(): Promise<boolean> {
17
+ return true;
18
+ }
19
+
20
+ async getAddress(): Promise<{ address: string }> {
21
+ return await requestHot("stellar:getAddress", {});
22
+ }
23
+
24
+ async signTransaction(xdr: string, opts?: { address?: string }): Promise<{ signedTxXdr: string; signerAddress?: string }> {
25
+ return await requestHot("stellar:signTransaction", { xdr, accountToSign: opts?.address });
26
+ }
27
+
28
+ async signAuthEntry(authEntry: string, opts?: { address?: string }): Promise<{ signedAuthEntry: string; signerAddress?: string }> {
29
+ return await requestHot("stellar:signAuthEntry", { authEntry, accountToSign: opts?.address });
30
+ }
31
+
32
+ async signMessage(message: string, opts?: { address?: string }): Promise<{ signedMessage: string; signerAddress?: string }> {
33
+ return await requestHot("stellar:signMessage", { message, accountToSign: opts?.address });
34
+ }
35
+
36
+ async getNetwork(): Promise<{ network: string; networkPassphrase: string }> {
37
+ return { network: "mainnet", networkPassphrase: WalletNetwork.PUBLIC };
38
+ }
39
+ }
@@ -0,0 +1,56 @@
1
+ import { isInjected, requestHot } from "./hot";
2
+
3
+ if (isInjected()) {
4
+ // @ts-expect-error: hotWallet is not defined
5
+ window.hotWallet = {
6
+ tonconnect: {
7
+ deviceInfo: {
8
+ appName: "hot",
9
+ appVersion: "1",
10
+ maxProtocolVersion: 2,
11
+ platform: "ios",
12
+ features: [
13
+ "SendTransaction",
14
+ {
15
+ name: "SendTransaction",
16
+ maxMessages: 255,
17
+ extraCurrencySupported: false,
18
+ },
19
+ {
20
+ name: "SignData",
21
+ types: ["text", "binary", "cell"],
22
+ },
23
+ ],
24
+ },
25
+
26
+ walletInfo: {
27
+ name: "hotWallet",
28
+ image: "https://storage.herewallet.app/logo.png",
29
+ about_url: "https://hot-labs.org",
30
+ },
31
+
32
+ protocolVersion: 2,
33
+ isWalletBrowser: true,
34
+
35
+ connect: (_: number, request: any) => {
36
+ return requestHot("ton:connect", request);
37
+ },
38
+
39
+ restoreConnection: () => {
40
+ return requestHot("ton:restoreConnection", {});
41
+ },
42
+
43
+ disconnect: () => {
44
+ return requestHot("ton:disconnect", {});
45
+ },
46
+
47
+ send: async (request: any) => {
48
+ return requestHot("ton:send", request);
49
+ },
50
+
51
+ listen: () => {
52
+ return function () {};
53
+ },
54
+ },
55
+ };
56
+ }
@@ -0,0 +1,44 @@
1
+ import { GlobalSettings } from "../settings";
2
+ import { uuid4 } from "./hot";
3
+
4
+ export const requestWebWallet = (chain?: number, address?: string) => (method: string, request: any) => {
5
+ const width = 480;
6
+ const height = 640;
7
+ const wallet = GlobalSettings.webWallet;
8
+ const x = (window.screen.width - width) / 2;
9
+ const y = (window.screen.height - height) / 2;
10
+
11
+ const popup = window.open(`${wallet}`, "_blank", `popup=1,width=${width},height=${height},top=${y},left=${x}`);
12
+
13
+ return new Promise<any>(async (resolve, reject) => {
14
+ const interval = setInterval(() => {
15
+ if (!popup?.closed) return;
16
+ clearInterval(interval);
17
+ reject(new Error("User rejected"));
18
+ }, 100);
19
+
20
+ const id = uuid4();
21
+ const handler = (event: MessageEvent) => {
22
+ if (event.origin !== wallet) return;
23
+
24
+ if (event.data === "hot:ready") {
25
+ popup?.postMessage({ chain, address, method, request, id }, "*");
26
+ return;
27
+ }
28
+
29
+ if (event.data.id !== id) return;
30
+ if (event.data.success === false) {
31
+ clearInterval(interval);
32
+ reject(new Error(event.data.payload));
33
+ window.removeEventListener("message", handler);
34
+ }
35
+
36
+ window.removeEventListener("message", handler);
37
+ resolve(event.data.payload);
38
+ clearInterval(interval);
39
+ popup?.close();
40
+ };
41
+
42
+ window.addEventListener("message", handler);
43
+ });
44
+ };