@shadow-corp/nearconnect 1.0.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/README.md +546 -0
- package/build/InjectedWallet.d.ts +22 -0
- package/build/InjectedWallet.js +58 -0
- package/build/InjectedWallet.js.map +1 -0
- package/build/NearConnector.d.ts +151 -0
- package/build/NearConnector.js +536 -0
- package/build/NearConnector.js.map +1 -0
- package/build/ParentFrameWallet.d.ts +22 -0
- package/build/ParentFrameWallet.js +66 -0
- package/build/ParentFrameWallet.js.map +1 -0
- package/build/SandboxedWallet/code.d.ts +7 -0
- package/build/SandboxedWallet/code.js +324 -0
- package/build/SandboxedWallet/code.js.map +1 -0
- package/build/SandboxedWallet/executor.d.ts +23 -0
- package/build/SandboxedWallet/executor.js +338 -0
- package/build/SandboxedWallet/executor.js.map +1 -0
- package/build/SandboxedWallet/iframe.d.ts +18 -0
- package/build/SandboxedWallet/iframe.js +78 -0
- package/build/SandboxedWallet/iframe.js.map +1 -0
- package/build/SandboxedWallet/index.d.ts +24 -0
- package/build/SandboxedWallet/index.js +54 -0
- package/build/SandboxedWallet/index.js.map +1 -0
- package/build/actions/index.d.ts +3 -0
- package/build/actions/index.js +105 -0
- package/build/actions/index.js.map +1 -0
- package/build/actions/types.d.ts +76 -0
- package/build/actions/types.js +3 -0
- package/build/actions/types.js.map +1 -0
- package/build/connection/health.d.ts +213 -0
- package/build/connection/health.js +391 -0
- package/build/connection/health.js.map +1 -0
- package/build/connection/index.d.ts +4 -0
- package/build/connection/index.js +48 -0
- package/build/connection/index.js.map +1 -0
- package/build/connection/reconnect.d.ts +261 -0
- package/build/connection/reconnect.js +454 -0
- package/build/connection/reconnect.js.map +1 -0
- package/build/connection/retry.d.ts +187 -0
- package/build/connection/retry.js +427 -0
- package/build/connection/retry.js.map +1 -0
- package/build/connection/state.d.ts +222 -0
- package/build/connection/state.js +431 -0
- package/build/connection/state.js.map +1 -0
- package/build/errors.d.ts +177 -0
- package/build/errors.js +546 -0
- package/build/errors.js.map +1 -0
- package/build/hardware/errors.d.ts +36 -0
- package/build/hardware/errors.js +127 -0
- package/build/hardware/errors.js.map +1 -0
- package/build/hardware/index.d.ts +7 -0
- package/build/hardware/index.js +39 -0
- package/build/hardware/index.js.map +1 -0
- package/build/hardware/near-app.d.ts +95 -0
- package/build/hardware/near-app.js +291 -0
- package/build/hardware/near-app.js.map +1 -0
- package/build/hardware/transport.d.ts +94 -0
- package/build/hardware/transport.js +267 -0
- package/build/hardware/transport.js.map +1 -0
- package/build/hardware/types.d.ts +98 -0
- package/build/hardware/types.js +72 -0
- package/build/hardware/types.js.map +1 -0
- package/build/helpers/analytics.d.ts +191 -0
- package/build/helpers/analytics.js +304 -0
- package/build/helpers/analytics.js.map +1 -0
- package/build/helpers/base58.d.ts +6 -0
- package/build/helpers/base58.js +47 -0
- package/build/helpers/base58.js.map +1 -0
- package/build/helpers/events.d.ts +42 -0
- package/build/helpers/events.js +68 -0
- package/build/helpers/events.js.map +1 -0
- package/build/helpers/html.d.ts +8 -0
- package/build/helpers/html.js +30 -0
- package/build/helpers/html.js.map +1 -0
- package/build/helpers/indexdb.d.ts +14 -0
- package/build/helpers/indexdb.js +166 -0
- package/build/helpers/indexdb.js.map +1 -0
- package/build/helpers/manifest.d.ts +147 -0
- package/build/helpers/manifest.js +329 -0
- package/build/helpers/manifest.js.map +1 -0
- package/build/helpers/queue.d.ts +11 -0
- package/build/helpers/queue.js +48 -0
- package/build/helpers/queue.js.map +1 -0
- package/build/helpers/session.d.ts +119 -0
- package/build/helpers/session.js +289 -0
- package/build/helpers/session.js.map +1 -0
- package/build/helpers/simulation.d.ts +128 -0
- package/build/helpers/simulation.js +441 -0
- package/build/helpers/simulation.js.map +1 -0
- package/build/helpers/storage.d.ts +58 -0
- package/build/helpers/storage.js +190 -0
- package/build/helpers/storage.js.map +1 -0
- package/build/helpers/trust.d.ts +157 -0
- package/build/helpers/trust.js +340 -0
- package/build/helpers/trust.js.map +1 -0
- package/build/helpers/url.d.ts +1 -0
- package/build/helpers/url.js +13 -0
- package/build/helpers/url.js.map +1 -0
- package/build/helpers/uuid.d.ts +1 -0
- package/build/helpers/uuid.js +14 -0
- package/build/helpers/uuid.js.map +1 -0
- package/build/index.d.ts +21 -0
- package/build/index.js +167 -0
- package/build/index.js.map +1 -0
- package/build/popups/IframeWalletPopup.d.ts +16 -0
- package/build/popups/IframeWalletPopup.js +38 -0
- package/build/popups/IframeWalletPopup.js.map +1 -0
- package/build/popups/NearWalletsPopup.d.ts +25 -0
- package/build/popups/NearWalletsPopup.js +153 -0
- package/build/popups/NearWalletsPopup.js.map +1 -0
- package/build/popups/Popup.d.ts +22 -0
- package/build/popups/Popup.js +94 -0
- package/build/popups/Popup.js.map +1 -0
- package/build/popups/styles.d.ts +1 -0
- package/build/popups/styles.js +257 -0
- package/build/popups/styles.js.map +1 -0
- package/build/security/audit-log.d.ts +123 -0
- package/build/security/audit-log.js +268 -0
- package/build/security/audit-log.js.map +1 -0
- package/build/security/csp.d.ts +68 -0
- package/build/security/csp.js +328 -0
- package/build/security/csp.js.map +1 -0
- package/build/security/index.d.ts +10 -0
- package/build/security/index.js +42 -0
- package/build/security/index.js.map +1 -0
- package/build/security/origin-guard.d.ts +90 -0
- package/build/security/origin-guard.js +244 -0
- package/build/security/origin-guard.js.map +1 -0
- package/build/security/rate-limiter.d.ts +84 -0
- package/build/security/rate-limiter.js +212 -0
- package/build/security/rate-limiter.js.map +1 -0
- package/build/security/secure-storage.d.ts +77 -0
- package/build/security/secure-storage.js +242 -0
- package/build/security/secure-storage.js.map +1 -0
- package/build/security/transaction-guard.d.ts +71 -0
- package/build/security/transaction-guard.js +239 -0
- package/build/security/transaction-guard.js.map +1 -0
- package/build/types.d.ts +508 -0
- package/build/types.js +3 -0
- package/build/types.js.map +1 -0
- package/build/ui/AccountSwitcherModal.d.ts +53 -0
- package/build/ui/AccountSwitcherModal.js +239 -0
- package/build/ui/AccountSwitcherModal.js.map +1 -0
- package/build/ui/Modal.d.ts +84 -0
- package/build/ui/Modal.js +278 -0
- package/build/ui/Modal.js.map +1 -0
- package/build/ui/TransactionModal.d.ts +84 -0
- package/build/ui/TransactionModal.js +406 -0
- package/build/ui/TransactionModal.js.map +1 -0
- package/build/ui/WalletSelectorModal.d.ts +97 -0
- package/build/ui/WalletSelectorModal.js +481 -0
- package/build/ui/WalletSelectorModal.js.map +1 -0
- package/build/ui/icons.d.ts +19 -0
- package/build/ui/icons.js +65 -0
- package/build/ui/icons.js.map +1 -0
- package/build/ui/index.d.ts +10 -0
- package/build/ui/index.js +31 -0
- package/build/ui/index.js.map +1 -0
- package/build/ui/styles.d.ts +5 -0
- package/build/ui/styles.js +973 -0
- package/build/ui/styles.js.map +1 -0
- package/build/ui/theme.d.ts +133 -0
- package/build/ui/theme.js +204 -0
- package/build/ui/theme.js.map +1 -0
- package/build/wallets/external/index.d.ts +4 -0
- package/build/wallets/external/index.js +9 -0
- package/build/wallets/external/index.js.map +1 -0
- package/build/wallets/external/manager.d.ts +152 -0
- package/build/wallets/external/manager.js +586 -0
- package/build/wallets/external/manager.js.map +1 -0
- package/build/wallets/privileged/index.d.ts +5 -0
- package/build/wallets/privileged/index.js +12 -0
- package/build/wallets/privileged/index.js.map +1 -0
- package/build/wallets/privileged/ledger.d.ts +132 -0
- package/build/wallets/privileged/ledger.js +563 -0
- package/build/wallets/privileged/ledger.js.map +1 -0
- package/build/wallets/privileged/manager.d.ts +54 -0
- package/build/wallets/privileged/manager.js +174 -0
- package/build/wallets/privileged/manager.js.map +1 -0
- package/package.json +33 -0
package/README.md
ADDED
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
# NearConnect
|
|
2
|
+
|
|
3
|
+
A comprehensive NEAR Protocol wallet connector library with a four-tier architecture supporting web wallets, browser extensions, hardware wallets, and mobile wallets.
|
|
4
|
+
|
|
5
|
+
> **Fork Notice:** This is an enhanced fork of [azbang/near-connect](https://github.com/azbang/near-connect) (commit c72689d). See [Enhancements](#enhancements) for details on what's been added.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @shadowcorp/near-connect
|
|
11
|
+
# or
|
|
12
|
+
yarn add @shadowcorp/near-connect
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Four-Tier Wallet Architecture
|
|
16
|
+
|
|
17
|
+

|
|
18
|
+
|
|
19
|
+
### Why Four Tiers?
|
|
20
|
+
|
|
21
|
+
The original NEAR wallet connector relied heavily on iframe sandboxing for security. While sandboxes provide isolation, they have significant limitations:
|
|
22
|
+
|
|
23
|
+
The four-tier architecture addresses these limitations by treating each wallet type according to its actual trust level and capabilities:
|
|
24
|
+
|
|
25
|
+
| Tier | Type | Trust Level | Security Model |
|
|
26
|
+
|------|------|-------------|----------------|
|
|
27
|
+
| 1 | Sandboxed (Web) | Untrusted | Iframe isolation + origin verification |
|
|
28
|
+
| 2 | Injected (Extensions) | Semi-trusted | Browser extension sandbox + permission model |
|
|
29
|
+
| 3 | Privileged (Hardware) | Trusted | Physical device confirmation required |
|
|
30
|
+
| 4 | External (Mobile) | Verified | Cryptographic signatures + callback verification |
|
|
31
|
+
|
|
32
|
+
This architecture, combined with the security layers below, provides defense-in-depth rather than relying on any single security mechanism.
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { NearConnector } from "@shadowcorp/near-connect";
|
|
38
|
+
|
|
39
|
+
const connector = new NearConnector({
|
|
40
|
+
network: "mainnet",
|
|
41
|
+
// Optional: hardware wallet config
|
|
42
|
+
hardware: {
|
|
43
|
+
ledger: { enabled: true }
|
|
44
|
+
},
|
|
45
|
+
// Optional: WalletConnect for mobile
|
|
46
|
+
external: {
|
|
47
|
+
walletConnect: { projectId: "your-project-id" }
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Listen for events
|
|
52
|
+
connector.on("wallet:signIn", async ({ accounts }) => {
|
|
53
|
+
console.log("Connected:", accounts[0].accountId);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
connector.on("wallet:signOut", () => {
|
|
57
|
+
console.log("Disconnected");
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Get available wallets
|
|
61
|
+
const wallets = connector.getWallets();
|
|
62
|
+
|
|
63
|
+
// Connect to a wallet
|
|
64
|
+
await connector.connect("ledger");
|
|
65
|
+
|
|
66
|
+
// Sign and send transaction
|
|
67
|
+
const result = await connector.signAndSendTransaction({
|
|
68
|
+
receiverId: "example.near",
|
|
69
|
+
actions: [{ type: "Transfer", params: { deposit: "1000000000000000000000000" } }]
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Hardware Wallet Support (Ledger)
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import { LedgerWallet, createLedgerWallet } from "@shadowcorp/near-connect";
|
|
77
|
+
|
|
78
|
+
// Using the factory function
|
|
79
|
+
const ledger = createLedgerWallet({
|
|
80
|
+
network: "mainnet",
|
|
81
|
+
rpcUrl: "https://rpc.mainnet.near.org"
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Listen for hardware events
|
|
85
|
+
ledger.on("waiting", ({ action }) => {
|
|
86
|
+
console.log(`Please ${action} on your Ledger device...`);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
ledger.on("confirm", ({ action }) => {
|
|
90
|
+
console.log(`Action confirmed: ${action}`);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Connect and get accounts
|
|
94
|
+
await ledger.connect();
|
|
95
|
+
const accounts = ledger.getAccounts();
|
|
96
|
+
|
|
97
|
+
// Sign transaction
|
|
98
|
+
const result = await ledger.signAndSendTransaction({
|
|
99
|
+
receiverId: "example.near",
|
|
100
|
+
actions: [{ type: "Transfer", params: { deposit: "1000000000000000000000000" } }]
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Mobile Wallet Support
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
import { ExternalWalletManager } from "@shadowcorp/near-connect";
|
|
108
|
+
|
|
109
|
+
const external = new ExternalWalletManager({
|
|
110
|
+
network: "mainnet",
|
|
111
|
+
appName: "My dApp",
|
|
112
|
+
appUrl: "https://mydapp.com",
|
|
113
|
+
callbackUrl: "https://mydapp.com/callback"
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Connect via deep link (Meteor, HERE wallet)
|
|
117
|
+
await external.connect("meteor-mobile");
|
|
118
|
+
|
|
119
|
+
// Or via WalletConnect
|
|
120
|
+
await external.connect("walletconnect");
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Pre-built UI Components
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
import {
|
|
127
|
+
WalletSelectorModal,
|
|
128
|
+
TransactionModal,
|
|
129
|
+
AccountSwitcherModal,
|
|
130
|
+
darkTheme,
|
|
131
|
+
lightTheme
|
|
132
|
+
} from "@shadowcorp/near-connect";
|
|
133
|
+
|
|
134
|
+
// Wallet selection modal
|
|
135
|
+
const selectorModal = new WalletSelectorModal({
|
|
136
|
+
wallets: connector.getWallets(),
|
|
137
|
+
theme: darkTheme,
|
|
138
|
+
onSelect: async (walletId) => {
|
|
139
|
+
await connector.connect(walletId);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
selectorModal.open();
|
|
144
|
+
|
|
145
|
+
// Transaction confirmation modal
|
|
146
|
+
const txModal = new TransactionModal({
|
|
147
|
+
transaction: { receiverId: "example.near", actions: [...] },
|
|
148
|
+
theme: darkTheme,
|
|
149
|
+
onConfirm: async () => {
|
|
150
|
+
await connector.signAndSendTransaction(tx);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Session Persistence
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
import {
|
|
159
|
+
SessionManager,
|
|
160
|
+
LocalStorage,
|
|
161
|
+
EncryptedStorage
|
|
162
|
+
} from "@shadowcorp/near-connect";
|
|
163
|
+
|
|
164
|
+
// Basic persistence
|
|
165
|
+
const session = new SessionManager({
|
|
166
|
+
storage: new LocalStorage(),
|
|
167
|
+
key: "near-session"
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// Encrypted persistence
|
|
171
|
+
const secureSession = new SessionManager({
|
|
172
|
+
storage: new EncryptedStorage("your-encryption-key"),
|
|
173
|
+
key: "near-session",
|
|
174
|
+
expiresIn: 24 * 60 * 60 * 1000 // 24 hours
|
|
175
|
+
});
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Connection Reliability
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
import {
|
|
182
|
+
withRetry,
|
|
183
|
+
CircuitBreaker,
|
|
184
|
+
HealthMonitor,
|
|
185
|
+
ConnectionStateMachine
|
|
186
|
+
} from "@shadowcorp/near-connect";
|
|
187
|
+
|
|
188
|
+
// Retry with exponential backoff
|
|
189
|
+
const result = await withRetry(
|
|
190
|
+
() => connector.signAndSendTransaction(tx),
|
|
191
|
+
{ maxRetries: 3, baseDelay: 1000 }
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
// Circuit breaker for failing connections
|
|
195
|
+
const breaker = new CircuitBreaker({
|
|
196
|
+
failureThreshold: 5,
|
|
197
|
+
resetTimeout: 30000
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// Health monitoring
|
|
201
|
+
const health = new HealthMonitor({
|
|
202
|
+
checkInterval: 10000,
|
|
203
|
+
healthCheck: () => connector.isConnected()
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
health.on("unhealthy", () => {
|
|
207
|
+
console.log("Connection lost, attempting reconnect...");
|
|
208
|
+
});
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Transaction Simulation
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
import { TransactionSimulator, quickGasEstimate } from "@shadowcorp/near-connect";
|
|
215
|
+
|
|
216
|
+
// Quick gas estimate
|
|
217
|
+
const gas = await quickGasEstimate(transaction, "mainnet");
|
|
218
|
+
|
|
219
|
+
// Full simulation
|
|
220
|
+
const simulator = new TransactionSimulator({ network: "mainnet" });
|
|
221
|
+
const result = await simulator.simulate(transaction);
|
|
222
|
+
|
|
223
|
+
if (result.warnings.length > 0) {
|
|
224
|
+
console.log("Warnings:", result.warnings);
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Trust Scoring
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
import { TrustScorer, quickTrustCheck } from "@shadowcorp/near-connect";
|
|
232
|
+
|
|
233
|
+
// Quick trust check
|
|
234
|
+
const trust = await quickTrustCheck("meteor-wallet");
|
|
235
|
+
console.log(`Trust level: ${trust.level}`); // "high", "medium", "low", "unknown"
|
|
236
|
+
|
|
237
|
+
// Detailed scoring
|
|
238
|
+
const scorer = new TrustScorer();
|
|
239
|
+
const score = await scorer.score("meteor-wallet");
|
|
240
|
+
console.log(`Score: ${score.overall}/100`);
|
|
241
|
+
console.log(`Signals:`, score.signals);
|
|
242
|
+
console.log(`Warnings:`, score.warnings);
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Analytics
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
import {
|
|
249
|
+
Analytics,
|
|
250
|
+
ConsoleAnalyticsAdapter,
|
|
251
|
+
BatchingAnalyticsAdapter
|
|
252
|
+
} from "@shadowcorp/near-connect";
|
|
253
|
+
|
|
254
|
+
const analytics = new Analytics({
|
|
255
|
+
adapter: new BatchingAnalyticsAdapter({
|
|
256
|
+
batchSize: 10,
|
|
257
|
+
flushInterval: 5000,
|
|
258
|
+
onFlush: (events) => {
|
|
259
|
+
// Send to your analytics service
|
|
260
|
+
fetch("/api/analytics", { method: "POST", body: JSON.stringify(events) });
|
|
261
|
+
}
|
|
262
|
+
})
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
// Track events
|
|
266
|
+
analytics.track("wallet:connect", { walletId: "ledger" });
|
|
267
|
+
analytics.track("transaction:send", { amount: "1 NEAR" });
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## Security Layers
|
|
271
|
+
|
|
272
|
+
Since sandboxing alone isn't sufficient, NearConnect implements multiple security layers that work together to protect users:
|
|
273
|
+
|
|
274
|
+
### Transaction Guard
|
|
275
|
+
|
|
276
|
+
Analyzes transactions before signing to detect dangerous operations:
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
import { TransactionGuard, createDefaultTransactionGuard } from "@shadowcorp/near-connect";
|
|
280
|
+
|
|
281
|
+
const guard = createDefaultTransactionGuard();
|
|
282
|
+
|
|
283
|
+
// Analyze transaction risk
|
|
284
|
+
const risk = guard.analyzeRisk({
|
|
285
|
+
receiverId: "contract.near",
|
|
286
|
+
actions: [{ type: "FunctionCall", params: { methodName: "transfer", args: {} } }]
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
console.log(risk.level); // "low" | "medium" | "high" | "critical"
|
|
290
|
+
console.log(risk.reasons); // ["Large transfer: 500.00 NEAR"]
|
|
291
|
+
|
|
292
|
+
// Validate before signing
|
|
293
|
+
const result = guard.validate(transaction);
|
|
294
|
+
if (!result.valid) {
|
|
295
|
+
console.log("Blocked:", result.error);
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
**What it detects:**
|
|
300
|
+
- Dangerous methods (`add_full_access_key`, `delete_account`, `deploy_contract`)
|
|
301
|
+
- Large transfers (configurable threshold, default 100 NEAR)
|
|
302
|
+
- Known scam contracts
|
|
303
|
+
- Delete account actions
|
|
304
|
+
- Contract deployments
|
|
305
|
+
- Custom blocklists and allowlists
|
|
306
|
+
|
|
307
|
+
### Origin Guard
|
|
308
|
+
|
|
309
|
+
Validates message origins to prevent cross-site attacks:
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
import { OriginGuard, createSecureMessageHandler } from "@shadowcorp/near-connect";
|
|
313
|
+
|
|
314
|
+
const guard = new OriginGuard({
|
|
315
|
+
appOrigins: ["https://myapp.com"],
|
|
316
|
+
walletOrigins: {
|
|
317
|
+
"custom-wallet": ["https://custom.wallet"]
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// Check if origin is trusted
|
|
322
|
+
guard.isOriginTrusted("https://wallet.meteorwallet.app"); // true
|
|
323
|
+
guard.isOriginTrusted("https://evil.com"); // false
|
|
324
|
+
|
|
325
|
+
// Validate callback URLs
|
|
326
|
+
const result = guard.verifyCallbackUrl("https://myapp.com/callback");
|
|
327
|
+
if (!result.valid) {
|
|
328
|
+
console.log("Invalid callback:", result.reason);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Secure postMessage handler
|
|
332
|
+
const handler = createSecureMessageHandler({
|
|
333
|
+
trustedOrigins: ["https://wallet.meteorwallet.app"],
|
|
334
|
+
onMessage: (data, origin) => {
|
|
335
|
+
// Only called for verified origins
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
window.addEventListener("message", handler);
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Rate Limiter
|
|
342
|
+
|
|
343
|
+
Prevents abuse by limiting request frequency:
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
import { RateLimiter, connectLimiter, signLimiter } from "@shadowcorp/near-connect";
|
|
347
|
+
|
|
348
|
+
// Custom limiter
|
|
349
|
+
const limiter = new RateLimiter({
|
|
350
|
+
maxRequests: 10, // Max requests per window
|
|
351
|
+
windowMs: 60000, // 1 minute window
|
|
352
|
+
blockDurationMs: 300000 // Block for 5 minutes if exceeded
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
const result = limiter.check("user-action");
|
|
356
|
+
if (!result.allowed) {
|
|
357
|
+
console.log(`Rate limited. Retry in ${result.retryAfter}s`);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Pre-configured limiters
|
|
361
|
+
connectLimiter.check("wallet-connect"); // 5 per minute
|
|
362
|
+
signLimiter.check("sign-tx"); // 10 per minute
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### Audit Log
|
|
366
|
+
|
|
367
|
+
Tracks all wallet actions for investigation and compliance:
|
|
368
|
+
|
|
369
|
+
```typescript
|
|
370
|
+
import { AuditLog, createAuditLog } from "@shadowcorp/near-connect";
|
|
371
|
+
|
|
372
|
+
const auditLog = createAuditLog({
|
|
373
|
+
consoleLog: true, // Log security events to console
|
|
374
|
+
remoteEndpoint: "/api/audit", // Optional: send to server
|
|
375
|
+
persist: true // Persist to localStorage
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
// Log events
|
|
379
|
+
auditLog.log("wallet:connect", { walletId: "ledger", accountId: "alice.near" });
|
|
380
|
+
auditLog.log("tx:sign", { data: { receiverId: "bob.near" } });
|
|
381
|
+
auditLog.logSecurityWarning("Large transfer detected", { amount: "500 NEAR" });
|
|
382
|
+
|
|
383
|
+
// Query events
|
|
384
|
+
const securityEvents = auditLog.getSecurityEvents();
|
|
385
|
+
const recentTx = auditLog.getEvents({ type: ["tx:sign", "tx:broadcast"], limit: 10 });
|
|
386
|
+
|
|
387
|
+
// Export for analysis
|
|
388
|
+
const json = auditLog.export();
|
|
389
|
+
const csv = auditLog.exportCsv();
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
**Event types tracked:**
|
|
393
|
+
- `wallet:connect`, `wallet:disconnect`, `wallet:switch`
|
|
394
|
+
- `tx:sign`, `tx:broadcast`, `tx:blocked`, `tx:failed`
|
|
395
|
+
- `security:violation`, `security:warning`
|
|
396
|
+
- `rate:limited`
|
|
397
|
+
- `hardware:connect`, `hardware:disconnect`, `hardware:error`
|
|
398
|
+
|
|
399
|
+
### Secure Storage
|
|
400
|
+
|
|
401
|
+
AES-GCM encrypted localStorage for sensitive data:
|
|
402
|
+
|
|
403
|
+
```typescript
|
|
404
|
+
import { SecureStorage, createSecureStorage } from "@shadowcorp/near-connect";
|
|
405
|
+
|
|
406
|
+
// Create encrypted storage (browser only)
|
|
407
|
+
const storage = await createSecureStorage({
|
|
408
|
+
keyName: "my-app-key" // Stored in non-exportable CryptoKey
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
// Store sensitive data
|
|
412
|
+
await storage.set("session", JSON.stringify({ token: "..." }));
|
|
413
|
+
const data = await storage.get("session");
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### Content Security Policy
|
|
417
|
+
|
|
418
|
+
Helpers for configuring CSP headers:
|
|
419
|
+
|
|
420
|
+
```typescript
|
|
421
|
+
import {
|
|
422
|
+
generateCSP,
|
|
423
|
+
getRecommendedCSP,
|
|
424
|
+
runSecurityChecklist
|
|
425
|
+
} from "@shadowcorp/near-connect";
|
|
426
|
+
|
|
427
|
+
// Generate CSP header
|
|
428
|
+
const csp = generateCSP({
|
|
429
|
+
"default-src": ["'self'"],
|
|
430
|
+
"connect-src": ["'self'", "https://rpc.mainnet.near.org"],
|
|
431
|
+
"frame-src": ["https://wallet.meteorwallet.app"]
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
// Get recommended CSP for NEAR apps
|
|
435
|
+
const recommended = getRecommendedCSP();
|
|
436
|
+
|
|
437
|
+
// Run security checklist
|
|
438
|
+
const checks = runSecurityChecklist();
|
|
439
|
+
checks.forEach(check => {
|
|
440
|
+
console.log(`${check.passed ? "✓" : "✗"} ${check.name}: ${check.message}`);
|
|
441
|
+
});
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
### Using Security Layers Together
|
|
445
|
+
|
|
446
|
+
```typescript
|
|
447
|
+
import {
|
|
448
|
+
createDefaultTransactionGuard,
|
|
449
|
+
createAuditLog,
|
|
450
|
+
RateLimiter
|
|
451
|
+
} from "@shadowcorp/near-connect";
|
|
452
|
+
|
|
453
|
+
// Setup security stack
|
|
454
|
+
const txGuard = createDefaultTransactionGuard();
|
|
455
|
+
const auditLog = createAuditLog({ consoleLog: true });
|
|
456
|
+
const rateLimiter = new RateLimiter({ maxRequests: 10, windowMs: 60000 });
|
|
457
|
+
|
|
458
|
+
async function secureSign(transaction) {
|
|
459
|
+
// 1. Check rate limit
|
|
460
|
+
const rateResult = rateLimiter.check("sign");
|
|
461
|
+
if (!rateResult.allowed) {
|
|
462
|
+
auditLog.log("rate:limited", { data: { retryAfter: rateResult.retryAfter } });
|
|
463
|
+
throw new Error(`Rate limited. Retry in ${rateResult.retryAfter}s`);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// 2. Validate transaction
|
|
467
|
+
const txResult = txGuard.validate(transaction);
|
|
468
|
+
if (!txResult.valid) {
|
|
469
|
+
auditLog.logTransaction("tx:blocked", {
|
|
470
|
+
receiverId: transaction.receiverId,
|
|
471
|
+
error: txResult.error,
|
|
472
|
+
risk: txResult.risk.level
|
|
473
|
+
});
|
|
474
|
+
throw new Error(txResult.error);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// 3. Log and proceed
|
|
478
|
+
auditLog.logTransaction("tx:sign", { receiverId: transaction.receiverId });
|
|
479
|
+
return await wallet.signAndSendTransaction(transaction);
|
|
480
|
+
}
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
## Enhancements
|
|
484
|
+
|
|
485
|
+
This fork adds the following features to the original near-connect:
|
|
486
|
+
|
|
487
|
+
### Session & Storage
|
|
488
|
+
- Multiple storage backends (Memory, Local, Session, IndexedDB, Encrypted)
|
|
489
|
+
- SessionManager with validation and automatic expiry
|
|
490
|
+
|
|
491
|
+
### Error Handling
|
|
492
|
+
- Structured error system with typed error codes
|
|
493
|
+
- Specific error classes for different failure modes
|
|
494
|
+
- User-friendly messages and recovery suggestions
|
|
495
|
+
|
|
496
|
+
### UI Components
|
|
497
|
+
- WalletSelectorModal, TransactionModal, AccountSwitcherModal
|
|
498
|
+
- Dark/light theme system with CSS variable generation
|
|
499
|
+
- Customizable icons and styling
|
|
500
|
+
|
|
501
|
+
### Connection Reliability
|
|
502
|
+
- Retry logic with exponential backoff
|
|
503
|
+
- Connection state machine
|
|
504
|
+
- Health monitoring
|
|
505
|
+
- Automatic reconnection
|
|
506
|
+
- Circuit breaker pattern
|
|
507
|
+
|
|
508
|
+
### Hardware Wallets (Tier 3: Privileged)
|
|
509
|
+
- WebHID transport for Ledger
|
|
510
|
+
- APDU protocol implementation
|
|
511
|
+
- Full borsh serialization for NEAR transactions
|
|
512
|
+
- NEP-413 message signing
|
|
513
|
+
|
|
514
|
+
### Mobile Wallets (Tier 4: External)
|
|
515
|
+
- Deep link support (Meteor, HERE)
|
|
516
|
+
- WalletConnect v2 integration
|
|
517
|
+
- Redirect flow handling
|
|
518
|
+
- Mobile device detection
|
|
519
|
+
|
|
520
|
+
### Security Layers
|
|
521
|
+
- **TransactionGuard** - Risk analysis, dangerous method detection, blocklists
|
|
522
|
+
- **OriginGuard** - postMessage origin validation, callback URL verification
|
|
523
|
+
- **SecureStorage** - AES-GCM encrypted localStorage
|
|
524
|
+
- **RateLimiter** - Request throttling with configurable windows and blocking
|
|
525
|
+
- **AuditLog** - Event tracking, security monitoring, JSON/CSV export
|
|
526
|
+
- **CSP Helpers** - Content Security Policy generation and security checklist
|
|
527
|
+
|
|
528
|
+
### Other
|
|
529
|
+
- Transaction simulation with gas estimation
|
|
530
|
+
- Federated wallet manifest system
|
|
531
|
+
- Trust scoring for wallet reputation
|
|
532
|
+
- Pluggable analytics system
|
|
533
|
+
- Multi-account support
|
|
534
|
+
|
|
535
|
+
## API Reference
|
|
536
|
+
|
|
537
|
+
See the [TypeScript definitions](./src/index.ts) for full API documentation.
|
|
538
|
+
|
|
539
|
+
## License
|
|
540
|
+
|
|
541
|
+
MIT
|
|
542
|
+
|
|
543
|
+
## Credits
|
|
544
|
+
|
|
545
|
+
Original library by [azbang](https://github.com/azbang/near-connect).
|
|
546
|
+
Enhanced by ShadowCorp.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Account, FinalExecutionOutcome, NearWalletBase, Network, SignAndSendTransactionParams, SignAndSendTransactionsParams, SignedMessage, SignMessageParams } from "./types";
|
|
2
|
+
import { NearConnector } from "./NearConnector";
|
|
3
|
+
export declare class InjectedWallet {
|
|
4
|
+
readonly connector: NearConnector;
|
|
5
|
+
readonly wallet: NearWalletBase;
|
|
6
|
+
constructor(connector: NearConnector, wallet: NearWalletBase);
|
|
7
|
+
get manifest(): import("./types").WalletManifest;
|
|
8
|
+
signIn(data?: {
|
|
9
|
+
network?: Network;
|
|
10
|
+
contractId?: string;
|
|
11
|
+
methodNames?: Array<string>;
|
|
12
|
+
}): Promise<Array<Account>>;
|
|
13
|
+
signOut(data?: {
|
|
14
|
+
network?: Network;
|
|
15
|
+
}): Promise<void>;
|
|
16
|
+
getAccounts(data?: {
|
|
17
|
+
network?: Network;
|
|
18
|
+
}): Promise<Array<Account>>;
|
|
19
|
+
signAndSendTransaction(params: SignAndSendTransactionParams): Promise<FinalExecutionOutcome>;
|
|
20
|
+
signAndSendTransactions(params: SignAndSendTransactionsParams): Promise<Array<FinalExecutionOutcome>>;
|
|
21
|
+
signMessage(params: SignMessageParams): Promise<SignedMessage>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InjectedWallet = void 0;
|
|
4
|
+
const actions_1 = require("./actions");
|
|
5
|
+
class InjectedWallet {
|
|
6
|
+
connector;
|
|
7
|
+
wallet;
|
|
8
|
+
constructor(connector, wallet) {
|
|
9
|
+
this.connector = connector;
|
|
10
|
+
this.wallet = wallet;
|
|
11
|
+
}
|
|
12
|
+
get manifest() {
|
|
13
|
+
return this.wallet.manifest;
|
|
14
|
+
}
|
|
15
|
+
async signIn(data) {
|
|
16
|
+
return this.wallet.signIn({
|
|
17
|
+
network: data?.network || this.connector.network,
|
|
18
|
+
contractId: data?.contractId,
|
|
19
|
+
methodNames: data?.methodNames,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
async signOut(data) {
|
|
23
|
+
await this.wallet.signOut({ network: data?.network || this.connector.network });
|
|
24
|
+
}
|
|
25
|
+
async getAccounts(data) {
|
|
26
|
+
return this.wallet.getAccounts({ network: data?.network || this.connector.network });
|
|
27
|
+
}
|
|
28
|
+
async signAndSendTransaction(params) {
|
|
29
|
+
const actions = (0, actions_1.nearActionsToConnectorActions)(params.actions);
|
|
30
|
+
const network = params.network || this.connector.network;
|
|
31
|
+
const result = await this.wallet.signAndSendTransaction({ ...params, actions, network });
|
|
32
|
+
if (!result)
|
|
33
|
+
throw new Error("No result from wallet");
|
|
34
|
+
// @ts-ignore
|
|
35
|
+
if (Array.isArray(result.transactions))
|
|
36
|
+
return result.transactions[0];
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
async signAndSendTransactions(params) {
|
|
40
|
+
const network = params.network || this.connector.network;
|
|
41
|
+
const transactions = params.transactions.map((transaction) => ({
|
|
42
|
+
actions: (0, actions_1.nearActionsToConnectorActions)(transaction.actions),
|
|
43
|
+
receiverId: transaction.receiverId,
|
|
44
|
+
}));
|
|
45
|
+
const result = await this.wallet.signAndSendTransactions({ ...params, transactions, network });
|
|
46
|
+
if (!result)
|
|
47
|
+
throw new Error("No result from wallet");
|
|
48
|
+
// @ts-ignore
|
|
49
|
+
if (Array.isArray(result.transactions))
|
|
50
|
+
return result.transactions;
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
async signMessage(params) {
|
|
54
|
+
return this.wallet.signMessage({ ...params, network: params.network || this.connector.network });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
exports.InjectedWallet = InjectedWallet;
|
|
58
|
+
//# sourceMappingURL=InjectedWallet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InjectedWallet.js","sourceRoot":"","sources":["../src/InjectedWallet.ts"],"names":[],"mappings":";;;AAWA,uCAA0D;AAE1D,MAAa,cAAc;IACJ;IAAmC;IAAxD,YAAqB,SAAwB,EAAW,MAAsB;QAAzD,cAAS,GAAT,SAAS,CAAe;QAAW,WAAM,GAAN,MAAM,CAAgB;IAAG,CAAC;IAElF,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAA8E;QACzF,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;YACxB,OAAO,EAAE,IAAI,EAAE,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO;YAChD,UAAU,EAAE,IAAI,EAAE,UAAU;YAC5B,WAAW,EAAE,IAAI,EAAE,WAAW;SAC/B,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,IAA4B;QACxC,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,IAA4B;QAC5C,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;IACvF,CAAC;IAED,KAAK,CAAC,sBAAsB,CAAC,MAAoC;QAC/D,MAAM,OAAO,GAAG,IAAA,uCAA6B,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC9D,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;QAEzD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QACzF,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAEtD,aAAa;QACb,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC;YAAE,OAAO,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACtE,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,uBAAuB,CAAC,MAAqC;QACjE,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;QACzD,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;YAC7D,OAAO,EAAE,IAAA,uCAA6B,EAAC,WAAW,CAAC,OAAO,CAAC;YAC3D,UAAU,EAAE,WAAW,CAAC,UAAU;SACnC,CAAC,CAAC,CAAC;QAEJ,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,uBAAuB,CAAC,EAAE,GAAG,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,CAAC;QAC/F,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAEtD,aAAa;QACb,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC;YAAE,OAAO,MAAM,CAAC,YAAY,CAAC;QACnE,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,MAAyB;QACzC,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;IACnG,CAAC;CACF;AArDD,wCAqDC"}
|