@hot-labs/kit 1.4.26 → 1.5.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/build/HotConnector.js +0 -1
- package/build/HotConnector.js.map +1 -1
- package/build/activity.js +2 -0
- package/build/activity.js.map +1 -1
- package/build/core/Intents.d.ts +1 -1
- package/build/core/Intents.js +1 -1
- package/build/core/Intents.js.map +1 -1
- package/build/core/OmniConnector.d.ts +3 -2
- package/build/core/OmniConnector.js +13 -7
- package/build/core/OmniConnector.js.map +1 -1
- package/build/core/OmniWallet.d.ts +1 -1
- package/build/core/OmniWallet.js +8 -3
- package/build/core/OmniWallet.js.map +1 -1
- package/build/core/chains.d.ts +2 -0
- package/build/core/chains.js +13 -1
- package/build/core/chains.js.map +1 -1
- package/build/core/exchange.js +20 -31
- package/build/core/exchange.js.map +1 -1
- package/build/core/token.d.ts +4 -3
- package/build/core/token.js +8 -5
- package/build/core/token.js.map +1 -1
- package/build/core/tokens.js +9 -2
- package/build/core/tokens.js.map +1 -1
- package/build/core/utils.d.ts +11 -0
- package/build/core/utils.js +42 -0
- package/build/core/utils.js.map +1 -1
- package/build/evm/wallet.js +2 -0
- package/build/evm/wallet.js.map +1 -1
- package/build/hocraft/connector.d.ts +19 -0
- package/build/hocraft/connector.js +35 -0
- package/build/hocraft/connector.js.map +1 -0
- package/build/hocraft/index.d.ts +6 -0
- package/build/hocraft/index.js +5 -0
- package/build/hocraft/index.js.map +1 -0
- package/build/hocraft/wallet.d.ts +39 -0
- package/build/hocraft/wallet.js +157 -0
- package/build/hocraft/wallet.js.map +1 -0
- package/build/near/wallet.js +2 -0
- package/build/near/wallet.js.map +1 -1
- package/build/solana/wallet.js +2 -0
- package/build/solana/wallet.js.map +1 -1
- package/build/stellar/wallet.js +2 -0
- package/build/stellar/wallet.js.map +1 -1
- package/build/ton/wallet.js +2 -0
- package/build/ton/wallet.js.map +1 -1
- package/build/tron/wallet.js +2 -0
- package/build/tron/wallet.js.map +1 -1
- package/build/ui/bridge/Bridge.d.ts +0 -2
- package/build/ui/bridge/Bridge.js +22 -8
- package/build/ui/bridge/Bridge.js.map +1 -1
- package/build/ui/bridge/TokenCard.js +2 -2
- package/build/ui/bridge/TokenCard.js.map +1 -1
- package/build/ui/profile/Profile.js +9 -4
- package/build/ui/profile/Profile.js.map +1 -1
- package/package.json +2 -1
- package/src/HotConnector.ts +0 -1
- package/src/activity.ts +1 -0
- package/src/core/Intents.ts +1 -1
- package/src/core/OmniConnector.ts +13 -6
- package/src/core/OmniWallet.ts +8 -5
- package/src/core/chains.ts +13 -1
- package/src/core/exchange.ts +20 -30
- package/src/core/token.ts +9 -5
- package/src/core/tokens.ts +8 -2
- package/src/core/utils.ts +45 -0
- package/src/evm/wallet.ts +2 -0
- package/src/hocraft/connector.ts +35 -0
- package/src/hocraft/index.ts +7 -0
- package/src/hocraft/wallet.ts +166 -0
- package/src/near/wallet.ts +2 -0
- package/src/solana/wallet.ts +1 -0
- package/src/stellar/wallet.ts +1 -0
- package/src/ton/wallet.ts +1 -0
- package/src/tron/wallet.ts +1 -0
- package/src/ui/bridge/Bridge.tsx +30 -13
- package/src/ui/bridge/TokenCard.tsx +2 -2
- package/src/ui/profile/Profile.tsx +11 -10
package/src/evm/wallet.ts
CHANGED
|
@@ -111,6 +111,8 @@ class EvmWallet extends OmniWallet {
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
async transfer(args: { token: Token; receiver: string; amount: bigint; comment?: string; gasFee?: ReviewFee }): Promise<string> {
|
|
114
|
+
if (args.token.isOmni) return await super.transfer(args);
|
|
115
|
+
|
|
114
116
|
if (args.token.address === "native") {
|
|
115
117
|
return await this.sendTransaction({
|
|
116
118
|
...args.gasFee?.evmGas,
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ConnectorType, OmniConnector } from "../core/OmniConnector";
|
|
2
|
+
import { Network, WalletType } from "../core/chains";
|
|
3
|
+
import { OmniWallet } from "../core/OmniWallet";
|
|
4
|
+
import { HotConnector } from "../HotConnector";
|
|
5
|
+
import HotCraftWallet from "./wallet";
|
|
6
|
+
|
|
7
|
+
export default class HotCraftConnector extends OmniConnector<HotCraftWallet> {
|
|
8
|
+
walletTypes = [WalletType.HotCraft];
|
|
9
|
+
type = ConnectorType.HOTCRAFT;
|
|
10
|
+
icon = "https://hotcraft.art/favicon-beige.ico";
|
|
11
|
+
name = "HotCraft";
|
|
12
|
+
id = "hotcraft";
|
|
13
|
+
|
|
14
|
+
constructor(readonly wibe3: HotConnector) {
|
|
15
|
+
super(wibe3);
|
|
16
|
+
|
|
17
|
+
wibe3.onConnect(async ({ wallet }) => {
|
|
18
|
+
if (wallet.type === WalletType.HotCraft) return;
|
|
19
|
+
const craftWallet = new HotCraftWallet(wallet, wibe3.storage);
|
|
20
|
+
const balances = await craftWallet.fetchBalances(Network.HotCraft);
|
|
21
|
+
if (Object.values(balances).some((balance) => balance === 0n)) return;
|
|
22
|
+
this.setWallet({ wallet: craftWallet, isNew: false });
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
wibe3.onDisconnect(async ({ wallet }) => {
|
|
26
|
+
if (wallet.type === WalletType.HotCraft) return;
|
|
27
|
+
const craftWallet = this.wallets.find((t) => t.wallet === wallet);
|
|
28
|
+
if (craftWallet) this.removeWallet(craftWallet);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async connect(id?: string): Promise<OmniWallet | { qrcode: string; deeplink?: string; task: Promise<OmniWallet> }> {
|
|
33
|
+
throw "Not supported";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { HotConnector } from "../HotConnector";
|
|
2
|
+
import HotCraftConnector from "./connector";
|
|
3
|
+
import HotCraftWallet from "./wallet";
|
|
4
|
+
|
|
5
|
+
export { HotCraftConnector, HotCraftWallet };
|
|
6
|
+
|
|
7
|
+
export default () => async (wibe3: HotConnector) => new HotCraftConnector(wibe3);
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import { base32crockford, base58, base64 } from "@scure/base";
|
|
3
|
+
import { KeyPair, KeyPairString } from "@near-js/crypto";
|
|
4
|
+
|
|
5
|
+
import { Commitment, Intents, Network, OmniToken, OmniWallet, ReviewFee, Token, WalletType } from "../core";
|
|
6
|
+
import { AutoQueue } from "../core/utils";
|
|
7
|
+
import { DataStorage } from "../storage";
|
|
8
|
+
import { rpc } from "../near/rpc";
|
|
9
|
+
|
|
10
|
+
export const TGAS = 1_000_000_000_000n;
|
|
11
|
+
|
|
12
|
+
class HotCraftAccount extends OmniWallet {
|
|
13
|
+
publicKey?: string | undefined;
|
|
14
|
+
type = WalletType.HotCraft;
|
|
15
|
+
omniAddress: string;
|
|
16
|
+
address: string;
|
|
17
|
+
|
|
18
|
+
constructor(readonly wallet: OmniWallet, readonly storage: DataStorage) {
|
|
19
|
+
super();
|
|
20
|
+
this.omniAddress = HotCraftAccount.getTradingAddress(wallet.omniAddress);
|
|
21
|
+
this.address = this.omniAddress;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
get icon() {
|
|
25
|
+
return this.wallet.icon;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async getTradingKey() {
|
|
29
|
+
const tradingKey = await this.storage.get(`hotcraft:${this.omniAddress}:key`);
|
|
30
|
+
if (tradingKey) return KeyPair.fromString(tradingKey as KeyPairString);
|
|
31
|
+
|
|
32
|
+
const newTradingKey = KeyPair.fromRandom("ed25519");
|
|
33
|
+
await this.storage.set(`hotcraft:${this.omniAddress}:key`, newTradingKey.toString());
|
|
34
|
+
return newTradingKey;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static getTradingAddress(signerId: string) {
|
|
38
|
+
const buffer = crypto.createHash("sha256").update(Buffer.from(signerId, "utf8")).digest();
|
|
39
|
+
const hash = base32crockford.encode(buffer.slice(0, 20)).toLowerCase();
|
|
40
|
+
return `${hash}.craft.tg`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async getAuthCommitment({ forceRegister = false }: { forceRegister?: boolean } = {}) {
|
|
44
|
+
const tradingKey = await this.getTradingKey();
|
|
45
|
+
const commitment = await this.storage.get(`hotcraft:${this.omniAddress}:auth`);
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
if (!commitment || forceRegister) throw new Error("No credentials found");
|
|
49
|
+
if (!commitment.includes(tradingKey.getPublicKey().toString())) throw "Invalid commitment";
|
|
50
|
+
return JSON.parse(commitment) as Commitment;
|
|
51
|
+
} catch (error) {
|
|
52
|
+
const commitment = await this.wallet
|
|
53
|
+
.intents()
|
|
54
|
+
.authCall({
|
|
55
|
+
contractId: "craft.tg",
|
|
56
|
+
attachNear: 0n,
|
|
57
|
+
tgas: 250,
|
|
58
|
+
msg: JSON.stringify({
|
|
59
|
+
public_key: tradingKey.getPublicKey().toString(),
|
|
60
|
+
force_register: forceRegister,
|
|
61
|
+
referral: "hotcraft.art",
|
|
62
|
+
}),
|
|
63
|
+
})
|
|
64
|
+
.sign();
|
|
65
|
+
|
|
66
|
+
await this.storage.set(`hotcraft:${this.omniAddress}:auth`, JSON.stringify(commitment));
|
|
67
|
+
return commitment;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async transfer(args: { token: Token; receiver: string; amount: bigint; comment?: string; gasFee?: ReviewFee }): Promise<string> {
|
|
72
|
+
if (args.token.chain !== Network.HotCraft) throw new Error("Invalid token chain");
|
|
73
|
+
return await this.intents()
|
|
74
|
+
.transfer({ amount: args.amount, recipient: args.receiver, token: args.token.omniAddress as OmniToken })
|
|
75
|
+
.execute();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
_isRegistered = false;
|
|
79
|
+
async isRegistered() {
|
|
80
|
+
if (this._isRegistered) return true;
|
|
81
|
+
const tradingKey = await this.getTradingKey();
|
|
82
|
+
const result = await rpc.viewMethod({
|
|
83
|
+
args: { account_id: this.omniAddress, public_key: tradingKey.getPublicKey().toString() },
|
|
84
|
+
methodName: "has_public_key",
|
|
85
|
+
contractId: "intents.near",
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
this._isRegistered = result;
|
|
89
|
+
return this._isRegistered;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async doubleCheckRegister() {
|
|
93
|
+
if (await this.isRegistered()) return true;
|
|
94
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
95
|
+
return await this.isRegistered();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async fetchBalance(chain: number, address: string): Promise<bigint> {
|
|
99
|
+
if (chain !== Network.HotCraft) return 0n;
|
|
100
|
+
if (!this.omniAddress) return 0n;
|
|
101
|
+
const balances = await Intents.getIntentsBalances([address], this.omniAddress);
|
|
102
|
+
return this.setBalance(`${Network.HotCraft}:${address}`, balances[address] || 0n);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async fetchBalances(chain: number, whitelist: string[] = []): Promise<Record<string, bigint>> {
|
|
106
|
+
if (chain !== Network.HotCraft) return {};
|
|
107
|
+
if (!this.omniAddress) return {};
|
|
108
|
+
|
|
109
|
+
const list = whitelist.length > 0 ? whitelist : await Intents.getIntentsAssets(this.omniAddress);
|
|
110
|
+
const balances = await Intents.getIntentsBalances(list, this.omniAddress);
|
|
111
|
+
Object.entries(balances).forEach(([address, balance]) => this.setBalance(`${Network.HotCraft}:${address}`, BigInt(balance as unknown as string)));
|
|
112
|
+
return balances;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private queue = new AutoQueue();
|
|
116
|
+
async registerAccount(): Promise<KeyPair> {
|
|
117
|
+
return await this.queue.enqueue<KeyPair>(async () => {
|
|
118
|
+
const tradingKey = await this.getTradingKey();
|
|
119
|
+
try {
|
|
120
|
+
if (await this.isRegistered()) return tradingKey;
|
|
121
|
+
const commitment = await this.getAuthCommitment();
|
|
122
|
+
console.log("commitment", commitment);
|
|
123
|
+
|
|
124
|
+
await Intents.publish([commitment]);
|
|
125
|
+
|
|
126
|
+
if (await this.doubleCheckRegister()) return tradingKey;
|
|
127
|
+
throw "We can't register your account, please try reconnect wallet";
|
|
128
|
+
} catch (error) {
|
|
129
|
+
if (await this.doubleCheckRegister()) return tradingKey;
|
|
130
|
+
if (!error?.toString()?.includes?.("AccountDoesNotExist")) {
|
|
131
|
+
throw "We can't register your account, please try reconnect wallet";
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const commitment = await this.getAuthCommitment({ forceRegister: true });
|
|
135
|
+
console.log("commitment", commitment);
|
|
136
|
+
|
|
137
|
+
await Intents.publish([commitment]);
|
|
138
|
+
return await this.registerAccount();
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async signIntents(intents: Record<string, any>[], options?: { nonce?: Uint8Array; deadline?: number; signerId?: string }): Promise<Commitment> {
|
|
144
|
+
const tradingKey = await this.registerAccount();
|
|
145
|
+
const nonce = new Uint8Array(options?.nonce || window.crypto.getRandomValues(new Uint8Array(32)));
|
|
146
|
+
|
|
147
|
+
const message = JSON.stringify({
|
|
148
|
+
deadline: options?.deadline ? new Date(options.deadline).toISOString() : "2100-01-01T00:00:00.000Z",
|
|
149
|
+
signer_id: options?.signerId || this.omniAddress,
|
|
150
|
+
verifying_contract: "intents.near",
|
|
151
|
+
nonce: base64.encode(nonce),
|
|
152
|
+
intents: intents,
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
const signature = tradingKey.sign(Buffer.from(message, "utf8"));
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
standard: "raw_ed25519",
|
|
159
|
+
payload: message,
|
|
160
|
+
signature: "ed25519:" + base58.encode(signature.signature),
|
|
161
|
+
public_key: tradingKey.getPublicKey().toString(),
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export default HotCraftAccount;
|
package/src/near/wallet.ts
CHANGED
|
@@ -140,6 +140,8 @@ export default class NearWallet extends OmniWallet {
|
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
async transfer(args: { token: Token; receiver: string; amount: bigint; comment?: string; gasFee?: ReviewFee }) {
|
|
143
|
+
if (args.token.isOmni) return await super.transfer(args);
|
|
144
|
+
|
|
143
145
|
if (args.token.address === "native") {
|
|
144
146
|
return await this.sendTransaction({
|
|
145
147
|
actions: [{ type: "Transfer", params: { deposit: String(args.amount) } }],
|
package/src/solana/wallet.ts
CHANGED
|
@@ -162,6 +162,7 @@ class SolanaWallet extends OmniWallet {
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
async transfer(args: { token: Token; receiver: string; amount: bigint; comment?: string; gasFee: ReviewFee }): Promise<string> {
|
|
165
|
+
if (args.token.isOmni) return await super.transfer(args);
|
|
165
166
|
const { instructions } = await this.buildTranferInstructions(args.token, args.amount, args.receiver, args.gasFee);
|
|
166
167
|
return await this.sendTransaction(instructions);
|
|
167
168
|
}
|
package/src/stellar/wallet.ts
CHANGED
|
@@ -157,6 +157,7 @@ class StellarWallet extends OmniWallet {
|
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
async transfer(args: { token: Token; receiver: string; amount: bigint; comment?: string; gasFee?: ReviewFee }) {
|
|
160
|
+
if (args.token.isOmni) return await super.transfer(args);
|
|
160
161
|
const { tx } = await this.emulateTransfer(args.token.address, args.receiver, args.amount, args.comment);
|
|
161
162
|
return this.sendTransaction(tx);
|
|
162
163
|
}
|
package/src/ton/wallet.ts
CHANGED
|
@@ -122,6 +122,7 @@ class TonWallet extends OmniWallet {
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
async transfer(args: { token: Token; receiver: string; amount: bigint; comment?: string; gasFee?: ReviewFee }) {
|
|
125
|
+
if (args.token.isOmni) return await super.transfer(args);
|
|
125
126
|
const memo = args.comment ? comment(args.comment) : null;
|
|
126
127
|
|
|
127
128
|
if (args.token.address === "native") {
|
package/src/tron/wallet.ts
CHANGED
|
@@ -84,6 +84,7 @@ class TronWallet extends OmniWallet {
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
async transfer(args: { token: Token; receiver: string; amount: bigint; comment?: string; gasFee?: ReviewFee }): Promise<string> {
|
|
87
|
+
if (args.token.isOmni) return await super.transfer(args);
|
|
87
88
|
if (!this.tronWeb.trx) throw new Error("TronLink not available");
|
|
88
89
|
|
|
89
90
|
if (args.token.address === "native") {
|
package/src/ui/bridge/Bridge.tsx
CHANGED
|
@@ -8,7 +8,7 @@ import ExchangeIcon from "../icons/exchange";
|
|
|
8
8
|
import RefreshIcon from "../icons/refresh";
|
|
9
9
|
|
|
10
10
|
import { HotConnector } from "../../HotConnector";
|
|
11
|
-
import { chains, WalletType } from "../../core/chains";
|
|
11
|
+
import { chains, Network, WalletType } from "../../core/chains";
|
|
12
12
|
import { BridgeReview } from "../../core/exchange";
|
|
13
13
|
import { OmniWallet } from "../../core/OmniWallet";
|
|
14
14
|
import { Recipient } from "../../core/recipient";
|
|
@@ -17,7 +17,7 @@ import { tokens } from "../../core/tokens";
|
|
|
17
17
|
import { Token } from "../../core/token";
|
|
18
18
|
|
|
19
19
|
import { ActionButton, Button } from "../uikit/button";
|
|
20
|
-
import { PLarge, PSmall, PTiny } from "../uikit/text";
|
|
20
|
+
import { PLarge, PMedium, PSmall, PTiny } from "../uikit/text";
|
|
21
21
|
import { Skeleton } from "../uikit/loader";
|
|
22
22
|
import { ImageView } from "../uikit/image";
|
|
23
23
|
|
|
@@ -43,8 +43,6 @@ export interface BridgeProps {
|
|
|
43
43
|
autoClose?: boolean; // if true, the popup will close automatically when the transaction is successful
|
|
44
44
|
title?: string;
|
|
45
45
|
readonlyAmount?: boolean;
|
|
46
|
-
readonlyTo?: boolean;
|
|
47
|
-
readonlyFrom?: boolean;
|
|
48
46
|
type?: "exactIn" | "exactOut";
|
|
49
47
|
sender?: OmniWallet;
|
|
50
48
|
recipient?: Recipient;
|
|
@@ -115,8 +113,8 @@ export const Bridge = observer(({ hot, widget, setup, onClose, onProcess, onSele
|
|
|
115
113
|
const availableBalance = sender !== "qr" ? +Math.max(0, from.float(hot.balance(sender, from)) - from.reserve).toFixed(FIXED) : 0;
|
|
116
114
|
|
|
117
115
|
let title = "Exchange";
|
|
118
|
-
if (from.chain ===
|
|
119
|
-
if (to.chain ===
|
|
116
|
+
if (from.chain === Network.HotCraft || from.chain === Network.Omni) title = `Withdraw ${from.symbol}`;
|
|
117
|
+
if (to.chain === Network.HotCraft || to.chain === Network.Omni) title = `Deposit ${to.symbol}`;
|
|
120
118
|
if (to.chain === from.chain) title = "Exchange";
|
|
121
119
|
|
|
122
120
|
useEffect(() => {
|
|
@@ -285,12 +283,13 @@ export const Bridge = observer(({ hot, widget, setup, onClose, onProcess, onSele
|
|
|
285
283
|
if (processing?.status === "error") {
|
|
286
284
|
return (
|
|
287
285
|
<Popup widget={widget} onClose={onClose} header={<p>{title}</p>} mobileFullscreen={setup?.mobileFullscreen}>
|
|
288
|
-
<div style={{ width: "100%", height: 400, gap: 8, display: "flex", justifyContent: "center", alignItems: "center", flexDirection: "column" }}>
|
|
286
|
+
<div style={{ width: "100%", height: 400, marginBottom: 8, gap: 8, display: "flex", justifyContent: "center", alignItems: "center", flexDirection: "column" }}>
|
|
289
287
|
{/* @ts-expect-error: dotlottie-wc is not typed */}
|
|
290
288
|
<dotlottie-wc key="error" src={animations.failed} speed="1" style={{ width: 300, height: 300 }} mode="forward" loop autoplay></dotlottie-wc>
|
|
291
289
|
<p style={{ fontSize: 24, marginTop: -32, fontWeight: "bold" }}>{title} failed</p>
|
|
292
|
-
<
|
|
290
|
+
<TextField>{processing.message}</TextField>
|
|
293
291
|
</div>
|
|
292
|
+
|
|
294
293
|
<ActionButton onClick={() => (cancelReview(), onClose())}>Continue</ActionButton>
|
|
295
294
|
</Popup>
|
|
296
295
|
);
|
|
@@ -338,10 +337,15 @@ export const Bridge = observer(({ hot, widget, setup, onClose, onProcess, onSele
|
|
|
338
337
|
|
|
339
338
|
<CardBody>
|
|
340
339
|
<div style={{ width: "100%", display: "flex", alignItems: "center", gap: 8, justifyContent: "space-between" }}>
|
|
341
|
-
<TokenPreview
|
|
342
|
-
onSelect={() => openSelectTokenPopup({ onSelect: (token, wallet) => (setFrom(token), setSender(wallet)), initialChain: from.chain, hot })}
|
|
343
|
-
style={{ pointerEvents: setup?.readonlyFrom ? "none" : "all" }}
|
|
340
|
+
<TokenPreview
|
|
344
341
|
token={from}
|
|
342
|
+
onSelect={() =>
|
|
343
|
+
openSelectTokenPopup({
|
|
344
|
+
onSelect: (token, wallet) => (setFrom(token), setSender(wallet)),
|
|
345
|
+
initialChain: from.chain,
|
|
346
|
+
hot,
|
|
347
|
+
})
|
|
348
|
+
}
|
|
345
349
|
/>
|
|
346
350
|
|
|
347
351
|
{isReviewing && type === "exactOut" ? (
|
|
@@ -404,6 +408,7 @@ export const Bridge = observer(({ hot, widget, setup, onClose, onProcess, onSele
|
|
|
404
408
|
</Button>
|
|
405
409
|
</AvailableBalance>
|
|
406
410
|
)}
|
|
411
|
+
|
|
407
412
|
{sender === "qr" && <div />}
|
|
408
413
|
<div style={{ display: "flex", alignItems: "center", gap: 4 }}>
|
|
409
414
|
{from.usd !== 0 && <PSmall style={{ marginRight: 8 }}>${from.readable(amountFrom, from.usd)}</PSmall>}
|
|
@@ -460,9 +465,8 @@ export const Bridge = observer(({ hot, widget, setup, onClose, onProcess, onSele
|
|
|
460
465
|
|
|
461
466
|
<CardBody style={{ borderRadius: "0 0 20px 20px" }}>
|
|
462
467
|
<div style={{ width: "100%", display: "flex", alignItems: "center", gap: 8, justifyContent: "space-between" }}>
|
|
463
|
-
<TokenPreview
|
|
468
|
+
<TokenPreview
|
|
464
469
|
token={to}
|
|
465
|
-
style={{ pointerEvents: setup?.readonlyTo ? "none" : "all" }}
|
|
466
470
|
onSelect={() =>
|
|
467
471
|
openSelectTokenPopup({
|
|
468
472
|
hot,
|
|
@@ -516,6 +520,19 @@ const TokenPreview = ({ style, token, onSelect }: { style?: React.CSSProperties;
|
|
|
516
520
|
);
|
|
517
521
|
};
|
|
518
522
|
|
|
523
|
+
const TextField = styled(PTiny)`
|
|
524
|
+
width: 100%;
|
|
525
|
+
overflow: auto;
|
|
526
|
+
max-height: 200px;
|
|
527
|
+
background: #2c2c2c;
|
|
528
|
+
border-radius: 12px;
|
|
529
|
+
font-size: 12px;
|
|
530
|
+
padding: 8px;
|
|
531
|
+
margin-bottom: 12px;
|
|
532
|
+
white-space: pre-wrap;
|
|
533
|
+
line-break: anywhere;
|
|
534
|
+
`;
|
|
535
|
+
|
|
519
536
|
const Tooltip = styled.div`
|
|
520
537
|
transition: 0.2s transform, 0.2s opacity;
|
|
521
538
|
transform: translateY(8px);
|
|
@@ -14,7 +14,7 @@ export const TokenIcon = observer(({ token, wallet, withoutChain, size = 40 }: {
|
|
|
14
14
|
<div style={{ position: "relative", width: size, height: size, flexShrink: 0 }}>
|
|
15
15
|
<ImageView src={token.icon} alt={token.symbol} size={size} />
|
|
16
16
|
{!withoutChain && <ImageView src={token.chainIcon} alt={token.symbol} size={size / 2 - 6} style={{ position: "absolute", bottom: 0, right: 0 }} />}
|
|
17
|
-
{token.
|
|
17
|
+
{token.isOmni && wallet?.type && <ImageView src={wallet.icon} alt={chains.getByType(wallet.type)?.[0]?.name || ""} size={size / 2 - 6} style={{ position: "absolute", bottom: 0, left: 0 }} />}
|
|
18
18
|
</div>
|
|
19
19
|
);
|
|
20
20
|
});
|
|
@@ -22,7 +22,7 @@ export const TokenIcon = observer(({ token, wallet, withoutChain, size = 40 }: {
|
|
|
22
22
|
export const TokenCard = observer(
|
|
23
23
|
({ token, onSelect, amount, hot, wallet, rightControl }: { rightControl?: React.ReactNode; token: Token; onSelect?: (token: Token, wallet?: OmniWallet) => void; amount?: bigint; hot: HotConnector; wallet?: OmniWallet }) => {
|
|
24
24
|
const balance = amount || hot.balance(wallet, token);
|
|
25
|
-
const symbol = token.
|
|
25
|
+
const symbol = token.isOmni && !token.isMainOmni ? `${token.symbol} (${token.originalChainSymbol})` : token.symbol;
|
|
26
26
|
|
|
27
27
|
return (
|
|
28
28
|
<Card key={token.id} onClick={() => onSelect?.(token, wallet)}>
|
|
@@ -11,7 +11,7 @@ import { Loader } from "../uikit/loader";
|
|
|
11
11
|
import { OmniWallet } from "../../core/OmniWallet";
|
|
12
12
|
import { ConnectorType } from "../../core/OmniConnector";
|
|
13
13
|
import { formatter } from "../../core/utils";
|
|
14
|
-
import { OmniToken } from "../../core/chains";
|
|
14
|
+
import { Network, OmniToken } from "../../core/chains";
|
|
15
15
|
import { tokens } from "../../core/tokens";
|
|
16
16
|
|
|
17
17
|
import { HotConnector } from "../../HotConnector";
|
|
@@ -32,7 +32,7 @@ export const Profile = observer(({ hot, onClose }: { hot: HotConnector; onClose:
|
|
|
32
32
|
component: (
|
|
33
33
|
<TokenCard //
|
|
34
34
|
onSelect={() => {
|
|
35
|
-
if (token.chain ===
|
|
35
|
+
if (token.chain === Network.Omni || token.chain === Network.HotCraft) hot.withdraw(token.address as OmniToken, +token.float(balance).toFixed(6), { sender: wallet });
|
|
36
36
|
else openBridge(hot, { title: "Exchange", sender: wallet, from: token });
|
|
37
37
|
}}
|
|
38
38
|
key={`${wallet.type}:${wallet.address}:${token.id}`}
|
|
@@ -45,8 +45,8 @@ export const Profile = observer(({ hot, onClose }: { hot: HotConnector; onClose:
|
|
|
45
45
|
})
|
|
46
46
|
.filter((t) => t != null);
|
|
47
47
|
|
|
48
|
-
const omniTokens = tokensList.filter((t) => t.chain ===
|
|
49
|
-
const nonOmniTokens = tokensList.filter((t) => t.chain !==
|
|
48
|
+
const omniTokens = tokensList.filter((t) => t.chain === Network.Omni || t.chain === Network.HotCraft);
|
|
49
|
+
const nonOmniTokens = tokensList.filter((t) => t.chain !== Network.Omni && t.chain !== Network.HotCraft);
|
|
50
50
|
const socialConnector = hot.connectors.find((connector) => connector.type === ConnectorType.SOCIAL && connector.wallets.length > 0);
|
|
51
51
|
|
|
52
52
|
useEffect(() => {
|
|
@@ -57,16 +57,17 @@ export const Profile = observer(({ hot, onClose }: { hot: HotConnector; onClose:
|
|
|
57
57
|
return (
|
|
58
58
|
<Popup onClose={onClose} style={{ gap: 16 }}>
|
|
59
59
|
<div style={{ display: "flex", flexWrap: "wrap", width: "100%", gap: 8 }}>
|
|
60
|
-
{hot.connectors.map((connector) =>
|
|
61
|
-
connector.
|
|
60
|
+
{hot.connectors.map((connector) => {
|
|
61
|
+
if (connector.type === ConnectorType.HOTCRAFT) return null;
|
|
62
|
+
return connector.wallets.map((wallet) => (
|
|
62
63
|
<WalletCard onClick={() => connector.disconnect()}>
|
|
63
|
-
<ImageView src={
|
|
64
|
-
{connector.
|
|
64
|
+
<ImageView src={connector.icon} alt={connector.name} size={20} />
|
|
65
|
+
{connector.icon !== wallet.icon && <ImageView style={{ position: "absolute", bottom: 4, left: 20 }} src={wallet.icon} alt={connector.name} size={12} />}
|
|
65
66
|
<div>{formatter.truncateAddress(wallet.address, 8)}</div>
|
|
66
67
|
<LogoutIcon />
|
|
67
68
|
</WalletCard>
|
|
68
|
-
))
|
|
69
|
-
)}
|
|
69
|
+
));
|
|
70
|
+
})}
|
|
70
71
|
|
|
71
72
|
{hot.wallets.length < hot.connectors.length && (
|
|
72
73
|
<WalletCard
|