@hot-labs/kit 1.2.0-alpha.2 → 1.2.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.
Files changed (280) hide show
  1. package/README.md +2 -9
  2. package/build/HotConnector.d.ts +8 -7
  3. package/build/HotConnector.js +21 -24
  4. package/build/HotConnector.js.map +1 -1
  5. package/build/OmniConnector.d.ts +5 -0
  6. package/build/OmniConnector.js +5 -5
  7. package/build/OmniConnector.js.map +1 -1
  8. package/build/OmniWallet.d.ts +10 -17
  9. package/build/OmniWallet.js +14 -19
  10. package/build/OmniWallet.js.map +1 -1
  11. package/build/core/Intents.d.ts +53 -43
  12. package/build/core/Intents.js +207 -133
  13. package/build/core/Intents.js.map +1 -1
  14. package/build/core/api.d.ts +30 -2
  15. package/build/core/api.js +43 -10
  16. package/build/core/api.js.map +1 -1
  17. package/build/core/bridge.js +1 -1
  18. package/build/core/bridge.js.map +1 -1
  19. package/build/core/index.d.ts +1 -1
  20. package/build/core/index.js +1 -1
  21. package/build/core/index.js.map +1 -1
  22. package/build/core/telemetry.d.ts +13 -0
  23. package/build/core/telemetry.js +27 -0
  24. package/build/core/telemetry.js.map +1 -0
  25. package/build/core/token.d.ts +1 -0
  26. package/build/core/token.js +3 -0
  27. package/build/core/token.js.map +1 -1
  28. package/build/core/tokens.js +0 -8
  29. package/build/core/tokens.js.map +1 -1
  30. package/build/core/types.d.ts +17 -0
  31. package/build/core/utils.d.ts +1 -0
  32. package/build/core/utils.js +21 -1
  33. package/build/core/utils.js.map +1 -1
  34. package/build/cosmos/connector.d.ts +2 -2
  35. package/build/cosmos/connector.js +17 -21
  36. package/build/cosmos/connector.js.map +1 -1
  37. package/build/cosmos/wallet.d.ts +2 -4
  38. package/build/cosmos/wallet.js +3 -8
  39. package/build/cosmos/wallet.js.map +1 -1
  40. package/build/evm/connector.d.ts +1 -0
  41. package/build/evm/connector.js +4 -0
  42. package/build/evm/connector.js.map +1 -1
  43. package/build/evm/wallet.d.ts +2 -1
  44. package/build/evm/wallet.js +7 -5
  45. package/build/evm/wallet.js.map +1 -1
  46. package/build/exchange.d.ts +4 -1
  47. package/build/exchange.js +24 -30
  48. package/build/exchange.js.map +1 -1
  49. package/build/hot-wallet/google.js +10 -5
  50. package/build/hot-wallet/google.js.map +1 -1
  51. package/build/hot-wallet/proxy.js +2 -2
  52. package/build/hot-wallet/proxy.js.map +1 -1
  53. package/build/index.d.ts +2 -1
  54. package/build/index.js +2 -1
  55. package/build/index.js.map +1 -1
  56. package/build/near/connector.js +2 -2
  57. package/build/near/connector.js.map +1 -1
  58. package/build/{core/nearRpc.d.ts → near/rpc.d.ts} +0 -1
  59. package/build/{core/nearRpc.js → near/rpc.js} +8 -22
  60. package/build/near/rpc.js.map +1 -0
  61. package/build/near/wallet.d.ts +4 -4
  62. package/build/near/wallet.js +36 -30
  63. package/build/near/wallet.js.map +1 -1
  64. package/build/solana/{protocol.d.ts → WalletStandard.d.ts} +1 -1
  65. package/build/solana/{protocol.js → WalletStandard.js} +1 -1
  66. package/build/solana/WalletStandard.js.map +1 -0
  67. package/build/solana/connector.d.ts +1 -1
  68. package/build/solana/connector.js +9 -8
  69. package/build/solana/connector.js.map +1 -1
  70. package/build/solana/injected/solana-wallet.js.map +1 -1
  71. package/build/solana/wallet.d.ts +5 -7
  72. package/build/solana/wallet.js +8 -17
  73. package/build/solana/wallet.js.map +1 -1
  74. package/build/solana/{wallets.js → walletStandartList.js} +1 -1
  75. package/build/solana/walletStandartList.js.map +1 -0
  76. package/build/stellar/connector.d.ts +0 -2
  77. package/build/stellar/connector.js +1 -4
  78. package/build/stellar/connector.js.map +1 -1
  79. package/build/stellar/wallet.d.ts +10 -8
  80. package/build/stellar/wallet.js +12 -16
  81. package/build/stellar/wallet.js.map +1 -1
  82. package/build/ton/connector.d.ts +0 -1
  83. package/build/ton/connector.js +1 -4
  84. package/build/ton/connector.js.map +1 -1
  85. package/build/ton/wallet.d.ts +2 -3
  86. package/build/ton/wallet.js +3 -4
  87. package/build/ton/wallet.js.map +1 -1
  88. package/build/tron/connector.d.ts +51 -0
  89. package/build/tron/connector.js +65 -0
  90. package/build/tron/connector.js.map +1 -0
  91. package/build/tron/index.d.ts +6 -0
  92. package/build/tron/index.js +5 -0
  93. package/build/tron/index.js.map +1 -0
  94. package/build/tron/wallet.d.ts +52 -0
  95. package/build/tron/wallet.js +122 -0
  96. package/build/tron/wallet.js.map +1 -0
  97. package/build/ui/Popup.d.ts +2 -2
  98. package/build/ui/Popup.js +5 -1
  99. package/build/ui/Popup.js.map +1 -1
  100. package/build/ui/bridge/Bridge.js +389 -0
  101. package/build/ui/bridge/Bridge.js.map +1 -0
  102. package/build/ui/{payment → bridge}/SelectRecipient.js +3 -3
  103. package/build/ui/bridge/SelectRecipient.js.map +1 -0
  104. package/build/ui/{payment → bridge}/SelectSender.js +2 -2
  105. package/build/ui/bridge/SelectSender.js.map +1 -0
  106. package/build/ui/{payment → bridge}/SelectToken.js +4 -3
  107. package/build/ui/bridge/SelectToken.js.map +1 -0
  108. package/build/ui/{payment → bridge}/TokenCard.d.ts +7 -9
  109. package/build/ui/bridge/TokenCard.js +65 -0
  110. package/build/ui/bridge/TokenCard.js.map +1 -0
  111. package/build/ui/connect/AuthPopup.js +1 -1
  112. package/build/ui/connect/AuthPopup.js.map +1 -1
  113. package/build/ui/connect/ConnectWallet.d.ts +7 -2
  114. package/build/ui/connect/ConnectWallet.js +7 -7
  115. package/build/ui/connect/ConnectWallet.js.map +1 -1
  116. package/build/ui/connect/PrimaryWallet.d.ts +6 -0
  117. package/build/ui/connect/PrimaryWallet.js +18 -0
  118. package/build/ui/connect/PrimaryWallet.js.map +1 -0
  119. package/build/ui/connect/WCRequest.js +1 -1
  120. package/build/ui/connect/WCRequest.js.map +1 -1
  121. package/build/ui/connect/WalletPicker.js +1 -1
  122. package/build/ui/connect/WalletPicker.js.map +1 -1
  123. package/build/ui/icons/arrow-right.d.ts +3 -1
  124. package/build/ui/icons/arrow-right.js +3 -3
  125. package/build/ui/icons/arrow-right.js.map +1 -1
  126. package/build/ui/icons/close.js +1 -1
  127. package/build/ui/icons/close.js.map +1 -1
  128. package/build/ui/icons/exchange.d.ts +3 -4
  129. package/build/ui/icons/exchange.js +2 -2
  130. package/build/ui/icons/exchange.js.map +1 -1
  131. package/build/ui/icons/logout.js +1 -1
  132. package/build/ui/icons/logout.js.map +1 -1
  133. package/build/ui/icons/pending.js +1 -1
  134. package/build/ui/icons/pending.js.map +1 -1
  135. package/build/ui/icons/plus.d.ts +2 -0
  136. package/build/ui/icons/plus.js +6 -0
  137. package/build/ui/icons/plus.js.map +1 -0
  138. package/build/ui/icons/qr.js +1 -1
  139. package/build/ui/icons/qr.js.map +1 -1
  140. package/build/ui/icons/refresh.d.ts +2 -0
  141. package/build/ui/icons/refresh.js +6 -0
  142. package/build/ui/icons/refresh.js.map +1 -0
  143. package/build/ui/icons/search.js +1 -1
  144. package/build/ui/icons/search.js.map +1 -1
  145. package/build/ui/icons/switch.js +1 -1
  146. package/build/ui/icons/switch.js.map +1 -1
  147. package/build/ui/icons/wallet.js +1 -1
  148. package/build/ui/icons/wallet.js.map +1 -1
  149. package/build/ui/{payment → profile}/DepositQR.js.map +1 -1
  150. package/build/ui/profile/Payment.d.ts +23 -0
  151. package/build/ui/profile/Payment.js +150 -0
  152. package/build/ui/profile/Payment.js.map +1 -0
  153. package/build/ui/profile/Profile.d.ts +7 -0
  154. package/build/ui/profile/Profile.js +135 -0
  155. package/build/ui/profile/Profile.js.map +1 -0
  156. package/build/ui/router.d.ts +19 -5
  157. package/build/ui/router.js +21 -9
  158. package/build/ui/router.js.map +1 -1
  159. package/build/ui/styles.js +4 -11
  160. package/build/ui/styles.js.map +1 -1
  161. package/build/ui/uikit/Stepper.d.ts +13 -0
  162. package/build/ui/uikit/Stepper.js +22 -0
  163. package/build/ui/uikit/Stepper.js.map +1 -0
  164. package/build/ui/uikit/Toast.d.ts +4 -0
  165. package/build/ui/uikit/Toast.js +33 -0
  166. package/build/ui/uikit/Toast.js.map +1 -0
  167. package/build/ui/uikit/button.d.ts +2 -0
  168. package/build/ui/uikit/button.js +52 -0
  169. package/build/ui/uikit/button.js.map +1 -0
  170. package/build/ui/uikit/image.d.ts +6 -0
  171. package/build/ui/uikit/image.js +38 -0
  172. package/build/ui/uikit/image.js.map +1 -0
  173. package/build/ui/uikit/loader.d.ts +2 -0
  174. package/build/ui/uikit/loader.js +50 -0
  175. package/build/ui/uikit/loader.js.map +1 -0
  176. package/build/ui/uikit/tabs.d.ts +12 -0
  177. package/build/ui/uikit/tabs.js +35 -0
  178. package/build/ui/uikit/tabs.js.map +1 -0
  179. package/build/ui/uikit/text.d.ts +6 -0
  180. package/build/ui/uikit/text.js +59 -0
  181. package/build/ui/uikit/text.js.map +1 -0
  182. package/build/ui/utils.d.ts +1 -0
  183. package/build/ui/utils.js +20 -0
  184. package/build/ui/utils.js.map +1 -0
  185. package/package.json +8 -4
  186. package/src/HotConnector.ts +24 -31
  187. package/src/OmniConnector.ts +10 -9
  188. package/src/OmniWallet.ts +24 -25
  189. package/src/core/Intents.ts +222 -151
  190. package/src/core/api.ts +56 -10
  191. package/src/core/bridge.ts +3 -2
  192. package/src/core/index.ts +1 -1
  193. package/src/core/telemetry.ts +28 -0
  194. package/src/core/token.ts +4 -0
  195. package/src/core/tokens.ts +0 -9
  196. package/src/core/types.ts +21 -0
  197. package/src/core/utils.ts +17 -1
  198. package/src/cosmos/connector.ts +22 -26
  199. package/src/cosmos/wallet.ts +3 -8
  200. package/src/evm/connector.ts +5 -0
  201. package/src/evm/wallet.ts +9 -6
  202. package/src/exchange.ts +24 -30
  203. package/src/hot-wallet/google.ts +12 -5
  204. package/src/hot-wallet/proxy.ts +2 -2
  205. package/src/index.ts +3 -1
  206. package/src/near/connector.ts +2 -2
  207. package/src/{core/nearRpc.ts → near/rpc.ts} +9 -23
  208. package/src/near/wallet.ts +39 -31
  209. package/src/solana/{protocol.ts → WalletStandard.ts} +2 -4
  210. package/src/solana/connector.ts +9 -8
  211. package/src/solana/injected/solana-wallet.ts +6 -6
  212. package/src/solana/wallet.ts +11 -20
  213. package/src/stellar/connector.ts +1 -6
  214. package/src/stellar/wallet.ts +17 -17
  215. package/src/ton/connector.ts +1 -5
  216. package/src/ton/wallet.ts +3 -3
  217. package/src/tron/connector.ts +89 -0
  218. package/src/tron/index.ts +7 -0
  219. package/src/tron/wallet.ts +146 -0
  220. package/src/ui/Popup.tsx +12 -4
  221. package/src/ui/{payment → bridge}/Bridge.tsx +266 -212
  222. package/src/ui/{payment → bridge}/SelectRecipient.tsx +5 -4
  223. package/src/ui/{payment → bridge}/SelectSender.tsx +5 -5
  224. package/src/ui/{payment → bridge}/SelectToken.tsx +6 -4
  225. package/src/ui/bridge/TokenCard.tsx +99 -0
  226. package/src/ui/connect/AuthPopup.tsx +1 -1
  227. package/src/ui/connect/ConnectWallet.tsx +16 -10
  228. package/src/ui/connect/PrimaryWallet.tsx +65 -0
  229. package/src/ui/connect/WCRequest.tsx +1 -1
  230. package/src/ui/connect/WalletPicker.tsx +1 -1
  231. package/src/ui/icons/arrow-right.tsx +3 -4
  232. package/src/ui/icons/close.tsx +1 -1
  233. package/src/ui/icons/exchange.tsx +4 -11
  234. package/src/ui/icons/logout.tsx +4 -13
  235. package/src/ui/icons/pending.tsx +2 -4
  236. package/src/ui/icons/plus.tsx +12 -0
  237. package/src/ui/icons/qr.tsx +1 -2
  238. package/src/ui/icons/refresh.tsx +20 -0
  239. package/src/ui/icons/search.tsx +4 -4
  240. package/src/ui/icons/switch.tsx +4 -4
  241. package/src/ui/icons/wallet.tsx +2 -4
  242. package/src/ui/profile/Payment.tsx +309 -0
  243. package/src/ui/{payment → profile}/Profile.tsx +110 -70
  244. package/src/ui/router.tsx +57 -17
  245. package/src/ui/styles.ts +4 -11
  246. package/src/ui/uikit/Stepper.tsx +50 -0
  247. package/src/ui/uikit/Toast.tsx +45 -0
  248. package/src/ui/uikit/button.tsx +53 -0
  249. package/src/ui/uikit/image.tsx +45 -0
  250. package/src/ui/uikit/loader.tsx +52 -0
  251. package/src/ui/uikit/tabs.tsx +56 -0
  252. package/src/ui/uikit/text.tsx +64 -0
  253. package/src/ui/utils.ts +14 -0
  254. package/build/core/nearRpc.js.map +0 -1
  255. package/build/solana/protocol.js.map +0 -1
  256. package/build/solana/wallets.js.map +0 -1
  257. package/build/ui/payment/Bridge.js +0 -358
  258. package/build/ui/payment/Bridge.js.map +0 -1
  259. package/build/ui/payment/Payment.d.ts +0 -16
  260. package/build/ui/payment/Payment.js +0 -50
  261. package/build/ui/payment/Payment.js.map +0 -1
  262. package/build/ui/payment/Profile.d.ts +0 -8
  263. package/build/ui/payment/Profile.js +0 -110
  264. package/build/ui/payment/Profile.js.map +0 -1
  265. package/build/ui/payment/SelectRecipient.js.map +0 -1
  266. package/build/ui/payment/SelectSender.js.map +0 -1
  267. package/build/ui/payment/SelectToken.js.map +0 -1
  268. package/build/ui/payment/TokenCard.js +0 -63
  269. package/build/ui/payment/TokenCard.js.map +0 -1
  270. package/src/ui/payment/Payment.tsx +0 -79
  271. package/src/ui/payment/TokenCard.tsx +0 -98
  272. package/build/solana/{wallets.d.ts → walletStandartList.d.ts} +0 -0
  273. package/build/ui/{payment → bridge}/Bridge.d.ts +3 -3
  274. package/build/ui/{payment → bridge}/SelectRecipient.d.ts +0 -0
  275. package/build/ui/{payment → bridge}/SelectSender.d.ts +2 -2
  276. package/build/ui/{payment → bridge}/SelectToken.d.ts +1 -1
  277. /package/build/ui/{payment → profile}/DepositQR.d.ts +0 -0
  278. /package/build/ui/{payment → profile}/DepositQR.js +0 -0
  279. /package/src/solana/{wallets.ts → walletStandartList.ts} +0 -0
  280. /package/src/ui/{payment → profile}/DepositQR.tsx +0 -0
