@ultraos/wallet-sdk 0.3.1 → 0.6.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/CHANGELOG.md +47 -0
- package/README.md +19 -8
- package/dist/index.mjs +559 -0
- package/dist/index.mjs.map +7 -0
- package/package.json +18 -3
- package/src/lib/interfaces/connect-params.interface.d.ts +12 -0
- package/src/lib/interfaces/connect-params.interface.d.ts.map +1 -1
- package/src/lib/interfaces/connect-params.interface.js.map +1 -1
- package/src/lib/interfaces/index.d.ts +0 -1
- package/src/lib/interfaces/index.d.ts.map +1 -1
- package/src/lib/interfaces/index.js +0 -1
- package/src/lib/interfaces/index.js.map +1 -1
- package/src/lib/interfaces/wallet-provider-response.interface.d.ts +84 -27
- package/src/lib/interfaces/wallet-provider-response.interface.d.ts.map +1 -1
- package/src/lib/interfaces/wallet-provider-response.interface.js.map +1 -1
- package/src/lib/interfaces/wallet-provider.interface.d.ts +1 -17
- package/src/lib/interfaces/wallet-provider.interface.d.ts.map +1 -1
- package/src/lib/interfaces/wallet-provider.interface.js.map +1 -1
- package/src/lib/providers/extension-provider/extension.provider.d.ts +1 -7
- package/src/lib/providers/extension-provider/extension.provider.d.ts.map +1 -1
- package/src/lib/providers/extension-provider/extension.provider.js +0 -6
- package/src/lib/providers/extension-provider/extension.provider.js.map +1 -1
- package/src/lib/providers/web-provider/web.provider.d.ts +1 -7
- package/src/lib/providers/web-provider/web.provider.d.ts.map +1 -1
- package/src/lib/providers/web-provider/web.provider.js +0 -10
- package/src/lib/providers/web-provider/web.provider.js.map +1 -1
- package/src/lib/ultra-wallet-sdk.d.ts +1 -7
- package/src/lib/ultra-wallet-sdk.d.ts.map +1 -1
- package/src/lib/ultra-wallet-sdk.js +0 -6
- package/src/lib/ultra-wallet-sdk.js.map +1 -1
- package/src/lib/interfaces/purchase-item.interface.d.ts +0 -8
- package/src/lib/interfaces/purchase-item.interface.d.ts.map +0 -1
- package/src/lib/interfaces/purchase-item.interface.js +0 -9
- package/src/lib/interfaces/purchase-item.interface.js.map +0 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@ultraos/wallet-sdk` are documented in this file.
|
|
4
|
+
|
|
5
|
+
## 0.6.0
|
|
6
|
+
|
|
7
|
+
### Removed
|
|
8
|
+
|
|
9
|
+
- `purchaseItem()` and the `PurchaseItemType` / `PurchaseItemResult` types. Neither wallet serves it any more: the
|
|
10
|
+
extension redesign deliberately removed Ultra-platform checkout dependencies and the Web Wallet never shipped the
|
|
11
|
+
route, so calls could only hang until the user closed the popup.
|
|
12
|
+
- `addNetwork()`. The extension removed its dApp-callable route in the v4 security audit (N-N1): adding a network
|
|
13
|
+
without an explicit approval screen is a silent RPC-takeover vector. Users add custom networks in the wallet's
|
|
14
|
+
Settings → Networks; dApps can then call `switchNetwork()`.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- Corrected the `ConnectResult.blockchainid` documentation: it is the connected account **name** (equal to
|
|
19
|
+
`selectedAccount.accountName`), not a network identifier.
|
|
20
|
+
- Declared the `nonce` / `signedNonce` fields every wallet already returns from `connect({ nonce })`.
|
|
21
|
+
- Marked the connect-time attestation surface (`ConnectAttestation`, `ConnectResult.attestation`,
|
|
22
|
+
`ConnectParams.requireAttestation`) `@experimental`: only the browser extension issues it and no Ultra service
|
|
23
|
+
consumes it yet.
|
|
24
|
+
- Published as a bundled ES module (`dist/index.mjs` + `exports` map), as in 0.3.2, now produced reproducibly by
|
|
25
|
+
`npm run build:wallet-sdk`.
|
|
26
|
+
|
|
27
|
+
## 0.5.0
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- `requireAttestation?: boolean` on `ConnectParams`. When set, a dApp signals that it needs a connect-time identity
|
|
32
|
+
attestation; if the wallet supports attestation but the origin hasn't yet consented, the wallet prompts for consent
|
|
33
|
+
via the existing connect prompt (no separate signature dialog) and resolves `connect()` with a populated
|
|
34
|
+
`ConnectResult.attestation`. Strictly additive and pass-through — the SDK forwards the flag to the wallet verbatim and
|
|
35
|
+
performs no logic on it; wallets without attestation support ignore it. Omitting it preserves existing behavior. See
|
|
36
|
+
the RFC:
|
|
37
|
+
<https://github.com/ultraio/ultra-tool-kit/blob/feature/ai-enhancement/docs/proposals/wallet-native-attestation.md>
|
|
38
|
+
|
|
39
|
+
## 0.4.0
|
|
40
|
+
|
|
41
|
+
### Added
|
|
42
|
+
|
|
43
|
+
- `ConnectAttestation` type and an optional `attestation` field on `ConnectResult`. When the connected wallet supports
|
|
44
|
+
silent connect-time identity attestation, `connect()` now surfaces it; otherwise `attestation` is `undefined`. This is
|
|
45
|
+
a strictly additive, type-only change — the SDK passes the value through verbatim and performs no verification. See
|
|
46
|
+
the RFC:
|
|
47
|
+
<https://github.com/ultraio/ultra-tool-kit/blob/feature/ai-enhancement/docs/proposals/wallet-native-attestation.md>
|
package/README.md
CHANGED
|
@@ -44,7 +44,7 @@ await ultra.signTransaction({
|
|
|
44
44
|
contract: 'eosio.token',
|
|
45
45
|
action: 'transfer',
|
|
46
46
|
data: { from: 'user', to: 'receiver', quantity: '1.00000000 UOS', memo: '' },
|
|
47
|
-
|
|
47
|
+
// authorization defaults to the connected account's `active` permission
|
|
48
48
|
});
|
|
49
49
|
```
|
|
50
50
|
|
|
@@ -55,7 +55,7 @@ You can pass options during initialization:
|
|
|
55
55
|
```ts
|
|
56
56
|
new UltraWalletSDK({
|
|
57
57
|
environment: 'testnet', // or 'mainnet', or provide custom URL
|
|
58
|
-
provider: 'web', // or 'extension', use a specific provider
|
|
58
|
+
provider: 'web', // or 'extension', use a specific provider independently of auto-detection
|
|
59
59
|
});
|
|
60
60
|
```
|
|
61
61
|
|
|
@@ -63,12 +63,23 @@ new UltraWalletSDK({
|
|
|
63
63
|
|
|
64
64
|
### Methods
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
All methods resolve to `UltraResponse<T>` (`{ status: 'success', data: T }`) and reject with
|
|
67
|
+
`{ status, code, message }`.
|
|
68
|
+
|
|
69
|
+
| Method | Extension | Web Wallet |
|
|
70
|
+
| ------------------------------------------------------------------------------------- | --------- | ---------- |
|
|
71
|
+
| `connect(params?: ConnectParams)` / `disconnect()` | ✅ | ✅ |
|
|
72
|
+
| `signMessage(message: string)` | ✅ | ✅ |
|
|
73
|
+
| `signTransaction(transaction, options?: { signOnly?: boolean })` | ✅ | ✅ |
|
|
74
|
+
| `getChainId()` | ✅ | ✅ |
|
|
75
|
+
| `getAccounts()` / `getSelectedAccount()` / `getAvailableAuthorizations()` | ✅ | — |
|
|
76
|
+
| `getNetwork()` / `getNetworks()` / `switchNetwork(chainId)` | ✅ | — |
|
|
77
|
+
| `on(event, cb)` / `off(event, cb)` — `accountChanged`, `networkChanged`, `disconnect` | ✅ | — |
|
|
78
|
+
| `dispose()` | ✅ | ✅ |
|
|
79
|
+
|
|
80
|
+
The Web Wallet is currently deployed for **mainnet** only.
|
|
81
|
+
|
|
82
|
+
Full documentation: <https://developers.ultra.io/products/ultra-wallet-sdk/>
|
|
72
83
|
|
|
73
84
|
---
|
|
74
85
|
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
// dist/libs/wallet-sdk/src/lib/interfaces/error-enum.js
|
|
2
|
+
var SdkErrorCode;
|
|
3
|
+
(function(SdkErrorCode2) {
|
|
4
|
+
SdkErrorCode2[SdkErrorCode2["USER_REJECTED_REQUEST"] = 4001] = "USER_REJECTED_REQUEST";
|
|
5
|
+
SdkErrorCode2[SdkErrorCode2["WALLET_HANDSHAKE_TIMEOUT"] = 4300] = "WALLET_HANDSHAKE_TIMEOUT";
|
|
6
|
+
SdkErrorCode2[SdkErrorCode2["WALLET_WINDOW_UNAVAILABLE"] = 4301] = "WALLET_WINDOW_UNAVAILABLE";
|
|
7
|
+
SdkErrorCode2[SdkErrorCode2["REQUESTED_RESOURCE_NOT_AVAILABLE"] = 32002] = "REQUESTED_RESOURCE_NOT_AVAILABLE";
|
|
8
|
+
SdkErrorCode2[SdkErrorCode2["UNKNOWN_ERROR"] = -32604] = "UNKNOWN_ERROR";
|
|
9
|
+
})(SdkErrorCode || (SdkErrorCode = {}));
|
|
10
|
+
var SDK_ERROR_MESSAGE = {
|
|
11
|
+
[SdkErrorCode.USER_REJECTED_REQUEST]: "The user rejected the request.",
|
|
12
|
+
[SdkErrorCode.WALLET_HANDSHAKE_TIMEOUT]: "Timeout to connect with the web wallet.",
|
|
13
|
+
[SdkErrorCode.WALLET_WINDOW_UNAVAILABLE]: "Wallet window blocked by browser or failed to open.",
|
|
14
|
+
[SdkErrorCode.REQUESTED_RESOURCE_NOT_AVAILABLE]: "Requested resource not available.",
|
|
15
|
+
[SdkErrorCode.UNKNOWN_ERROR]: "Unknown error occurred."
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// dist/libs/wallet-sdk/src/lib/interfaces/wallet-provider-response.interface.js
|
|
19
|
+
var ResponseStatus;
|
|
20
|
+
(function(ResponseStatus2) {
|
|
21
|
+
ResponseStatus2["SUCCESS"] = "success";
|
|
22
|
+
ResponseStatus2["FAIL"] = "fail";
|
|
23
|
+
ResponseStatus2["ERROR"] = "error";
|
|
24
|
+
})(ResponseStatus || (ResponseStatus = {}));
|
|
25
|
+
|
|
26
|
+
// dist/libs/wallet-sdk/src/lib/config/ultra-wallet-sdk.config.js
|
|
27
|
+
var UltraWalletSdkConfig = Object.freeze({
|
|
28
|
+
width: 420,
|
|
29
|
+
height: 815,
|
|
30
|
+
walletUrls: {
|
|
31
|
+
mainnet: "https://web-wallet.ultra.io",
|
|
32
|
+
testnet: "https://web-wallet.staging.ultra.io"
|
|
33
|
+
},
|
|
34
|
+
networkInfo: {
|
|
35
|
+
mainnet: {
|
|
36
|
+
chainId: "a9c481dfbc7d9506dc7e87e9a137c931b0a9303f64fd7a1d08b8230133920097"
|
|
37
|
+
},
|
|
38
|
+
testnet: {
|
|
39
|
+
chainId: "7fc56be645bb76ab9d747b53089f132dcb7681db06f0852cfa03eaf6f7ac80e9"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
checkWindowInterval: 500,
|
|
43
|
+
handshakeTimeout: 1e4
|
|
44
|
+
});
|
|
45
|
+
var ultra_wallet_sdk_config_default = UltraWalletSdkConfig;
|
|
46
|
+
|
|
47
|
+
// dist/libs/wallet-sdk/src/lib/utils/chain-validator.js
|
|
48
|
+
function isValidChain(targetNetwork, walletChainId) {
|
|
49
|
+
const { chainId } = ultra_wallet_sdk_config_default.networkInfo[targetNetwork] || {};
|
|
50
|
+
return !chainId || chainId === walletChainId;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// dist/libs/wallet-sdk/src/lib/providers/extension-provider/extension.provider.js
|
|
54
|
+
var HEARTBEAT_INTERVAL_MS = 2e3;
|
|
55
|
+
var ExtensionProvider = class {
|
|
56
|
+
/**
|
|
57
|
+
* Access window.ultra typed as UltraWalletProvider.
|
|
58
|
+
* At runtime, window.ultra is a Proxy that handles all SDK method calls.
|
|
59
|
+
* We cast here rather than declaring a global Window augmentation to avoid
|
|
60
|
+
* conflicting with the app-level window.d.ts which types window.ultra as IUltraInternalAPI.
|
|
61
|
+
*/
|
|
62
|
+
get walletProvider() {
|
|
63
|
+
return window.ultra;
|
|
64
|
+
}
|
|
65
|
+
constructor(options) {
|
|
66
|
+
this.options = options;
|
|
67
|
+
this.eventListeners = /* @__PURE__ */ new Map();
|
|
68
|
+
this.listenerIds = /* @__PURE__ */ new Map();
|
|
69
|
+
this.heartbeatTimer = null;
|
|
70
|
+
this.messageHandler = null;
|
|
71
|
+
this.initWindowEventListener();
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Wire-format match: the BG's MessageType.EVENT serialises as the uppercase
|
|
75
|
+
* string 'EVENT'. We uppercase the incoming type so a future SDK build that
|
|
76
|
+
* emits lowercase (or any case variant) still dispatches. Payload shape:
|
|
77
|
+
* `{ event, origin, data }`.
|
|
78
|
+
*/
|
|
79
|
+
initWindowEventListener() {
|
|
80
|
+
if (typeof window === "undefined")
|
|
81
|
+
return;
|
|
82
|
+
if (this.messageHandler)
|
|
83
|
+
return;
|
|
84
|
+
this.messageHandler = (event) => {
|
|
85
|
+
if (event.source !== window || !event.data)
|
|
86
|
+
return;
|
|
87
|
+
const msg = event.data;
|
|
88
|
+
const msgType = typeof msg.type === "string" ? msg.type.toUpperCase() : "";
|
|
89
|
+
if (msgType !== "EVENT" || !msg.payload)
|
|
90
|
+
return;
|
|
91
|
+
const eventName = msg.payload.event;
|
|
92
|
+
if (!eventName)
|
|
93
|
+
return;
|
|
94
|
+
const cbs = this.eventListeners.get(eventName);
|
|
95
|
+
if (cbs)
|
|
96
|
+
cbs.forEach((cb) => cb(msg.payload.data));
|
|
97
|
+
};
|
|
98
|
+
window.addEventListener("message", this.messageHandler);
|
|
99
|
+
}
|
|
100
|
+
async connect(params) {
|
|
101
|
+
const { data: chainId } = await this.walletProvider.getChainId();
|
|
102
|
+
if (!isValidChain(this.options?.environment, chainId)) {
|
|
103
|
+
throw new Error(`Wallet environment mismatch: expected "${this.options?.environment}" chain, but received "${chainId}". Please verify the SDK configuration and the connected network.`);
|
|
104
|
+
}
|
|
105
|
+
const result = await this.walletProvider.connect(params);
|
|
106
|
+
if (result?.status === "success") {
|
|
107
|
+
this.listenerIds.clear();
|
|
108
|
+
for (const event of this.eventListeners.keys()) {
|
|
109
|
+
void this.registerListenerWithExtension(event);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return result;
|
|
113
|
+
}
|
|
114
|
+
disconnect() {
|
|
115
|
+
return this.walletProvider.disconnect();
|
|
116
|
+
}
|
|
117
|
+
signMessage(message) {
|
|
118
|
+
return this.walletProvider.signMessage(message);
|
|
119
|
+
}
|
|
120
|
+
signTransaction(transaction, options) {
|
|
121
|
+
return this.walletProvider.signTransaction(transaction, options);
|
|
122
|
+
}
|
|
123
|
+
getChainId() {
|
|
124
|
+
return this.walletProvider.getChainId();
|
|
125
|
+
}
|
|
126
|
+
getAccounts() {
|
|
127
|
+
return this.walletProvider.getAccounts();
|
|
128
|
+
}
|
|
129
|
+
getSelectedAccount() {
|
|
130
|
+
return this.walletProvider.getSelectedAccount();
|
|
131
|
+
}
|
|
132
|
+
getAvailableAuthorizations() {
|
|
133
|
+
return this.walletProvider.getAvailableAuthorizations();
|
|
134
|
+
}
|
|
135
|
+
on(event, callback) {
|
|
136
|
+
this.initWindowEventListener();
|
|
137
|
+
const cbs = this.eventListeners.get(event) ?? [];
|
|
138
|
+
cbs.push(callback);
|
|
139
|
+
this.eventListeners.set(event, cbs);
|
|
140
|
+
void this.registerListenerWithExtension(event);
|
|
141
|
+
this.ensureHeartbeat();
|
|
142
|
+
}
|
|
143
|
+
off(event, callback) {
|
|
144
|
+
const cbs = this.eventListeners.get(event);
|
|
145
|
+
if (!cbs)
|
|
146
|
+
return;
|
|
147
|
+
const idx = cbs.indexOf(callback);
|
|
148
|
+
if (idx >= 0)
|
|
149
|
+
cbs.splice(idx, 1);
|
|
150
|
+
if (cbs.length === 0) {
|
|
151
|
+
this.eventListeners.delete(event);
|
|
152
|
+
void this.deregisterListenerWithExtension(event);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
switchNetwork(chainId) {
|
|
156
|
+
return this.walletProvider.switchNetwork(chainId);
|
|
157
|
+
}
|
|
158
|
+
getNetwork() {
|
|
159
|
+
return this.walletProvider.getNetwork();
|
|
160
|
+
}
|
|
161
|
+
getNetworks() {
|
|
162
|
+
return this.walletProvider.getNetworks();
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Detach the window message listener and clear timers + maps. Safe to call
|
|
166
|
+
* multiple times. Does NOT deregister each listener on the BG — the BG
|
|
167
|
+
* GCs on tab close (verified via the S5(b) dedup work + tab-close cleanup
|
|
168
|
+
* in `EventsService.removeTabListeners`). Calling N RPCs at dispose-time
|
|
169
|
+
* would slow the page-unload path for no benefit.
|
|
170
|
+
*/
|
|
171
|
+
dispose() {
|
|
172
|
+
if (this.heartbeatTimer != null) {
|
|
173
|
+
clearInterval(this.heartbeatTimer);
|
|
174
|
+
this.heartbeatTimer = null;
|
|
175
|
+
}
|
|
176
|
+
if (this.messageHandler && typeof window !== "undefined") {
|
|
177
|
+
window.removeEventListener("message", this.messageHandler);
|
|
178
|
+
this.messageHandler = null;
|
|
179
|
+
}
|
|
180
|
+
this.eventListeners.clear();
|
|
181
|
+
this.listenerIds.clear();
|
|
182
|
+
}
|
|
183
|
+
async registerListenerWithExtension(event) {
|
|
184
|
+
if (!this.isExtensionAvailable())
|
|
185
|
+
return;
|
|
186
|
+
const id = this.listenerIds.get(event) ?? this.generateListenerId();
|
|
187
|
+
this.listenerIds.set(event, id);
|
|
188
|
+
try {
|
|
189
|
+
const result = this.walletProvider.addExtensionListener?.(event, id);
|
|
190
|
+
if (result && typeof result.catch === "function") {
|
|
191
|
+
result.catch(() => void 0);
|
|
192
|
+
}
|
|
193
|
+
} catch {
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
async deregisterListenerWithExtension(event) {
|
|
197
|
+
if (!this.isExtensionAvailable())
|
|
198
|
+
return;
|
|
199
|
+
const id = this.listenerIds.get(event);
|
|
200
|
+
if (!id)
|
|
201
|
+
return;
|
|
202
|
+
this.listenerIds.delete(event);
|
|
203
|
+
try {
|
|
204
|
+
const result = this.walletProvider.removeExtensionListener?.(event, id);
|
|
205
|
+
if (result && typeof result.catch === "function") {
|
|
206
|
+
result.catch(() => void 0);
|
|
207
|
+
}
|
|
208
|
+
} catch {
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
ensureHeartbeat() {
|
|
212
|
+
if (this.heartbeatTimer != null || typeof window === "undefined")
|
|
213
|
+
return;
|
|
214
|
+
this.heartbeatTimer = setInterval(() => this.heartbeatTick(), HEARTBEAT_INTERVAL_MS);
|
|
215
|
+
}
|
|
216
|
+
heartbeatTick() {
|
|
217
|
+
if (!this.isExtensionAvailable())
|
|
218
|
+
return;
|
|
219
|
+
let hasAny = false;
|
|
220
|
+
for (const cbs of this.eventListeners.values()) {
|
|
221
|
+
if (cbs.length > 0) {
|
|
222
|
+
hasAny = true;
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (!hasAny)
|
|
227
|
+
return;
|
|
228
|
+
for (const event of this.eventListeners.keys()) {
|
|
229
|
+
void this.registerListenerWithExtension(event);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
isExtensionAvailable() {
|
|
233
|
+
return typeof window !== "undefined" && !!window.ultra;
|
|
234
|
+
}
|
|
235
|
+
generateListenerId() {
|
|
236
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
237
|
+
return crypto.randomUUID();
|
|
238
|
+
}
|
|
239
|
+
return Math.random().toString(36).slice(2) + Date.now().toString(36);
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
// dist/libs/wallet-sdk/src/lib/common/client-messenger.js
|
|
244
|
+
import { JSONRPCClient } from "json-rpc-2.0";
|
|
245
|
+
|
|
246
|
+
// dist/libs/wallet-sdk/src/lib/common/client-error.js
|
|
247
|
+
var ClientError = class extends Error {
|
|
248
|
+
constructor(code, data) {
|
|
249
|
+
super();
|
|
250
|
+
this.code = code;
|
|
251
|
+
this.data = data;
|
|
252
|
+
this.message = SDK_ERROR_MESSAGE[code];
|
|
253
|
+
this.name = this.constructor.name;
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
// dist/libs/wallet-sdk/src/lib/common/client-messenger.js
|
|
258
|
+
var ClientMessenger = class {
|
|
259
|
+
constructor(windowManager) {
|
|
260
|
+
this.pendingRequest = false;
|
|
261
|
+
this.windowManager = windowManager;
|
|
262
|
+
this.initializeRpcClient();
|
|
263
|
+
this.setupMessageListener();
|
|
264
|
+
}
|
|
265
|
+
initializeRpcClient() {
|
|
266
|
+
this.rpcClient = new JSONRPCClient((request) => {
|
|
267
|
+
const walletWindow = this.windowManager.getWalletWindow();
|
|
268
|
+
if (!walletWindow) {
|
|
269
|
+
return Promise.reject(new ClientError(SdkErrorCode.WALLET_WINDOW_UNAVAILABLE));
|
|
270
|
+
}
|
|
271
|
+
walletWindow.postMessage(request, this.windowManager.walletUrl);
|
|
272
|
+
return Promise.resolve();
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
setupMessageListener() {
|
|
276
|
+
window.addEventListener("message", (event) => {
|
|
277
|
+
if (event.origin === this.windowManager.walletUrl && event.data?.jsonrpc === "2.0") {
|
|
278
|
+
this.rpcClient.receive(event.data);
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
async sendRequest(requestMethod, requestParams) {
|
|
283
|
+
if (this.pendingRequest && !this.isWalletWindowClosed()) {
|
|
284
|
+
throw this.createErrorResponse(SdkErrorCode.REQUESTED_RESOURCE_NOT_AVAILABLE);
|
|
285
|
+
}
|
|
286
|
+
this.pendingRequest = true;
|
|
287
|
+
try {
|
|
288
|
+
this.windowManager.openOrReuseWallet();
|
|
289
|
+
const walletWindow = this.ensureWalletWindow();
|
|
290
|
+
return await this.executeRequest(walletWindow, requestMethod, requestParams);
|
|
291
|
+
} finally {
|
|
292
|
+
this.pendingRequest = false;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
isWalletWindowClosed() {
|
|
296
|
+
return this.windowManager.getWalletWindow()?.closed === true;
|
|
297
|
+
}
|
|
298
|
+
ensureWalletWindow() {
|
|
299
|
+
const walletWindow = this.windowManager.getWalletWindow();
|
|
300
|
+
if (!walletWindow) {
|
|
301
|
+
throw this.createErrorResponse(SdkErrorCode.WALLET_WINDOW_UNAVAILABLE);
|
|
302
|
+
}
|
|
303
|
+
return walletWindow;
|
|
304
|
+
}
|
|
305
|
+
async executeRequest(walletWindow, requestMethod, requestParams) {
|
|
306
|
+
await this.waitForWalletReady(walletWindow);
|
|
307
|
+
return this.processRpcRequest(walletWindow, requestMethod, requestParams);
|
|
308
|
+
}
|
|
309
|
+
async waitForWalletReady(walletWindow) {
|
|
310
|
+
return this.withWindowMonitoring(walletWindow, () => {
|
|
311
|
+
return new Promise((resolve, reject) => {
|
|
312
|
+
let isResolved = false;
|
|
313
|
+
let timeoutId;
|
|
314
|
+
const cleanup = () => {
|
|
315
|
+
if (isResolved)
|
|
316
|
+
return;
|
|
317
|
+
isResolved = true;
|
|
318
|
+
clearTimeout(timeoutId);
|
|
319
|
+
window.removeEventListener("message", handleWalletHandshake);
|
|
320
|
+
};
|
|
321
|
+
const handleWalletHandshake = (event) => {
|
|
322
|
+
if (!this.isValidReadyMessage(event))
|
|
323
|
+
return;
|
|
324
|
+
cleanup();
|
|
325
|
+
resolve();
|
|
326
|
+
};
|
|
327
|
+
const handleTimeout = () => {
|
|
328
|
+
cleanup();
|
|
329
|
+
walletWindow.close();
|
|
330
|
+
reject(this.createErrorResponse(SdkErrorCode.WALLET_HANDSHAKE_TIMEOUT));
|
|
331
|
+
};
|
|
332
|
+
window.addEventListener("message", handleWalletHandshake);
|
|
333
|
+
timeoutId = setTimeout(handleTimeout, ultra_wallet_sdk_config_default.handshakeTimeout);
|
|
334
|
+
});
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
async processRpcRequest(walletWindow, requestMethod, requestParams) {
|
|
338
|
+
return this.withWindowMonitoring(walletWindow, async () => {
|
|
339
|
+
let result;
|
|
340
|
+
try {
|
|
341
|
+
result = await this.rpcClient.request(requestMethod, requestParams);
|
|
342
|
+
} catch (error) {
|
|
343
|
+
const clientError = new ClientError(SdkErrorCode.UNKNOWN_ERROR, error);
|
|
344
|
+
throw {
|
|
345
|
+
status: ResponseStatus.ERROR,
|
|
346
|
+
...clientError
|
|
347
|
+
};
|
|
348
|
+
} finally {
|
|
349
|
+
if (result?.status === ResponseStatus.SUCCESS) {
|
|
350
|
+
return result;
|
|
351
|
+
} else {
|
|
352
|
+
throw result;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
async withWindowMonitoring(walletWindow, operation) {
|
|
358
|
+
return new Promise((resolve, reject) => {
|
|
359
|
+
const intervalId = setInterval(() => {
|
|
360
|
+
if (walletWindow.closed) {
|
|
361
|
+
clearInterval(intervalId);
|
|
362
|
+
reject(this.createErrorResponse(SdkErrorCode.USER_REJECTED_REQUEST));
|
|
363
|
+
}
|
|
364
|
+
}, ultra_wallet_sdk_config_default.checkWindowInterval);
|
|
365
|
+
operation().then((result) => {
|
|
366
|
+
clearInterval(intervalId);
|
|
367
|
+
resolve(result);
|
|
368
|
+
}).catch((error) => {
|
|
369
|
+
clearInterval(intervalId);
|
|
370
|
+
reject(error);
|
|
371
|
+
});
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
isValidReadyMessage(event) {
|
|
375
|
+
if (event.origin !== this.windowManager.walletUrl)
|
|
376
|
+
return false;
|
|
377
|
+
const msg = event.data;
|
|
378
|
+
return msg?.jsonrpc === "2.0" && msg.method === "ready";
|
|
379
|
+
}
|
|
380
|
+
createErrorResponse(errorCode) {
|
|
381
|
+
const { code, message } = new ClientError(errorCode);
|
|
382
|
+
return { status: ResponseStatus.ERROR, code, message, data: null };
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
// dist/libs/wallet-sdk/src/lib/common/window-manager.js
|
|
387
|
+
var WindowManager = class {
|
|
388
|
+
constructor(walletUrl) {
|
|
389
|
+
this.walletWindow = null;
|
|
390
|
+
this.currentWindow = window;
|
|
391
|
+
this.walletUrl = walletUrl;
|
|
392
|
+
}
|
|
393
|
+
openOrReuseWallet() {
|
|
394
|
+
if (this.walletWindow == null || this.walletWindow.closed) {
|
|
395
|
+
const height = ultra_wallet_sdk_config_default.height;
|
|
396
|
+
const width = ultra_wallet_sdk_config_default.width;
|
|
397
|
+
const top = this.currentWindow.top;
|
|
398
|
+
const left = this.currentWindow.screenLeft + this.currentWindow.innerWidth - width;
|
|
399
|
+
this.walletWindow = window.open(this.walletUrl, "_blank", `width=${width},height=${height},top=${top},left=${left},resizable=0`);
|
|
400
|
+
} else {
|
|
401
|
+
this.walletWindow.focus();
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
// Provides a reference to the wallet window
|
|
405
|
+
getWalletWindow() {
|
|
406
|
+
return this.walletWindow;
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
// dist/libs/wallet-sdk/src/lib/providers/web-provider/web.provider.js
|
|
411
|
+
var WebProvider = class {
|
|
412
|
+
constructor(options) {
|
|
413
|
+
this.options = options;
|
|
414
|
+
this.windowManager = new WindowManager(this.resolveWalletUrl());
|
|
415
|
+
this.clientMessenger = new ClientMessenger(this.windowManager);
|
|
416
|
+
}
|
|
417
|
+
connect(options) {
|
|
418
|
+
return this.clientMessenger.sendRequest("connect", { options });
|
|
419
|
+
}
|
|
420
|
+
disconnect() {
|
|
421
|
+
return this.clientMessenger.sendRequest("disconnect", {});
|
|
422
|
+
}
|
|
423
|
+
signMessage(message) {
|
|
424
|
+
return this.clientMessenger.sendRequest("signMessage", { message });
|
|
425
|
+
}
|
|
426
|
+
signTransaction(transaction, options) {
|
|
427
|
+
return this.clientMessenger.sendRequest("signTransaction", { transaction, options });
|
|
428
|
+
}
|
|
429
|
+
async getChainId() {
|
|
430
|
+
const environment = this.options?.environment || "mainnet";
|
|
431
|
+
switch (environment) {
|
|
432
|
+
case "mainnet":
|
|
433
|
+
const mainnetChainId = ultra_wallet_sdk_config_default.networkInfo.mainnet.chainId;
|
|
434
|
+
return {
|
|
435
|
+
status: ResponseStatus.SUCCESS,
|
|
436
|
+
data: mainnetChainId
|
|
437
|
+
};
|
|
438
|
+
case "testnet":
|
|
439
|
+
const testnetChainId = ultra_wallet_sdk_config_default.networkInfo.testnet.chainId;
|
|
440
|
+
return {
|
|
441
|
+
status: ResponseStatus.SUCCESS,
|
|
442
|
+
data: testnetChainId
|
|
443
|
+
};
|
|
444
|
+
default:
|
|
445
|
+
return this.clientMessenger.sendRequest("getChainId", {});
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
getAccounts() {
|
|
449
|
+
return this.clientMessenger.sendRequest("getAccounts", {});
|
|
450
|
+
}
|
|
451
|
+
getSelectedAccount() {
|
|
452
|
+
return this.clientMessenger.sendRequest("getSelectedAccount", {});
|
|
453
|
+
}
|
|
454
|
+
getAvailableAuthorizations() {
|
|
455
|
+
return this.clientMessenger.sendRequest("getAvailableAuthorizations", {});
|
|
456
|
+
}
|
|
457
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
458
|
+
on(_event, _callback) {
|
|
459
|
+
}
|
|
460
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
461
|
+
off(_event, _callback) {
|
|
462
|
+
}
|
|
463
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
464
|
+
switchNetwork(_chainId) {
|
|
465
|
+
throw new Error("Not supported in web provider");
|
|
466
|
+
}
|
|
467
|
+
getNetwork() {
|
|
468
|
+
throw new Error("Not supported in web provider");
|
|
469
|
+
}
|
|
470
|
+
getNetworks() {
|
|
471
|
+
throw new Error("Not supported in web provider");
|
|
472
|
+
}
|
|
473
|
+
dispose() {
|
|
474
|
+
}
|
|
475
|
+
resolveWalletUrl() {
|
|
476
|
+
const env = ultra_wallet_sdk_config_default.walletUrls[this.options?.environment || "mainnet"];
|
|
477
|
+
return env || this.options.environment;
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
// dist/libs/wallet-sdk/src/lib/utils/detection.js
|
|
482
|
+
function isExtensionAvailable() {
|
|
483
|
+
return typeof window !== "undefined" && "ultra" in window;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// dist/libs/wallet-sdk/src/lib/ultra-wallet-sdk.js
|
|
487
|
+
var UltraWalletSDK = class {
|
|
488
|
+
/**
|
|
489
|
+
* Constructs an UltraWalletClient instance.
|
|
490
|
+
* If the Ultra Wallet Extension is available (window.ultra), it will be used automatically.
|
|
491
|
+
* If the Extension is not available, the Web Wallet provider will be initialized using the given network options.
|
|
492
|
+
*
|
|
493
|
+
* @param {UltraWalletSdkOptions} [options] - Configuration options for the Web Wallet fallback (environment or custom URL).
|
|
494
|
+
*/
|
|
495
|
+
constructor(options) {
|
|
496
|
+
this.options = options;
|
|
497
|
+
this.provider = this.resolveWalletProvider();
|
|
498
|
+
}
|
|
499
|
+
connect(params) {
|
|
500
|
+
return this.provider.connect(params);
|
|
501
|
+
}
|
|
502
|
+
disconnect() {
|
|
503
|
+
return this.provider.disconnect();
|
|
504
|
+
}
|
|
505
|
+
signMessage(message) {
|
|
506
|
+
return this.provider.signMessage(message);
|
|
507
|
+
}
|
|
508
|
+
signTransaction(transaction, options) {
|
|
509
|
+
return this.provider.signTransaction(transaction, options);
|
|
510
|
+
}
|
|
511
|
+
getChainId() {
|
|
512
|
+
return this.provider.getChainId();
|
|
513
|
+
}
|
|
514
|
+
getAccounts() {
|
|
515
|
+
return this.provider.getAccounts();
|
|
516
|
+
}
|
|
517
|
+
getSelectedAccount() {
|
|
518
|
+
return this.provider.getSelectedAccount();
|
|
519
|
+
}
|
|
520
|
+
getAvailableAuthorizations() {
|
|
521
|
+
return this.provider.getAvailableAuthorizations();
|
|
522
|
+
}
|
|
523
|
+
on(event, callback) {
|
|
524
|
+
this.provider.on(event, callback);
|
|
525
|
+
}
|
|
526
|
+
off(event, callback) {
|
|
527
|
+
this.provider.off(event, callback);
|
|
528
|
+
}
|
|
529
|
+
switchNetwork(chainId) {
|
|
530
|
+
return this.provider.switchNetwork(chainId);
|
|
531
|
+
}
|
|
532
|
+
getNetwork() {
|
|
533
|
+
return this.provider.getNetwork();
|
|
534
|
+
}
|
|
535
|
+
getNetworks() {
|
|
536
|
+
return this.provider.getNetworks();
|
|
537
|
+
}
|
|
538
|
+
dispose() {
|
|
539
|
+
this.provider.dispose();
|
|
540
|
+
}
|
|
541
|
+
resolveWalletProvider() {
|
|
542
|
+
const requestedProvider = this.options?.provider;
|
|
543
|
+
if (requestedProvider === "extension") {
|
|
544
|
+
return new ExtensionProvider(this.options);
|
|
545
|
+
}
|
|
546
|
+
if (requestedProvider === "web") {
|
|
547
|
+
return new WebProvider(this.options);
|
|
548
|
+
}
|
|
549
|
+
const extensionAvailable = isExtensionAvailable();
|
|
550
|
+
return extensionAvailable ? new ExtensionProvider(this.options) : new WebProvider(this.options);
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
export {
|
|
554
|
+
ResponseStatus,
|
|
555
|
+
SDK_ERROR_MESSAGE,
|
|
556
|
+
SdkErrorCode,
|
|
557
|
+
UltraWalletSDK
|
|
558
|
+
};
|
|
559
|
+
//# sourceMappingURL=index.mjs.map
|