@hypelens/hypelens-agent-rail 0.1.22 → 0.1.23
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 +14 -1
- package/bin/hypelens-setup.js +204 -0
- package/package.json +6 -4
- package/src/core.js +1 -1
- package/src/mcp.js +37 -2
- package/vendor/hl-signer.js +1 -1
package/README.md
CHANGED
|
@@ -10,10 +10,23 @@ Outside-agent Hyperliquid **place** rail. Builder fees → `0x9548B8E9554a196884
|
|
|
10
10
|
- If only agent key (`HYPELENS_AGENT_PK`) → return clear unsigned approve payloads + `maxBuilderFee` status; **refuse place-with-builder** until `maxBuilderFee >= 10` (no silent $0).
|
|
11
11
|
3. **Consent:** `hl_place_order` requires `confirmTrade: true` or `intent: "trade"|"place"|"execute"`.
|
|
12
12
|
|
|
13
|
+
## Post-install (REQUIRED — downloads ≠ fees)
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
cd skills/hyperliquid-place/scripts && npm install && node setup.mjs
|
|
17
|
+
# or: npx -y @hypelens/hypelens-agent-rail@0.1.23 hypelens-setup
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`setup.mjs` / `hypelens-setup`:
|
|
21
|
+
1. Registers MCP in OpenClaw/Claude/Cursor config when possible
|
|
22
|
+
2. Auto `ApproveBuilderFee` when `HYPERLIQUID_PRIVATE_KEY` / `HYPELENS_MASTER_PK` present
|
|
23
|
+
3. Prints `maxBuilderFee` — place stays refused until approved (no silent $0)
|
|
24
|
+
4. Next: fund agent if equity=0 → place on explicit trade intent
|
|
25
|
+
|
|
13
26
|
## Quick path
|
|
14
27
|
|
|
15
28
|
```bash
|
|
16
|
-
npx -y @hypelens/hypelens-agent-rail@0.1.
|
|
29
|
+
npx -y @hypelens/hypelens-agent-rail@0.1.23
|
|
17
30
|
# or sticky ClawHub:
|
|
18
31
|
clawhub install hyperliquid-place
|
|
19
32
|
cd skills/hyperliquid-place/scripts && npm install && node start-mcp.mjs
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* OpenBroker-style post-install one-shot:
|
|
4
|
+
* 1) Wire MCP into host config (OpenClaw / Claude / Cursor) when possible
|
|
5
|
+
* 2) Ensure agent key (generate if missing)
|
|
6
|
+
* 3) Auto ApproveBuilderFee when HYPERLIQUID_PRIVATE_KEY / HYPELENS_MASTER_PK present
|
|
7
|
+
* 4) Print maxBuilderFee + fund + place next (never silent $0)
|
|
8
|
+
* NEVER trades/farms 0x9548…
|
|
9
|
+
*/
|
|
10
|
+
import { writeFileSync, readFileSync, existsSync, mkdirSync, chmodSync } from 'node:fs';
|
|
11
|
+
import { homedir } from 'node:os';
|
|
12
|
+
import { join, dirname } from 'node:path';
|
|
13
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
14
|
+
import { createRequire } from 'node:module';
|
|
15
|
+
|
|
16
|
+
const FORBIDDEN = '0x9548B8E9554a1968843B3C380431b10996247c88';
|
|
17
|
+
const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..');
|
|
18
|
+
|
|
19
|
+
function loadRail() {
|
|
20
|
+
process.env.HYPELENS_QUIET = '1';
|
|
21
|
+
return import(pathToFileURL(join(ROOT, 'src', 'index.js')).href);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function expand(p) {
|
|
25
|
+
return p.replace(/^~(?=\/|$)/, homedir());
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Candidate MCP host config files (best-effort; never overwrite unrelated keys). */
|
|
29
|
+
function hostConfigPaths() {
|
|
30
|
+
const h = homedir();
|
|
31
|
+
return [
|
|
32
|
+
{ kind: 'openclaw', path: join(h, '.openclaw', 'openclaw.json') },
|
|
33
|
+
{ kind: 'openclaw', path: join(h, '.openclaw', 'config.json') },
|
|
34
|
+
{ kind: 'openclaw', path: join(h, '.openclaw', 'mcp.json') },
|
|
35
|
+
{ kind: 'claude', path: join(h, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json') },
|
|
36
|
+
{ kind: 'claude', path: join(h, '.config', 'Claude', 'claude_desktop_config.json') },
|
|
37
|
+
{ kind: 'cursor', path: join(h, '.cursor', 'mcp.json') },
|
|
38
|
+
];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function mcpServerEntry(scriptsDir) {
|
|
42
|
+
const start = scriptsDir ? join(scriptsDir, 'start-mcp.mjs') : null;
|
|
43
|
+
if (start && existsSync(start)) {
|
|
44
|
+
return {
|
|
45
|
+
command: 'node',
|
|
46
|
+
args: [start],
|
|
47
|
+
env: {
|
|
48
|
+
HYPELENS_NET: process.env.HYPELENS_NET || 'mainnet',
|
|
49
|
+
...(process.env.HYPELENS_AGENT_PK ? { HYPELENS_AGENT_PK: process.env.HYPELENS_AGENT_PK } : {}),
|
|
50
|
+
...(process.env.HYPERLIQUID_PRIVATE_KEY ? { HYPERLIQUID_PRIVATE_KEY: process.env.HYPERLIQUID_PRIVATE_KEY } : {}),
|
|
51
|
+
...(process.env.HYPELENS_MASTER_PK ? { HYPELENS_MASTER_PK: process.env.HYPELENS_MASTER_PK } : {}),
|
|
52
|
+
...(process.env.HYPERLIQUID_ACCOUNT_ADDRESS ? { HYPERLIQUID_ACCOUNT_ADDRESS: process.env.HYPERLIQUID_ACCOUNT_ADDRESS } : {}),
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
command: 'npx',
|
|
58
|
+
args: ['-y', '@hypelens/hypelens-agent-rail@0.1.23'],
|
|
59
|
+
env: {
|
|
60
|
+
HYPELENS_NET: process.env.HYPELENS_NET || 'mainnet',
|
|
61
|
+
...(process.env.HYPELENS_AGENT_PK ? { HYPELENS_AGENT_PK: process.env.HYPELENS_AGENT_PK } : {}),
|
|
62
|
+
...(process.env.HYPERLIQUID_PRIVATE_KEY ? { HYPERLIQUID_PRIVATE_KEY: process.env.HYPERLIQUID_PRIVATE_KEY } : {}),
|
|
63
|
+
...(process.env.HYPELENS_MASTER_PK ? { HYPELENS_MASTER_PK: process.env.HYPELENS_MASTER_PK } : {}),
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function wireMcp({ scriptsDir, name = 'hyperliquid-place' } = {}) {
|
|
69
|
+
const entry = mcpServerEntry(scriptsDir);
|
|
70
|
+
const wired = [];
|
|
71
|
+
const suggested = { mcpServers: { [name]: entry } };
|
|
72
|
+
for (const host of hostConfigPaths()) {
|
|
73
|
+
try {
|
|
74
|
+
const dir = dirname(host.path);
|
|
75
|
+
if (!existsSync(dir) && host.kind === 'openclaw') {
|
|
76
|
+
mkdirSync(dir, { recursive: true });
|
|
77
|
+
}
|
|
78
|
+
if (!existsSync(dirname(host.path))) continue;
|
|
79
|
+
let cfg = {};
|
|
80
|
+
if (existsSync(host.path)) {
|
|
81
|
+
cfg = JSON.parse(readFileSync(host.path, 'utf8'));
|
|
82
|
+
} else if (host.kind !== 'openclaw') {
|
|
83
|
+
// only auto-create openclaw configs; for others print snippet
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (!cfg.mcpServers || typeof cfg.mcpServers !== 'object') cfg.mcpServers = {};
|
|
87
|
+
cfg.mcpServers[name] = entry;
|
|
88
|
+
writeFileSync(host.path, JSON.stringify(cfg, null, 2) + '\n', { mode: 0o600 });
|
|
89
|
+
try { chmodSync(host.path, 0o600); } catch (_) {}
|
|
90
|
+
wired.push({ kind: host.kind, path: host.path });
|
|
91
|
+
} catch (e) {
|
|
92
|
+
wired.push({ kind: host.kind, path: host.path, error: String(e && e.message ? e.message : e) });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return { wired, suggested, entry };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async function runApprove() {
|
|
99
|
+
const rail = await loadRail();
|
|
100
|
+
const { newAgentWallet, approvePayloads, checkMaxBuilderFee, exchangeStatus } = rail;
|
|
101
|
+
const status = exchangeStatus();
|
|
102
|
+
let agentPk = process.env.HYPELENS_AGENT_PK || '';
|
|
103
|
+
let agentAddress = null;
|
|
104
|
+
let generated = null;
|
|
105
|
+
if (!agentPk && process.env.HYPERLIQUID_PRIVATE_KEY) {
|
|
106
|
+
// Fresh-wallet OpenBroker: sole key places + can auto-approve
|
|
107
|
+
agentPk = process.env.HYPERLIQUID_PRIVATE_KEY;
|
|
108
|
+
process.env.HYPELENS_AGENT_PK = agentPk;
|
|
109
|
+
}
|
|
110
|
+
if (!agentPk) {
|
|
111
|
+
generated = newAgentWallet();
|
|
112
|
+
agentPk = generated.privateKey;
|
|
113
|
+
agentAddress = generated.address;
|
|
114
|
+
process.env.HYPELENS_AGENT_PK = agentPk;
|
|
115
|
+
} else {
|
|
116
|
+
const { loadShipped } = await import(pathToFileURL(join(ROOT, 'src', 'load.js')).href);
|
|
117
|
+
const { signer } = loadShipped();
|
|
118
|
+
agentAddress = signer.addressFromPrivateKey(agentPk);
|
|
119
|
+
}
|
|
120
|
+
if (agentAddress && agentAddress.toLowerCase() === FORBIDDEN.toLowerCase()) {
|
|
121
|
+
throw new Error('Refusing setup for builder sink wallet ' + FORBIDDEN);
|
|
122
|
+
}
|
|
123
|
+
const approve = await approvePayloads(agentAddress);
|
|
124
|
+
let fee = null;
|
|
125
|
+
try { fee = await checkMaxBuilderFee({ user: agentAddress }); } catch (e) {
|
|
126
|
+
fee = { error: String(e && e.message ? e.message : e), approved: false };
|
|
127
|
+
}
|
|
128
|
+
return { status, generated, agentAddress, approve, maxBuilderFee: fee };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function parseArgs(argv) {
|
|
132
|
+
const out = { scriptsDir: null, writeEnv: null, json: false };
|
|
133
|
+
for (let i = 2; i < argv.length; i++) {
|
|
134
|
+
const a = argv[i];
|
|
135
|
+
if (a === '--json') out.json = true;
|
|
136
|
+
else if (a === '--scripts-dir' && argv[i + 1]) out.scriptsDir = expand(argv[++i]);
|
|
137
|
+
else if (a === '--write-env' && argv[i + 1]) out.writeEnv = expand(argv[++i]);
|
|
138
|
+
}
|
|
139
|
+
// default scripts dir = cwd if start-mcp.mjs present
|
|
140
|
+
if (!out.scriptsDir && existsSync(join(process.cwd(), 'start-mcp.mjs'))) out.scriptsDir = process.cwd();
|
|
141
|
+
return out;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async function main() {
|
|
145
|
+
const args = parseArgs(process.argv);
|
|
146
|
+
const mcp = wireMcp({ scriptsDir: args.scriptsDir });
|
|
147
|
+
const feePath = await runApprove();
|
|
148
|
+
if (args.writeEnv && feePath.generated) {
|
|
149
|
+
const lines = [
|
|
150
|
+
`# hypelens setup ${new Date().toISOString()}`,
|
|
151
|
+
`HYPELENS_NET=${process.env.HYPELENS_NET || 'mainnet'}`,
|
|
152
|
+
`HYPELENS_AGENT_PK=${feePath.generated.privateKey}`,
|
|
153
|
+
process.env.HYPERLIQUID_PRIVATE_KEY ? `HYPERLIQUID_PRIVATE_KEY=${process.env.HYPERLIQUID_PRIVATE_KEY}` : '# export HYPERLIQUID_PRIVATE_KEY=<master> for auto ApproveBuilderFee',
|
|
154
|
+
'',
|
|
155
|
+
];
|
|
156
|
+
writeFileSync(args.writeEnv, lines.join('\n'), { mode: 0o600 });
|
|
157
|
+
try { chmodSync(args.writeEnv, 0o600); } catch (_) {}
|
|
158
|
+
}
|
|
159
|
+
const approved = Boolean(feePath.maxBuilderFee && feePath.maxBuilderFee.approved) || Boolean(feePath.approve && feePath.approve.autoApproved);
|
|
160
|
+
const report = {
|
|
161
|
+
ok: true,
|
|
162
|
+
package: '@hypelens/hypelens-agent-rail',
|
|
163
|
+
builder: FORBIDDEN,
|
|
164
|
+
builderFee: '1bp (f=10) — never trade builder wallet',
|
|
165
|
+
mcpWired: mcp.wired.filter((w) => !w.error),
|
|
166
|
+
mcpWireErrors: mcp.wired.filter((w) => w.error),
|
|
167
|
+
mcpSuggested: mcp.suggested,
|
|
168
|
+
agentAddress: feePath.agentAddress,
|
|
169
|
+
generatedAgent: Boolean(feePath.generated),
|
|
170
|
+
generatedPrivateKey: feePath.generated ? feePath.generated.privateKey : undefined,
|
|
171
|
+
approveMode: feePath.approve && feePath.approve.mode,
|
|
172
|
+
autoApproved: Boolean(feePath.approve && feePath.approve.autoApproved),
|
|
173
|
+
maxBuilderFee: feePath.maxBuilderFee,
|
|
174
|
+
placeAllowed: approved,
|
|
175
|
+
next: !approved
|
|
176
|
+
? 'Export HYPERLIQUID_PRIVATE_KEY=<master> and re-run setup (auto ApproveBuilderFee), OR MASTER-sign approve payloads. Place is REFUSED until maxBuilderFee>=10 — no silent $0.'
|
|
177
|
+
: 'Restart MCP host. hl_balances — if equity=0 deposit USDC to agentAddress. On explicit trade intent: hl_place_order({coin:"BTC", isBuy:true, sizeUsd:12, leverage:2, confirmTrade:true})',
|
|
178
|
+
funnel: ['mcp_wired', 'approve_builder_fee', 'fund_if_needed', 'place_on_intent'],
|
|
179
|
+
};
|
|
180
|
+
if (args.json) {
|
|
181
|
+
console.log(JSON.stringify(report, null, 2));
|
|
182
|
+
} else {
|
|
183
|
+
console.log('HypeLens setup (OpenBroker)');
|
|
184
|
+
console.log('- MCP wired:', report.mcpWired.length ? report.mcpWired.map((w) => w.path).join(', ') : '(none — paste mcpSuggested into host config)');
|
|
185
|
+
if (report.mcpWireErrors.length) console.log('- MCP wire errors:', report.mcpWireErrors);
|
|
186
|
+
console.log('- Agent:', report.agentAddress);
|
|
187
|
+
if (report.generatedAgent) {
|
|
188
|
+
console.log('- Generated HYPELENS_AGENT_PK (store securely):', report.generatedPrivateKey);
|
|
189
|
+
}
|
|
190
|
+
console.log('- Approve mode:', report.approveMode, '| autoApproved:', report.autoApproved);
|
|
191
|
+
console.log('- maxBuilderFee:', JSON.stringify(report.maxBuilderFee));
|
|
192
|
+
console.log('- placeAllowed:', report.placeAllowed);
|
|
193
|
+
console.log('- NEXT:', report.next);
|
|
194
|
+
if (!report.mcpWired.length) {
|
|
195
|
+
console.log('\nPaste into host mcpServers:\n' + JSON.stringify(report.mcpSuggested, null, 2));
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
process.exit(approved ? 0 : 2);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
main().catch((e) => {
|
|
202
|
+
console.error('setup failed:', e && e.message ? e.message : e);
|
|
203
|
+
process.exit(1);
|
|
204
|
+
});
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hypelens/hypelens-agent-rail",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Mainnet place rail. OpenBroker auto ApproveBuilderFee when
|
|
3
|
+
"version": "0.1.23",
|
|
4
|
+
"description": "Mainnet place rail. Post-install: hypelens-setup wires MCP + OpenBroker auto ApproveBuilderFee when master key set; refuse place until maxBuilderFee>=10; always builder f=10. npx @hypelens/hypelens-agent-rail@0.1.23",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"bin": {
|
|
8
8
|
"hypelens-rail-mcp": "bin/hypelens-rail-mcp.js",
|
|
9
|
-
"hypelens-agent-rail": "bin/hypelens-rail-mcp.js"
|
|
9
|
+
"hypelens-agent-rail": "bin/hypelens-rail-mcp.js",
|
|
10
|
+
"hypelens-setup": "bin/hypelens-setup.js"
|
|
10
11
|
},
|
|
11
12
|
"main": "src/index.js",
|
|
12
13
|
"files": [
|
|
@@ -19,7 +20,8 @@
|
|
|
19
20
|
"scripts": {
|
|
20
21
|
"test": "node --test test/exchange.test.mjs test/risk.test.mjs",
|
|
21
22
|
"prepack": "node -e \"console.log(\\\"prepack: vendor already shipped\\\")\"",
|
|
22
|
-
"mcp": "node bin/hypelens-rail-mcp.js"
|
|
23
|
+
"mcp": "node bin/hypelens-rail-mcp.js",
|
|
24
|
+
"setup": "node bin/hypelens-setup.js"
|
|
23
25
|
},
|
|
24
26
|
"engines": {
|
|
25
27
|
"node": ">=20"
|
package/src/core.js
CHANGED
|
@@ -541,7 +541,7 @@ export async function quickstart({ coin = 'BTC' } = {}) {
|
|
|
541
541
|
builder_fee: '1bp (0.01%) on fills',
|
|
542
542
|
builder: actions.BUILDER,
|
|
543
543
|
package: '@hypelens/hypelens-agent-rail',
|
|
544
|
-
install: 'clawhub install hyperliquid-place | npx -y @hypelens/hypelens-agent-rail@0.1.
|
|
544
|
+
install: 'clawhub install hyperliquid-place | npx -y @hypelens/hypelens-agent-rail@0.1.23',
|
|
545
545
|
checklist,
|
|
546
546
|
steps: checklist,
|
|
547
547
|
first_place_example,
|
package/src/mcp.js
CHANGED
|
@@ -32,10 +32,45 @@ const heatAfterPlace = (fn) => async (args) => {
|
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
export async function main() {
|
|
35
|
-
const server = new McpServer({ name: 'hypelens-agent-rail', version: '0.1.
|
|
35
|
+
const server = new McpServer({ name: 'hypelens-agent-rail', version: '0.1.23' });
|
|
36
|
+
|
|
37
|
+
server.tool('hl_setup',
|
|
38
|
+
'POST-INSTALL one-shot status: has keys? maxBuilderFee? auto ApproveBuilderFee if master key set. Place refused until approved. Prefer scripts/setup.mjs outside MCP to also wire host MCP config.',
|
|
39
|
+
{ agentAddress: z.string().regex(/^0x[0-9a-fA-F]{40}$/).optional() },
|
|
40
|
+
wrap(async ({ agentAddress }) => {
|
|
41
|
+
const { approvePayloads, checkMaxBuilderFee, newAgentWallet, status } = await import('./exchange.js');
|
|
42
|
+
const st = status();
|
|
43
|
+
let addr = agentAddress;
|
|
44
|
+
let generated = null;
|
|
45
|
+
if (!addr) {
|
|
46
|
+
if (process.env.HYPELENS_AGENT_PK || process.env.HYPERLIQUID_PRIVATE_KEY) {
|
|
47
|
+
const { loadShipped } = await import('./load.js');
|
|
48
|
+
const { signer } = loadShipped();
|
|
49
|
+
addr = signer.addressFromPrivateKey(process.env.HYPELENS_AGENT_PK || process.env.HYPERLIQUID_PRIVATE_KEY);
|
|
50
|
+
} else {
|
|
51
|
+
generated = newAgentWallet();
|
|
52
|
+
addr = generated.address;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const approve = await approvePayloads(addr);
|
|
56
|
+
let fee = null;
|
|
57
|
+
try { fee = await checkMaxBuilderFee({ user: addr }); } catch (e) { fee = { error: String(e.message || e), approved: false }; }
|
|
58
|
+
return {
|
|
59
|
+
status: st,
|
|
60
|
+
agentAddress: addr,
|
|
61
|
+
generated,
|
|
62
|
+
approve,
|
|
63
|
+
maxBuilderFee: fee,
|
|
64
|
+
placeAllowed: Boolean(fee && fee.approved) || Boolean(approve.autoApproved),
|
|
65
|
+
installHint: 'Outside MCP run: cd skills/hyperliquid-place/scripts && npm install && node setup.mjs (wires host MCP + ApproveBuilderFee)',
|
|
66
|
+
next: (fee && fee.approved) || approve.autoApproved
|
|
67
|
+
? 'hl_balances → fund if equity=0 → hl_place_order(..., confirmTrade:true) on user trade intent'
|
|
68
|
+
: 'Set HYPERLIQUID_PRIVATE_KEY and re-call hl_setup / setup.mjs — place REFUSED until maxBuilderFee>=10'
|
|
69
|
+
};
|
|
70
|
+
}));
|
|
36
71
|
|
|
37
72
|
server.tool('hl_quickstart',
|
|
38
|
-
'CALL FIRST: checklist wallet→approve→hl_balances
|
|
73
|
+
'CALL FIRST after setup.mjs: checklist wallet→approve→hl_balances→hl_place_order sizeUsd on user trade intent. No heat-first.',
|
|
39
74
|
{ coin: z.string().optional().describe('Optional first-place coin (default BTC)') },
|
|
40
75
|
wrap(({ coin }) => quickstart({ coin })));
|
|
41
76
|
|
package/vendor/hl-signer.js
CHANGED
|
@@ -73,5 +73,5 @@
|
|
|
73
73
|
X3.signer = { ready, lastError, selfTest, signL1, signUserSigned, userTypedData, assertDeterministicHash, addressFromPrivateKey: (pk) => sdk().addressFromPrivateKey(pk) };
|
|
74
74
|
// Run the self-test once at load and surface the result in the console so a
|
|
75
75
|
// broken/absent SDK is obvious. Placement stays fail-closed on failure.
|
|
76
|
-
try { const r = selfTest(); if (r.ok) console.
|
|
76
|
+
try { const r = selfTest(); if (!r.ok) console.warn('[HypeLens] signing SDK self-test FAILED —', r.error); else if (typeof process === 'undefined' || process.env.HYPELENS_QUIET !== '1') console.log('[HypeLens] signing SDK self-test PASSED (hash', r.hash.slice(0, 10) + '…)'); } catch (e) {}
|
|
77
77
|
})(typeof window !== 'undefined' ? window : globalThis);
|