@@ -1,14 +1,17 @@
1
1
  import { sha256 } from "@noble/hashes/sha2.js";
2
- import { ed25519 } from "@noble/curves/ed25519";
3
- import { base58, base64, hex } from "@scure/base";
4
2
 
5
3
  import type { HotConnector } from "../HotConnector";
6
4
  import type { OmniWallet } from "../OmniWallet";
7
- import type { TransferIntent, MtWithdrawIntent, FtWithdrawIntent, TokenDiffIntent, AuthCallIntent } from "./types";
5
+ import { rpc } from "../near/rpc";
8
6
 
7
+ import type { Intent, Commitment, TokenDiffIntent, MtWithdrawIntent, FtWithdrawIntent, NftWithdrawIntent, TransferIntent } from "./types";
9
8
  import { OmniToken } from "./chains";
9
+ import { formatter } from "./utils";
10
10
  import { tokens } from "./tokens";
11
- import { rpc } from "./nearRpc";
11
+ import { api } from "./api";
12
+
13
+ import { openConnector, openConnectPrimaryWallet, openPayment, openToast } from "../ui/router";
14
+ import { BridgeReview } from "../exchange";
12
15
 
13
16
  export const TGAS = 1000000000000n;
14
17
 
@@ -19,14 +22,22 @@ export class Intents {
19
22
  return new Intents();
20
23
  }
21
24
 
22
- hashes: string[] = [];
23
- intents: (TransferIntent | MtWithdrawIntent | FtWithdrawIntent | TokenDiffIntent | AuthCallIntent)[] = [];
24
- nonce?: Uint8Array;
25
- deadline?: Date;
26
- signer?: OmniWallet | { ed25519PrivateKey: Uint8Array; omniAddress?: string };
27
-
28
- commitments: Record<string, any>[] = [];
25
+ signedHashes: string[] = [];
26
+ commitments: Commitment[] = [];
29
27
  need = new Map<OmniToken, bigint>();
28
+ signer?: OmniWallet;
29
+
30
+ unsignedCommitment?: {
31
+ intents: Intent[];
32
+ nonce?: Uint8Array;
33
+ deadline?: Date;
34
+ };
35
+
36
+ addIntent(intent: Intent) {
37
+ if (!this.unsignedCommitment) this.unsignedCommitment = { intents: [] };
38
+ this.unsignedCommitment.intents.push(intent);
39
+ return this;
40
+ }
30
41
 
31
42
  addNeed(token: OmniToken, amount: bigint) {
32
43
  if (!this.need.has(token)) this.need.set(token, 0n);
@@ -36,7 +47,7 @@ export class Intents {
36
47
 
37
48
  authCall(args: { contractId: string; msg: string; attachNear: bigint; tgas: number }) {
38
49
  this.addNeed(OmniToken.NEAR, args.attachNear);
39
- this.intents.push({
50
+ this.addIntent({
40
51
  min_gas: (BigInt(args.tgas) * TGAS).toString(),
41
52
  attached_deposit: args.attachNear.toString(),
42
53
  contract_id: args.contractId,
@@ -47,6 +58,22 @@ export class Intents {
47
58
  return this;
48
59
  }
49
60
 
61
+ /**
62
+ * Use this method to pay for a merchant's item created in pay.hot-labs.org
63
+ */
64
+ merchantPayment({ merchantId, token, itemId, email, amount, memo }: { token: OmniToken; merchantId: string; itemId: string; amount: number | bigint; memo: string; email: string }) {
65
+ return this.transfer({
66
+ msg: JSON.stringify({ merchant_id: merchantId, item_id: itemId, memo: memo }),
67
+ recipient: "pay.fi.tg",
68
+ amount,
69
+ token,
70
+ }).depositAndExecute({
71
+ title: `Pay ${this.wibe3?.omni(token).readable(amount)} ${this.wibe3?.omni(token).symbol}`,
72
+ serverSideProcessing: true,
73
+ payload: { email },
74
+ });
75
+ }
76
+
50
77
  transfer(args: { recipient: string; token: OmniToken; amount: number | bigint; memo?: string; msg?: string; tgas?: number }) {
51
78
  const omniToken = tokens.get(args.token);
52
79
  const amount = (typeof args.amount === "number" ? omniToken.int(args.amount) : args.amount).toString();
@@ -60,7 +87,7 @@ export class Intents {
60
87
  };
61
88
 
62
89
  this.addNeed(args.token, BigInt(amount));
63
- this.intents.push(intent);
90
+ this.addIntent(intent);
64
91
  return this;
65
92
  }
66
93
 
@@ -82,11 +109,11 @@ export class Intents {
82
109
  msg: args.msg,
83
110
  };
84
111
 
85
- this.intents.push(intent);
112
+ this.addIntent(intent);
86
113
  return this;
87
114
  }
88
115
 
89
- tokenDiff(args: Record<OmniToken, bigint | number>) {
116
+ tokenDiff(args: Record<string, bigint | number>) {
90
117
  const parse = (token: OmniToken, amount: bigint | number): [string, string] => {
91
118
  if (typeof amount === "number") return [token.toString(), tokens.get(token).int(amount).toString()];
92
119
  return [token.toString(), amount.toString()];
@@ -105,45 +132,44 @@ export class Intents {
105
132
  }
106
133
  }
107
134
 
108
- this.intents.push(intent);
135
+ this.addIntent(intent);
109
136
  return this;
110
137
  }
111
138
 
112
- addRawIntent(rawIntent: Record<string, any>) {
139
+ addRawIntent(rawIntent: Intent) {
113
140
  if (!rawIntent.intent) throw new Error("Intent must have 'intent' field");
114
141
  const intentType = rawIntent.intent;
115
142
 
116
143
  if (intentType === "token_diff") {
117
- const diff = rawIntent.diff || rawIntent.token_diff;
118
- if (!diff) throw new Error("token_diff intent must have 'diff' or 'token_diff' field");
119
-
120
144
  const tokenDiffArgs: Record<OmniToken, bigint> = {} as Record<OmniToken, bigint>;
121
- for (const [token, amountStr] of Object.entries(diff)) {
145
+ for (const [token, amountStr] of Object.entries(rawIntent.diff)) {
122
146
  tokenDiffArgs[token as OmniToken] = BigInt(amountStr as string);
123
147
  }
124
148
  return this.tokenDiff(tokenDiffArgs);
125
149
  }
126
150
 
127
151
  if (intentType === "transfer") {
128
- if (!rawIntent.tokens || !rawIntent.receiver_id) {
129
- throw new Error("transfer intent must have 'tokens' and 'receiver_id' fields");
130
- }
131
-
132
152
  const tokens: Record<OmniToken, bigint> = {} as Record<OmniToken, bigint>;
133
153
  for (const [token, amount] of Object.entries(rawIntent.tokens)) {
134
154
  tokens[token as OmniToken] = BigInt(amount as string);
135
155
  }
156
+
136
157
  return this.batchTransfer({
158
+ tgas: rawIntent.min_gas ? Number(BigInt(rawIntent.min_gas) / TGAS) : undefined,
137
159
  recipient: rawIntent.receiver_id,
138
- tokens,
139
160
  memo: rawIntent.memo,
140
161
  msg: rawIntent.msg,
141
- tgas: rawIntent.min_gas ? Number(BigInt(rawIntent.min_gas) / TGAS) : undefined,
162
+ tokens,
142
163
  });
143
164
  }
144
165
 
145
166
  if (intentType === "mt_withdraw") {
146
- const intent: MtWithdrawIntent = {
167
+ for (let i = 0; i < rawIntent.amounts.length; i++) {
168
+ const token = `nep245:${rawIntent.token}:${rawIntent.token_ids[i]}` as OmniToken;
169
+ this.addNeed(token, BigInt(rawIntent.amounts[i]));
170
+ }
171
+
172
+ this.addIntent({
147
173
  intent: "mt_withdraw",
148
174
  amounts: rawIntent.amounts,
149
175
  receiver_id: rawIntent.receiver_id,
@@ -152,58 +178,71 @@ export class Intents {
152
178
  memo: rawIntent.memo,
153
179
  msg: rawIntent.msg,
154
180
  min_gas: rawIntent.min_gas,
155
- };
156
-
157
- for (let i = 0; i < rawIntent.amounts.length; i++) {
158
- const token = `nep245:${rawIntent.token}:${rawIntent.token_ids[i]}` as OmniToken;
159
- this.addNeed(token, BigInt(rawIntent.amounts[i]));
160
- }
161
-
162
- this.intents.push(intent);
181
+ } as MtWithdrawIntent);
163
182
  return this;
164
183
  }
165
184
 
166
185
  if (intentType === "ft_withdraw") {
167
- if (!rawIntent.token || !rawIntent.receiver_id || !rawIntent.amount) {
168
- throw new Error("ft_withdraw intent must have 'token', 'receiver_id', and 'amount' fields");
169
- }
170
-
171
- const token = `nep141:${rawIntent.token}` as OmniToken;
172
186
  return this.withdraw({
187
+ token: `nep141:${rawIntent.token}`,
173
188
  amount: BigInt(rawIntent.amount),
174
189
  receiver: rawIntent.receiver_id,
175
190
  memo: rawIntent.memo,
176
191
  msg: rawIntent.msg,
177
- token,
178
192
  });
179
193
  }
180
194
 
181
195
  if (intentType === "auth_call") {
182
- if (!rawIntent.contract_id || !rawIntent.msg || !rawIntent.attached_deposit || !rawIntent.min_gas) {
183
- throw new Error("auth_call intent must have 'contract_id', 'msg', 'attached_deposit', and 'min_gas' fields");
184
- }
185
-
186
196
  return this.authCall({
187
- contractId: rawIntent.contract_id,
188
- msg: rawIntent.msg,
189
197
  attachNear: BigInt(rawIntent.attached_deposit),
190
198
  tgas: Number(BigInt(rawIntent.min_gas) / TGAS),
199
+ contractId: rawIntent.contract_id,
200
+ msg: rawIntent.msg,
201
+ });
202
+ }
203
+
204
+ if (intentType === "add_public_key") {
205
+ return this.addPublicKey(rawIntent.public_key);
206
+ }
207
+
208
+ if (intentType === "remove_public_key") {
209
+ return this.removePublicKey(rawIntent.public_key);
210
+ }
211
+
212
+ if (intentType === "nft_withdraw") {
213
+ return this.withdraw({
214
+ token: rawIntent.token_id,
215
+ receiver: rawIntent.receiver_id,
216
+ memo: rawIntent.memo,
217
+ msg: rawIntent.msg,
218
+ tgas: rawIntent.min_gas ? Number(BigInt(rawIntent.min_gas) / TGAS) : undefined,
219
+ amount: 1n,
191
220
  });
192
221
  }
193
222
 
194
223
  throw new Error(`Unsupported intent type: ${intentType}`);
195
224
  }
196
225
 
197
- withdraw(args: { token: OmniToken; amount: number | bigint; receiver: string; memo?: string; msg?: string; tgas?: number }) {
226
+ addPublicKey(publicKey: string) {
227
+ this.addIntent({ intent: "add_public_key", public_key: publicKey });
228
+ return this;
229
+ }
230
+
231
+ removePublicKey(publicKey: string) {
232
+ this.addIntent({ intent: "remove_public_key", public_key: publicKey });
233
+ return this;
234
+ }
235
+
236
+ withdraw(args: { token: string; amount: number | bigint; receiver: string; memo?: string; msg?: string; tgas?: number }) {
198
237
  const omniToken = tokens.get(args.token);
199
238
  const amount = (typeof args.amount === "number" ? omniToken.int(args.amount) : args.amount).toString();
200
239
  const [standart, ...tokenParts] = args.token.split(":");
201
- this.addNeed(args.token, BigInt(amount));
240
+ this.addNeed(args.token as OmniToken, BigInt(amount));
202
241
 
203
242
  if (standart === "nep245") {
204
243
  const mtContract = tokenParts[0];
205
244
  const tokenId = tokenParts.slice(1).join(":");
206
- const intent: MtWithdrawIntent = {
245
+ this.addIntent({
207
246
  intent: "mt_withdraw",
208
247
  amounts: [amount],
209
248
  receiver_id: args.receiver,
@@ -212,23 +251,31 @@ export class Intents {
212
251
  memo: args.memo,
213
252
  msg: args.msg,
214
253
  min_gas: args.tgas ? (BigInt(args.tgas) * TGAS).toString() : undefined,
215
- };
216
-
217
- this.intents.push(intent);
254
+ } as MtWithdrawIntent);
218
255
  return this;
219
256
  }
220
257
 
221
258
  if (standart === "nep141") {
222
- const intent: FtWithdrawIntent = {
259
+ this.addIntent({
223
260
  intent: "ft_withdraw",
224
261
  receiver_id: args.receiver,
225
262
  token: tokenParts.join(":"),
226
263
  amount: amount,
227
264
  memo: args.memo,
228
265
  msg: args.msg,
229
- };
266
+ } as FtWithdrawIntent);
267
+ return this;
268
+ }
230
269
 
231
- this.intents.push(intent);
270
+ if (standart === "nep171") {
271
+ this.addIntent({
272
+ intent: "nft_withdraw",
273
+ receiver_id: args.receiver,
274
+ token_id: tokenParts.join(":"),
275
+ min_gas: args.tgas ? (BigInt(args.tgas) * TGAS).toString() : undefined,
276
+ memo: args.memo,
277
+ msg: args.msg,
278
+ } as NftWithdrawIntent);
232
279
  return this;
233
280
  }
234
281
 
@@ -236,164 +283,188 @@ export class Intents {
236
283
  }
237
284
 
238
285
  attachHashes(hashes: string[]) {
239
- this.hashes.push(...hashes);
286
+ this.signedHashes.push(...hashes);
240
287
  return this;
241
288
  }
242
289
 
243
- attachWallet(wallet: OmniWallet) {
290
+ attachWallet(wallet?: OmniWallet) {
244
291
  this.signer = wallet;
245
292
  return this;
246
293
  }
247
294
 
248
295
  attachDeadline(deadline: Date) {
249
- this.deadline = deadline;
296
+ if (!this.unsignedCommitment) this.unsignedCommitment = { intents: [] };
297
+ this.unsignedCommitment.deadline = deadline;
250
298
  return this;
251
299
  }
252
300
 
253
301
  attachNonce(nonce: Uint8Array) {
254
- this.nonce = nonce;
302
+ if (!this.unsignedCommitment) this.unsignedCommitment = { intents: [] };
303
+ this.unsignedCommitment.nonce = nonce;
255
304
  return this;
256
305
  }
257
306
 
258
307
  attachTimeout(seconds: number) {
259
- this.deadline = new Date(Date.now() + seconds * 1000);
308
+ if (!this.unsignedCommitment) this.unsignedCommitment = { intents: [] };
309
+ this.unsignedCommitment.deadline = new Date(Date.now() + seconds * 1000);
260
310
  return this;
261
311
  }
262
312
 
263
313
  attachSeed(seed: string) {
264
- this.nonce = new Uint8Array(sha256(new TextEncoder().encode(seed))).slice(0, 32);
314
+ if (!this.unsignedCommitment) this.unsignedCommitment = { intents: [] };
315
+ this.unsignedCommitment.nonce = new Uint8Array(sha256(new TextEncoder().encode(seed))).slice(0, 32);
316
+ return this;
317
+ }
318
+
319
+ attachCommitment(commitment: Commitment) {
320
+ this.commitments.push(commitment);
265
321
  return this;
266
322
  }
267
323
 
268
- take(token: OmniToken, amount: number | bigint) {
324
+ take(token: string, amount: number | bigint) {
269
325
  const intAmount = typeof amount === "number" ? tokens.get(token).int(amount) : amount;
270
326
 
271
- this.addNeed(token, intAmount);
272
- const tokenDiff = this.intents.find((intent) => intent.intent === "token_diff");
327
+ // this.addNeed(token, -intAmount); Do we need to add the need here?
328
+ const tokenDiff = this.unsignedCommitment?.intents.find((intent) => intent.intent === "token_diff");
273
329
 
274
330
  if (tokenDiff) tokenDiff.diff[token.toString()] = intAmount.toString();
275
- else this.intents.push({ intent: "token_diff", diff: { [token.toString()]: intAmount.toString() } });
331
+ else this.addIntent({ intent: "token_diff", diff: { [token.toString()]: intAmount.toString() } });
276
332
  return this;
277
333
  }
278
334
 
279
- give(token: OmniToken, amount: number | bigint) {
335
+ give(token: string, amount: number | bigint) {
280
336
  const intAmount = typeof amount === "number" ? tokens.get(token).int(amount) : amount;
281
337
 
282
- this.addNeed(token, -intAmount);
283
- const tokenDiff = this.intents.find((intent) => intent.intent === "token_diff");
338
+ this.addNeed(token as OmniToken, intAmount);
339
+ const tokenDiff = this.unsignedCommitment?.intents.find((intent) => intent.intent === "token_diff");
284
340
 
285
341
  if (tokenDiff) tokenDiff.diff[token.toString()] = (-intAmount).toString();
286
- else this.intents.push({ intent: "token_diff", diff: { [token.toString()]: (-intAmount).toString() } });
342
+ else this.addIntent({ intent: "token_diff", diff: { [token.toString()]: (-intAmount).toString() } });
287
343
  return this;
288
344
  }
289
345
 
290
- async signRaw({ ed25519PrivateKey, intentsAddress, checkTokens }: { ed25519PrivateKey: Uint8Array; intentsAddress?: string; checkTokens?: boolean }) {
291
- if (checkTokens) {
292
- await this.checkRequiredTokens();
346
+ async signSequence() {
347
+ const signer = this.signer;
348
+ if (!signer) throw new Error("No signer attached");
349
+ if (!signer.omniAddress) throw new Error("No omni address");
350
+
351
+ const commitments: Commitment[] = [];
352
+ for (const intent of this.unsignedCommitment?.intents || []) {
353
+ commitments.push(
354
+ await signer.signIntents([intent], {
355
+ deadline: this.unsignedCommitment?.deadline ? +this.unsignedCommitment.deadline : undefined,
356
+ nonce: this.unsignedCommitment?.nonce,
357
+ })
358
+ );
293
359
  }
294
360
 
295
- const publicKey = ed25519.getPublicKey(ed25519PrivateKey);
296
- const nonce = new Uint8Array(this.nonce || window.crypto.getRandomValues(new Uint8Array(32)));
361
+ return commitments;
362
+ }
297
363
 
298
- const message = JSON.stringify({
299
- deadline: this.deadline ? new Date(this.deadline).toISOString() : "2100-01-01T00:00:00.000Z",
300
- nonce: base64.encode(nonce),
301
- verifying_contract: "intents.near",
302
- signer_id: intentsAddress || hex.encode(publicKey).toLowerCase(),
303
- intents: this.intents,
364
+ async sign() {
365
+ const signer = this.signer;
366
+ if (!signer) throw new Error("No signer attached");
367
+ if (!signer.omniAddress) throw new Error("No omni address");
368
+ const commitment = await signer.signIntents(this.unsignedCommitment?.intents || [], {
369
+ deadline: this.unsignedCommitment?.deadline ? +this.unsignedCommitment.deadline : undefined,
370
+ nonce: this.unsignedCommitment?.nonce,
304
371
  });
305
372
 
306
- return {
307
- signature: `ed25519:${base58.encode(ed25519.sign(message, ed25519PrivateKey))}`,
308
- public_key: `ed25519:${base58.encode(publicKey)}`,
309
- standard: "raw_ed25519",
310
- payload: message,
311
- };
312
- }
313
-
314
- async attachCommitment(commitment: Record<string, any>) {
373
+ this.unsignedCommitment = undefined;
315
374
  this.commitments.push(commitment);
316
375
  return this;
317
376
  }
318
377
 
319
- async attachSigner(signer: OmniWallet | { ed25519PrivateKey: Uint8Array; omniAddress?: string }) {
320
- this.signer = signer;
321
- return this;
322
- }
323
-
324
- async checkRequiredTokens() {
325
- if (this.wibe3 == null) return;
326
- for (const [token, needAmount] of this.need.entries()) {
327
- if (needAmount <= 0n) continue;
328
- await this.wibe3.requestToken(token, needAmount);
329
- }
378
+ async simulate() {
379
+ if (this.commitments.length === 0) throw new Error("No commitments attached");
380
+ return await Intents.simulateIntents(this.commitments);
330
381
  }
331
382
 
332
- async sign(params = { checkTokens: true }) {
333
- const signer = this.signer;
334
- if (!signer) throw new Error("No signer attached");
335
- if (!signer.omniAddress) throw new Error("No omni address");
383
+ async setupSigner() {
384
+ if (!this.wibe3) throw new Error("No wibe3 attached");
385
+ if (this.signer) return this.signer;
336
386
 
337
- if ("ed25519PrivateKey" in signer) {
338
- return await this.signRaw({
339
- ed25519PrivateKey: signer.ed25519PrivateKey,
340
- intentsAddress: signer.omniAddress,
341
- checkTokens: params.checkTokens,
342
- });
387
+ if (this.wibe3.priorityWallet) {
388
+ this.signer = this.wibe3.priorityWallet;
389
+ return this.signer;
343
390
  }
344
391
 
345
- if (params.checkTokens) {
346
- await this.checkRequiredTokens();
347
- }
392
+ if (this.wibe3.wallets.length > 0) await openConnectPrimaryWallet(this.wibe3);
393
+ else await openConnector(this.wibe3);
394
+
395
+ if (this.wibe3.priorityWallet == undefined) throw new Error("No signer attached");
396
+ this.signer = this.wibe3.priorityWallet;
397
+ return this.signer;
398
+ }
348
399
 
349
- return await signer.signIntents(this.intents, {
350
- deadline: this.deadline ? +this.deadline : undefined,
351
- nonce: this.nonce,
400
+ async openSignFlow({ title, allowedTokens, onConfirm }: { title?: string; allowedTokens?: string[]; onConfirm: (args: { depositQoute?: BridgeReview; processing?: () => Promise<BridgeReview> }) => Promise<void> }) {
401
+ if (!this.wibe3) throw "Attach wibe3";
402
+ if (!this.signer) throw "Attach signer";
403
+
404
+ // TODO: Handle multiple payables
405
+ const payableToken = tokens.get(Array.from(this.need.keys())[0]);
406
+ const payableAmount = this.need.get(payableToken.omniAddress as OmniToken) || 0n;
407
+ const balance = await this.wibe3.fetchToken(payableToken!, this.signer);
408
+ const prepaidAmount = formatter.bigIntMin(payableAmount, balance);
409
+
410
+ return await openPayment(this.wibe3, {
411
+ onConfirm,
412
+ needAmount: payableAmount - prepaidAmount,
413
+ allowedTokens,
414
+ prepaidAmount,
415
+ payableToken,
416
+ intents: this,
417
+ title,
352
418
  });
353
419
  }
354
420
 
355
- async simulate(params = { checkTokens: true }) {
356
- const signed = await this.sign(params);
357
- return await Intents.simulateIntents([signed]);
421
+ async depositAndExecute({ title = "Payment", message, allowedTokens, serverSideProcessing, payload }: { title?: string; message?: string; allowedTokens?: string[]; serverSideProcessing?: boolean; payload?: Record<string, any> } = {}) {
422
+ await this.setupSigner();
423
+ if (this.need.size === 0) return this.execute();
424
+
425
+ await this.openSignFlow({
426
+ title,
427
+ allowedTokens,
428
+ onConfirm: async ({ depositQoute, processing }: { depositQoute?: BridgeReview; processing?: () => Promise<BridgeReview> }) => {
429
+ if (!serverSideProcessing) return;
430
+
431
+ let depositAddress: string | undefined;
432
+ if (depositQoute?.qoute === "deposit") await processing?.();
433
+ else if (depositQoute?.qoute === "withdraw") await processing?.();
434
+ else depositAddress = depositQoute?.qoute?.depositAddress;
435
+
436
+ await api.yieldIntentCall({
437
+ depositAddress: depositAddress,
438
+ commitment: this.commitments[0],
439
+ payload: payload || {},
440
+ });
441
+ },
442
+ });
443
+
444
+ if (serverSideProcessing) return;
445
+ const close = openToast(message || "Executing payment");
446
+ await this.execute().finally(() => close());
358
447
  }
359
448
 
360
- async execute(params = { checkTokens: true }) {
361
- const signed = await this.sign(params);
362
- const hash = await Intents.publishSignedIntents([...this.commitments, signed], this.hashes);
449
+ async execute() {
450
+ if (this.unsignedCommitment != null) await this.sign();
451
+ const task = Intents.publish(this.commitments, this.signedHashes);
452
+ this.commitments = [];
453
+ this.signedHashes = [];
454
+
455
+ const hash = await task;
363
456
  await rpc.waitTransactionResult(hash, "intents.near");
364
457
  return hash;
365
458
  }
366
459
 
367
- static async publishSignedIntents(signed: Record<string, any>[], hashes: string[] = []): Promise<string> {
368
- const res = await fetch("https://api0.herewallet.app/api/v1/evm/intent-solver", {
369
- headers: { "Content-Type": "application/json" },
370
- method: "POST",
371
- body: JSON.stringify({
372
- params: [{ signed_datas: signed, quote_hashes: hashes }],
373
- method: "publish_intents",
374
- id: "dontcare",
375
- jsonrpc: "2.0",
376
- }),
377
- });
378
-
379
- const { result } = await res.json();
460
+ static async publish(signed: Commitment[], hashes: string[] = []): Promise<string> {
461
+ const result = await api.publishIntents(signed, hashes);
380
462
  if (result.status === "FAILED") throw result.reason;
381
463
  const intentResult = result.intent_hashes[0];
382
464
 
383
465
  const getStatus = async () => {
384
- const statusRes = await fetch("https://api0.herewallet.app/api/v1/evm/intent-solver", {
385
- headers: { "Content-Type": "application/json" },
386
- method: "POST",
387
- body: JSON.stringify({
388
- params: [{ intent_hash: intentResult }],
389
- method: "get_status",
390
- id: "dontcare",
391
- jsonrpc: "2.0",
392
- }),
393
- });
394
-
395
- const { result } = await statusRes.json();
396
- return result;
466
+ const statusResult = await api.getIntentsStatus(intentResult);
467
+ return statusResult;
397
468
  };
398
469
 
399
470
  const fetchResult = async () => {
@@ -417,7 +488,7 @@ export class Intents {
417
488
  });
418
489
  }
419
490
 
420
- static async simulateIntents(signed: Record<string, any>[]) {
491
+ static async simulateIntents(signed: Commitment[]) {
421
492
  return await rpc.viewMethod({
422
493
  args: { signed: signed },
423
494
  methodName: "simulate_intents",