moneyos 0.6.0 → 0.6.2
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 +54 -1
- package/README.md +2 -2
- package/dist/cli/index.js +198 -70
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +53 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +53 -13
- package/dist/index.js.map +1 -1
- package/package.json +7 -10
- package/node_modules/@moneyos/gasless/CHANGELOG.md +0 -5
- package/node_modules/@moneyos/gasless/README.md +0 -29
- package/node_modules/@moneyos/gasless/contracts/MoneyOSAccountFactoryV1.sol +0 -58
- package/node_modules/@moneyos/gasless/contracts/MoneyOSAccountV1.sol +0 -330
- package/node_modules/@moneyos/gasless/contracts/interfaces/IIntentTypesV1.sol +0 -20
- package/node_modules/@moneyos/gasless/contracts/lib/ECDSA.sol +0 -41
- package/node_modules/@moneyos/gasless/contracts/lib/IntentHashV1.sol +0 -74
- package/node_modules/@moneyos/gasless/dist/index.cjs +0 -753
- package/node_modules/@moneyos/gasless/dist/index.cjs.map +0 -1
- package/node_modules/@moneyos/gasless/dist/index.d.cts +0 -514
- package/node_modules/@moneyos/gasless/dist/index.d.ts +0 -514
- package/node_modules/@moneyos/gasless/dist/index.js +0 -706
- package/node_modules/@moneyos/gasless/dist/index.js.map +0 -1
- package/node_modules/@moneyos/gasless/package.json +0 -43
- package/node_modules/@moneyos/gasless/vectors/intent-v1-golden.json +0 -36
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,59 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to the repo's current `main` branch are documented here.
|
|
4
4
|
|
|
5
|
+
## 0.6.2 - 2026-04-16
|
|
6
|
+
|
|
7
|
+
Fixes the broken `npm install -g moneyos` path reported in #114.
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- `npm install -g moneyos` no longer ships with an empty `node_modules/viem/`
|
|
12
|
+
and no longer crashes with `ERR_MODULE_NOT_FOUND` before the CLI can print
|
|
13
|
+
`--help`. Root cause was `@moneyos/gasless` being bundled inside the moneyos
|
|
14
|
+
tarball while declaring `viem` as a peerDependency, which npm mishandles on
|
|
15
|
+
global install. The smart-account package is now published standalone as
|
|
16
|
+
`@moneyos/smart-account` and no longer bundled, so `viem` resolves normally
|
|
17
|
+
as a top-level sibling. See #114 and #118.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- `@moneyos/gasless` has been renamed to
|
|
22
|
+
[`@moneyos/smart-account`](https://www.npmjs.com/package/@moneyos/smart-account)
|
|
23
|
+
and is now a standalone npm package. The new name reflects the package's
|
|
24
|
+
actual surface: smart-account contracts, EIP-712 intent signing, nonce lanes,
|
|
25
|
+
and the gasless relay client are all included — gasless execution is one
|
|
26
|
+
capability built on those primitives. The `moneyos gasless` CLI command,
|
|
27
|
+
`config.gasless` key, and `MONEYOS_GASLESS_*` env vars all keep their names;
|
|
28
|
+
only the underlying package was renamed.
|
|
29
|
+
- Root `moneyos` tarball shrinks from 180KB to 143KB now that the smart-account
|
|
30
|
+
code lives in its own package alongside `viem` and other deps.
|
|
31
|
+
- `scripts/release-verify.mjs` now includes a `npm install -g` smoke test that
|
|
32
|
+
would have caught the 0.6.0 and 0.6.1 regressions before they shipped.
|
|
33
|
+
|
|
34
|
+
## 0.6.1 - 2026-04-16
|
|
35
|
+
|
|
36
|
+
Patch release rolling up the gasless swap UX fixes from #101, #102, #108, and #110.
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
|
|
40
|
+
- `moneyos balance` now shows both the EOA and smart-account balances when
|
|
41
|
+
gasless mode is enabled and `--address` is not passed, so users can see at a
|
|
42
|
+
glance which wallet actually holds funds (#103, #108).
|
|
43
|
+
- `moneyos swap` performs a client-side balance pre-check on the executor wallet
|
|
44
|
+
before requesting a quote, failing fast with a clear
|
|
45
|
+
`Insufficient <symbol> balance on <address>: need N, have M` error for both
|
|
46
|
+
ERC-20 and native inputs (#106, #108).
|
|
47
|
+
- Gasless swap failures surface the underlying revert reason in the error
|
|
48
|
+
message (e.g. `Gasless swap failed: ERC20: transfer amount exceeds balance
|
|
49
|
+
[simulation_failed]`) instead of the generic
|
|
50
|
+
`Relay accepted intent without txHash` (#105, #110).
|
|
51
|
+
- `@moneyos/smart-account` exports a typed `GaslessRelayError` class that carries
|
|
52
|
+
`revertReason`, `policyCode`, `reason`, and `submissionId` for callers that
|
|
53
|
+
want to react programmatically to relay rejections (#110).
|
|
54
|
+
- Local session executor submits the `approve` + `swap` pair as a single atomic
|
|
55
|
+
batch on batching executors, matching the relay policy that only sponsors
|
|
56
|
+
`[approve, swap]` shapes for ERC-20-in swaps (#101, #102).
|
|
57
|
+
|
|
5
58
|
## 0.6.0 - 2026-04-15
|
|
6
59
|
|
|
7
60
|
Gasless execution, local contacts, and a wave of wallet UX cleanup.
|
|
@@ -9,7 +62,7 @@ Gasless execution, local contacts, and a wave of wallet UX cleanup.
|
|
|
9
62
|
### Added
|
|
10
63
|
|
|
11
64
|
- Gasless execution mode, opt-in and default-off. `moneyos gasless status|enable|disable` routes write commands through a smart-account executor instead of the owner EOA. The relay sponsors gas; the smart account still has to hold the asset being sent or swapped. Arbitrum One is the v1 target, with baked defaults for the relay URL, sponsor, factory, and derived smart-account address so `moneyos gasless enable` works out of the box.
|
|
12
|
-
- Smart-account primitives shipped inside the new `@moneyos/
|
|
65
|
+
- Smart-account primitives shipped inside the new `@moneyos/smart-account` workspace package: `MoneyOSAccountV1`, `MoneyOSAccountFactoryV1` with deterministic CREATE2 deployment, EIP-712 `IntentV1`, ERC-1271 owner-only validation, and replay-safe signer-scoped nonce lanes. The package is bundled inside the published root `moneyos` tarball and is not published to npm on its own.
|
|
13
66
|
- Hosted gasless relay at `services/relay/` — Fastify HTTP app with `POST /v1/execute`, `GET /v1/capabilities`, `GET /v1/tx/:id`; SQLite persistence for nonce reservations, submissions, and usage counters; nonce/simulation/treasury/wallet/health gates; submission adapter with `deployAndExecute` for undeployed smart accounts; kill switch; deploy artifacts for macOS launchd, Linux systemd, and Docker.
|
|
14
67
|
- Local contacts address book. `moneyos contact set|list|remove` stores `name → address` pairs in `~/.moneyos/contacts.json` with 0600 permissions. `moneyos send <amount> <token> <name>` now accepts either a 0x address or a saved contact name, and prints the resolved address before execution so the recipient is always visible.
|
|
15
68
|
- `moneyos update [tool] [--check]` for updating installed MoneyOS CLI tools from the user tool home.
|
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ but the repo is structured so each major surface can evolve independently.
|
|
|
12
12
|
|
|
13
13
|
- `moneyos`: the root SDK + CLI package for runtime, wallet, balance, and send
|
|
14
14
|
- `@moneyos/core`: runtime interfaces, shared types, chain/token registries
|
|
15
|
-
- `@moneyos/
|
|
15
|
+
- `@moneyos/smart-account`: smart-account contracts, intent helpers, gasless executor, relay client, and baked Arbitrum defaults
|
|
16
16
|
- `@moneyos/swap`: canonical swap package and Odos provider, published on npm
|
|
17
17
|
- `services/relay`: the hosted relay service that sponsors gas for the gasless path
|
|
18
18
|
|
|
@@ -268,7 +268,7 @@ Published packages:
|
|
|
268
268
|
- `@moneyos/core`
|
|
269
269
|
- `@moneyos/swap`
|
|
270
270
|
|
|
271
|
-
`@moneyos/
|
|
271
|
+
`@moneyos/smart-account` exists in this repo but is not published to npm yet.
|
|
272
272
|
|
|
273
273
|
Current `moneyos` releases no longer bundle swap into the root SDK or CLI. If
|
|
274
274
|
you want swap from the root CLI, install `moneyos` and then run
|
package/dist/cli/index.js
CHANGED
|
@@ -653,7 +653,7 @@ import {
|
|
|
653
653
|
GaslessExecutor,
|
|
654
654
|
RelayClient,
|
|
655
655
|
moneyOSAccountV1Abi
|
|
656
|
-
} from "@moneyos/
|
|
656
|
+
} from "@moneyos/smart-account";
|
|
657
657
|
import { createPublicClient, http } from "viem";
|
|
658
658
|
|
|
659
659
|
// packages/core/dist/index.js
|
|
@@ -1003,7 +1003,7 @@ function createRequestId() {
|
|
|
1003
1003
|
return `${Date.now()}-${Math.random().toString(16).slice(2, 10)}`;
|
|
1004
1004
|
}
|
|
1005
1005
|
function createSendRequestFingerprint(request) {
|
|
1006
|
-
return JSON.stringify(request.params);
|
|
1006
|
+
return JSON.stringify({ type: request.type, params: request.params });
|
|
1007
1007
|
}
|
|
1008
1008
|
function toGaslessExecutionConfig(config) {
|
|
1009
1009
|
return {
|
|
@@ -1142,6 +1142,14 @@ function unwrapSessionSendResponse(response) {
|
|
|
1142
1142
|
}
|
|
1143
1143
|
return response.result;
|
|
1144
1144
|
}
|
|
1145
|
+
function capabilitiesForMode(mode) {
|
|
1146
|
+
const smartAccount = mode === "smart-account";
|
|
1147
|
+
return {
|
|
1148
|
+
sponsoredGas: smartAccount,
|
|
1149
|
+
batching: false,
|
|
1150
|
+
simulation: smartAccount
|
|
1151
|
+
};
|
|
1152
|
+
}
|
|
1145
1153
|
async function getSessionStatus(socketPath, tokenPath) {
|
|
1146
1154
|
try {
|
|
1147
1155
|
const response = await sendSessionRequest(
|
|
@@ -1157,10 +1165,12 @@ async function getSessionStatus(socketPath, tokenPath) {
|
|
|
1157
1165
|
return void 0;
|
|
1158
1166
|
}
|
|
1159
1167
|
const result = response.result;
|
|
1168
|
+
const mode = result.mode ?? "eoa";
|
|
1160
1169
|
return {
|
|
1161
1170
|
address: result.address,
|
|
1162
1171
|
expiresAt: result.expiresAt,
|
|
1163
|
-
mode
|
|
1172
|
+
mode,
|
|
1173
|
+
capabilities: result.capabilities ?? capabilitiesForMode(mode)
|
|
1164
1174
|
};
|
|
1165
1175
|
} catch {
|
|
1166
1176
|
removeFileIfPresent(socketPath);
|
|
@@ -1186,16 +1196,26 @@ async function lockSession(socketPath, tokenPath) {
|
|
|
1186
1196
|
return false;
|
|
1187
1197
|
}
|
|
1188
1198
|
}
|
|
1199
|
+
function serializeCallForSession(call) {
|
|
1200
|
+
return {
|
|
1201
|
+
to: call.to,
|
|
1202
|
+
chainId: call.chainId,
|
|
1203
|
+
data: call.data,
|
|
1204
|
+
value: call.value?.toString()
|
|
1205
|
+
};
|
|
1206
|
+
}
|
|
1189
1207
|
var SessionExecutionClient = class {
|
|
1190
1208
|
mode;
|
|
1191
1209
|
socketPath;
|
|
1192
1210
|
tokenPath;
|
|
1193
1211
|
address;
|
|
1212
|
+
caps;
|
|
1194
1213
|
constructor(params) {
|
|
1195
1214
|
this.socketPath = params.socketPath;
|
|
1196
1215
|
this.tokenPath = params.tokenPath;
|
|
1197
1216
|
this.address = params.address;
|
|
1198
1217
|
this.mode = params.mode ?? "eoa";
|
|
1218
|
+
this.caps = params.capabilities ?? capabilitiesForMode(this.mode);
|
|
1199
1219
|
}
|
|
1200
1220
|
getAddress() {
|
|
1201
1221
|
return this.address;
|
|
@@ -1211,6 +1231,20 @@ var SessionExecutionClient = class {
|
|
|
1211
1231
|
return this.sendWithRequestId(requestId, call);
|
|
1212
1232
|
}
|
|
1213
1233
|
}
|
|
1234
|
+
async sendBatch(calls) {
|
|
1235
|
+
if (calls.length === 0) {
|
|
1236
|
+
throw new Error("sendBatch requires at least one call");
|
|
1237
|
+
}
|
|
1238
|
+
const requestId = createRequestId();
|
|
1239
|
+
try {
|
|
1240
|
+
return await this.sendBatchWithRequestId(requestId, calls);
|
|
1241
|
+
} catch (error) {
|
|
1242
|
+
if (!isRetryableSessionTransportError(error)) {
|
|
1243
|
+
throw error;
|
|
1244
|
+
}
|
|
1245
|
+
return this.sendBatchWithRequestId(requestId, calls);
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1214
1248
|
async sendWithRequestId(requestId, call) {
|
|
1215
1249
|
const response = await sendSessionRequest(
|
|
1216
1250
|
this.socketPath,
|
|
@@ -1218,11 +1252,21 @@ var SessionExecutionClient = class {
|
|
|
1218
1252
|
{
|
|
1219
1253
|
id: requestId,
|
|
1220
1254
|
type: "send",
|
|
1255
|
+
params: serializeCallForSession(call)
|
|
1256
|
+
},
|
|
1257
|
+
SESSION_SEND_TIMEOUT_MS
|
|
1258
|
+
);
|
|
1259
|
+
return unwrapSessionSendResponse(response);
|
|
1260
|
+
}
|
|
1261
|
+
async sendBatchWithRequestId(requestId, calls) {
|
|
1262
|
+
const response = await sendSessionRequest(
|
|
1263
|
+
this.socketPath,
|
|
1264
|
+
this.tokenPath,
|
|
1265
|
+
{
|
|
1266
|
+
id: requestId,
|
|
1267
|
+
type: "sendBatch",
|
|
1221
1268
|
params: {
|
|
1222
|
-
|
|
1223
|
-
chainId: call.chainId,
|
|
1224
|
-
data: call.data,
|
|
1225
|
-
value: call.value?.toString()
|
|
1269
|
+
calls: calls.map(serializeCallForSession)
|
|
1226
1270
|
}
|
|
1227
1271
|
},
|
|
1228
1272
|
SESSION_SEND_TIMEOUT_MS
|
|
@@ -1230,14 +1274,54 @@ var SessionExecutionClient = class {
|
|
|
1230
1274
|
return unwrapSessionSendResponse(response);
|
|
1231
1275
|
}
|
|
1232
1276
|
capabilities() {
|
|
1233
|
-
|
|
1277
|
+
return { ...this.caps };
|
|
1278
|
+
}
|
|
1279
|
+
};
|
|
1280
|
+
function deserializeSessionCall(params) {
|
|
1281
|
+
return {
|
|
1282
|
+
to: params.to,
|
|
1283
|
+
chainId: params.chainId,
|
|
1284
|
+
data: params.data,
|
|
1285
|
+
value: params.value !== void 0 ? BigInt(params.value) : void 0
|
|
1286
|
+
};
|
|
1287
|
+
}
|
|
1288
|
+
async function executeSendLikeRequest(executor, request) {
|
|
1289
|
+
try {
|
|
1290
|
+
let result;
|
|
1291
|
+
if (request.type === "send") {
|
|
1292
|
+
result = await executor.send(deserializeSessionCall(request.params));
|
|
1293
|
+
} else {
|
|
1294
|
+
if (typeof executor.sendBatch !== "function") {
|
|
1295
|
+
return {
|
|
1296
|
+
id: request.id,
|
|
1297
|
+
ok: false,
|
|
1298
|
+
error: "Session executor does not support batched execution."
|
|
1299
|
+
};
|
|
1300
|
+
}
|
|
1301
|
+
if (request.params.calls.length === 0) {
|
|
1302
|
+
return {
|
|
1303
|
+
id: request.id,
|
|
1304
|
+
ok: false,
|
|
1305
|
+
error: "sendBatch requires at least one call"
|
|
1306
|
+
};
|
|
1307
|
+
}
|
|
1308
|
+
result = await executor.sendBatch(
|
|
1309
|
+
request.params.calls.map(deserializeSessionCall)
|
|
1310
|
+
);
|
|
1311
|
+
}
|
|
1234
1312
|
return {
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1313
|
+
id: request.id,
|
|
1314
|
+
ok: true,
|
|
1315
|
+
result
|
|
1316
|
+
};
|
|
1317
|
+
} catch (error) {
|
|
1318
|
+
return {
|
|
1319
|
+
id: request.id,
|
|
1320
|
+
ok: false,
|
|
1321
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1238
1322
|
};
|
|
1239
1323
|
}
|
|
1240
|
-
}
|
|
1324
|
+
}
|
|
1241
1325
|
async function startSessionServer(start, hooks = {}) {
|
|
1242
1326
|
ensureSecureParent(start.tokenPath);
|
|
1243
1327
|
ensureSecureParent(start.socketPath);
|
|
@@ -1328,7 +1412,8 @@ async function startSessionServer(start, hooks = {}) {
|
|
|
1328
1412
|
result: {
|
|
1329
1413
|
address: executor.getAddress(),
|
|
1330
1414
|
expiresAt: expiresAt.toISOString(),
|
|
1331
|
-
mode: executor.mode
|
|
1415
|
+
mode: executor.mode,
|
|
1416
|
+
capabilities: executor.capabilities()
|
|
1332
1417
|
}
|
|
1333
1418
|
});
|
|
1334
1419
|
return;
|
|
@@ -1361,27 +1446,7 @@ async function startSessionServer(start, hooks = {}) {
|
|
|
1361
1446
|
respond(await existing.response);
|
|
1362
1447
|
return;
|
|
1363
1448
|
}
|
|
1364
|
-
const responsePromise = (
|
|
1365
|
-
try {
|
|
1366
|
-
const result = await executor.send({
|
|
1367
|
-
to: request.params.to,
|
|
1368
|
-
chainId: request.params.chainId,
|
|
1369
|
-
data: request.params.data,
|
|
1370
|
-
value: request.params.value !== void 0 ? BigInt(request.params.value) : void 0
|
|
1371
|
-
});
|
|
1372
|
-
return {
|
|
1373
|
-
id: request.id,
|
|
1374
|
-
ok: true,
|
|
1375
|
-
result
|
|
1376
|
-
};
|
|
1377
|
-
} catch (error) {
|
|
1378
|
-
return {
|
|
1379
|
-
id: request.id,
|
|
1380
|
-
ok: false,
|
|
1381
|
-
error: error instanceof Error ? error.message : String(error)
|
|
1382
|
-
};
|
|
1383
|
-
}
|
|
1384
|
-
})();
|
|
1449
|
+
const responsePromise = executeSendLikeRequest(executor, request);
|
|
1385
1450
|
sendResponses.set(request.id, {
|
|
1386
1451
|
fingerprint,
|
|
1387
1452
|
response: responsePromise
|
|
@@ -1416,6 +1481,7 @@ async function startSessionServer(start, hooks = {}) {
|
|
|
1416
1481
|
address: executor.getAddress(),
|
|
1417
1482
|
expiresAt: expiresAt.toISOString(),
|
|
1418
1483
|
mode: executor.mode,
|
|
1484
|
+
capabilities: executor.capabilities(),
|
|
1419
1485
|
close
|
|
1420
1486
|
};
|
|
1421
1487
|
}
|
|
@@ -1473,7 +1539,8 @@ async function startDetachedSessionDaemon(params) {
|
|
|
1473
1539
|
finish(void 0, {
|
|
1474
1540
|
address: payload.address,
|
|
1475
1541
|
expiresAt: payload.expiresAt,
|
|
1476
|
-
mode: payload.mode
|
|
1542
|
+
mode: payload.mode,
|
|
1543
|
+
capabilities: payload.capabilities ?? capabilitiesForMode(payload.mode)
|
|
1477
1544
|
});
|
|
1478
1545
|
} else if (payload?.type === "error") {
|
|
1479
1546
|
finish(new Error(payload.error));
|
|
@@ -1519,7 +1586,8 @@ async function runSessionDaemonProcess() {
|
|
|
1519
1586
|
type: "ready",
|
|
1520
1587
|
address: handle.address,
|
|
1521
1588
|
expiresAt: handle.expiresAt,
|
|
1522
|
-
mode: handle.mode
|
|
1589
|
+
mode: handle.mode,
|
|
1590
|
+
capabilities: handle.capabilities
|
|
1523
1591
|
});
|
|
1524
1592
|
process.on("SIGTERM", () => {
|
|
1525
1593
|
void handle.close().then(() => shutdown());
|
|
@@ -1876,7 +1944,8 @@ async function connectLocalSession(options = {}) {
|
|
|
1876
1944
|
socketPath,
|
|
1877
1945
|
tokenPath,
|
|
1878
1946
|
address: session.address,
|
|
1879
|
-
mode: session.mode
|
|
1947
|
+
mode: session.mode,
|
|
1948
|
+
capabilities: session.capabilities
|
|
1880
1949
|
});
|
|
1881
1950
|
}
|
|
1882
1951
|
|
|
@@ -1884,7 +1953,7 @@ async function connectLocalSession(options = {}) {
|
|
|
1884
1953
|
import {
|
|
1885
1954
|
deriveDefaultGaslessAccount,
|
|
1886
1955
|
getGaslessNetworkDefaults
|
|
1887
|
-
} from "@moneyos/
|
|
1956
|
+
} from "@moneyos/smart-account";
|
|
1888
1957
|
var GASLESS_ENABLED_ENV = "MONEYOS_GASLESS_ENABLED";
|
|
1889
1958
|
var GASLESS_RELAY_URL_ENV = "MONEYOS_GASLESS_RELAY_URL";
|
|
1890
1959
|
var GASLESS_ACCOUNT_ENV = "MONEYOS_GASLESS_ACCOUNT";
|
|
@@ -1940,6 +2009,7 @@ async function resolveGaslessExecutionConfig(config, options = {}) {
|
|
|
1940
2009
|
}
|
|
1941
2010
|
|
|
1942
2011
|
// src/cli/wallet.ts
|
|
2012
|
+
var GASLESS_MISSING_ENV_ERROR = "Gasless mode is enabled but required environment variables are missing. Set MONEYOS_GASLESS_RELAY_URL, MONEYOS_GASLESS_ACCOUNT, and MONEYOS_GASLESS_SPONSOR.";
|
|
1943
2013
|
function resolveEnvPrivateKey(explicit) {
|
|
1944
2014
|
return explicit ?? process.env.MONEYOS_PRIVATE_KEY;
|
|
1945
2015
|
}
|
|
@@ -1979,6 +2049,24 @@ async function loadCliAddress(config, options = {}) {
|
|
|
1979
2049
|
}
|
|
1980
2050
|
throw new Error("No wallet configured. Run `moneyos init`.");
|
|
1981
2051
|
}
|
|
2052
|
+
async function resolveCliOwnedAddresses(config, options = {}) {
|
|
2053
|
+
const { address } = await loadCliAddress(config, options);
|
|
2054
|
+
if (!isGaslessEnabled(config)) {
|
|
2055
|
+
return { eoa: address };
|
|
2056
|
+
}
|
|
2057
|
+
const gasless = await resolveGaslessExecutionConfig(config, {
|
|
2058
|
+
ownerAddress: address,
|
|
2059
|
+
chainId: options.chainId ?? config.chainId ?? 42161,
|
|
2060
|
+
rpcUrl: config.rpcUrl
|
|
2061
|
+
});
|
|
2062
|
+
if (!gasless) {
|
|
2063
|
+
throw new Error(GASLESS_MISSING_ENV_ERROR);
|
|
2064
|
+
}
|
|
2065
|
+
return {
|
|
2066
|
+
eoa: address,
|
|
2067
|
+
smartAccount: gasless.account
|
|
2068
|
+
};
|
|
2069
|
+
}
|
|
1982
2070
|
async function buildCliMoneyOSConfig(config, options = {}) {
|
|
1983
2071
|
const moneyosConfig = {
|
|
1984
2072
|
chainId: options.chainId ?? config.chainId ?? 42161,
|
|
@@ -1998,9 +2086,7 @@ async function buildCliMoneyOSConfig(config, options = {}) {
|
|
|
1998
2086
|
});
|
|
1999
2087
|
if (!gasless) {
|
|
2000
2088
|
if (gaslessEnabled) {
|
|
2001
|
-
throw new Error(
|
|
2002
|
-
"Gasless mode is enabled but required environment variables are missing. Set MONEYOS_GASLESS_RELAY_URL, MONEYOS_GASLESS_ACCOUNT, and MONEYOS_GASLESS_SPONSOR."
|
|
2003
|
-
);
|
|
2089
|
+
throw new Error(GASLESS_MISSING_ENV_ERROR);
|
|
2004
2090
|
}
|
|
2005
2091
|
return {
|
|
2006
2092
|
...moneyosConfig,
|
|
@@ -2059,6 +2145,28 @@ async function buildCliMoneyOSConfig(config, options = {}) {
|
|
|
2059
2145
|
}
|
|
2060
2146
|
|
|
2061
2147
|
// src/cli/commands/balance.ts
|
|
2148
|
+
function shortenAddress(address) {
|
|
2149
|
+
return `${address.slice(0, 6)}\u2026${address.slice(-4)}`;
|
|
2150
|
+
}
|
|
2151
|
+
function formatTargetLabel(target) {
|
|
2152
|
+
return `${target.label} (${shortenAddress(target.address)}):`;
|
|
2153
|
+
}
|
|
2154
|
+
function targetLineWidth(targets) {
|
|
2155
|
+
return Math.max(...targets.map((target) => formatTargetLabel(target).length));
|
|
2156
|
+
}
|
|
2157
|
+
async function resolveBalanceTargets(config, chainId, address) {
|
|
2158
|
+
if (address) {
|
|
2159
|
+
return [{ address }];
|
|
2160
|
+
}
|
|
2161
|
+
const resolved = await resolveCliOwnedAddresses(config, { chainId });
|
|
2162
|
+
if (resolved.smartAccount && resolved.smartAccount.toLowerCase() !== resolved.eoa.toLowerCase()) {
|
|
2163
|
+
return [
|
|
2164
|
+
{ label: "EOA", address: resolved.eoa },
|
|
2165
|
+
{ label: "Smart account", address: resolved.smartAccount }
|
|
2166
|
+
];
|
|
2167
|
+
}
|
|
2168
|
+
return [{ address: resolved.eoa }];
|
|
2169
|
+
}
|
|
2062
2170
|
var balanceCommand = new Command2("balance").description("Check token balance").argument("[token]", "Token symbol (e.g. USDC, ETH, RYZE). Omit with --all.").option("-a, --address <address>", "Address to check (defaults to your own)").option("-c, --chain <chainId>", "Chain ID (default: 42161 Arbitrum)").option("--all", "Show balances for every built-in token on the selected chain").action(async (token, options) => {
|
|
2063
2171
|
if (options.all && token !== void 0) {
|
|
2064
2172
|
console.error("Cannot combine a token argument with --all.");
|
|
@@ -2071,17 +2179,15 @@ var balanceCommand = new Command2("balance").description("Check token balance").
|
|
|
2071
2179
|
return;
|
|
2072
2180
|
}
|
|
2073
2181
|
const config = loadConfig();
|
|
2074
|
-
const chainId = options.chain ? parseInt(options.chain) : config.chainId;
|
|
2075
|
-
|
|
2182
|
+
const chainId = options.chain ? parseInt(options.chain) : config.chainId ?? 42161;
|
|
2183
|
+
const address = options.address;
|
|
2076
2184
|
let moneyos;
|
|
2185
|
+
let targets;
|
|
2077
2186
|
try {
|
|
2078
|
-
|
|
2079
|
-
const resolved = await loadCliAddress(config);
|
|
2080
|
-
address = resolved.address;
|
|
2081
|
-
}
|
|
2187
|
+
targets = await resolveBalanceTargets(config, chainId, address);
|
|
2082
2188
|
moneyos = new MoneyOS(
|
|
2083
2189
|
await buildCliMoneyOSConfig(config, {
|
|
2084
|
-
chainId
|
|
2190
|
+
chainId,
|
|
2085
2191
|
requireSigner: false
|
|
2086
2192
|
})
|
|
2087
2193
|
);
|
|
@@ -2093,40 +2199,62 @@ var balanceCommand = new Command2("balance").description("Check token balance").
|
|
|
2093
2199
|
return;
|
|
2094
2200
|
}
|
|
2095
2201
|
if (options.all) {
|
|
2096
|
-
const
|
|
2097
|
-
const candidates = listTokens(resolvedChainId);
|
|
2202
|
+
const candidates = listTokens(chainId);
|
|
2098
2203
|
if (candidates.length === 0) {
|
|
2099
2204
|
console.error(
|
|
2100
|
-
`No built-in tokens registered on chain ${
|
|
2205
|
+
`No built-in tokens registered on chain ${chainId}.`
|
|
2101
2206
|
);
|
|
2102
2207
|
process.exitCode = 1;
|
|
2103
2208
|
return;
|
|
2104
2209
|
}
|
|
2105
|
-
const results = await Promise.allSettled(
|
|
2106
|
-
candidates.map(
|
|
2107
|
-
(t) => moneyos.balance(t.symbol, { address, chainId: resolvedChainId })
|
|
2108
|
-
)
|
|
2109
|
-
);
|
|
2110
|
-
const width = Math.max(...candidates.map((t) => t.symbol.length));
|
|
2111
2210
|
let anyFailed = false;
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
console.log(
|
|
2116
|
-
}
|
|
2211
|
+
for (const [index, target] of targets.entries()) {
|
|
2212
|
+
if (target.label) {
|
|
2213
|
+
if (index > 0) console.log("");
|
|
2214
|
+
console.log(formatTargetLabel(target));
|
|
2215
|
+
}
|
|
2216
|
+
const results2 = await Promise.allSettled(
|
|
2217
|
+
candidates.map(
|
|
2218
|
+
(candidate) => moneyos.balance(candidate.symbol, { address: target.address, chainId })
|
|
2219
|
+
)
|
|
2220
|
+
);
|
|
2221
|
+
const width2 = Math.max(...candidates.map((candidate) => candidate.symbol.length));
|
|
2222
|
+
results2.forEach((result, resultIndex) => {
|
|
2223
|
+
const symbol = candidates[resultIndex].symbol.padEnd(width2);
|
|
2224
|
+
if (result.status === "fulfilled") {
|
|
2225
|
+
console.log(`${symbol} ${result.value.amount}`);
|
|
2226
|
+
return;
|
|
2227
|
+
}
|
|
2117
2228
|
anyFailed = true;
|
|
2118
|
-
const message =
|
|
2229
|
+
const message = result.reason instanceof Error ? result.reason.message : String(result.reason);
|
|
2119
2230
|
console.log(`${symbol} error: ${message}`);
|
|
2120
|
-
}
|
|
2121
|
-
}
|
|
2231
|
+
});
|
|
2232
|
+
}
|
|
2122
2233
|
if (anyFailed) process.exitCode = 1;
|
|
2123
2234
|
return;
|
|
2124
2235
|
}
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2236
|
+
if (targets.length === 1) {
|
|
2237
|
+
const result = await moneyos.balance(token, {
|
|
2238
|
+
address: targets[0].address,
|
|
2239
|
+
chainId
|
|
2240
|
+
});
|
|
2241
|
+
console.log(`${result.amount} ${result.symbol}`);
|
|
2242
|
+
return;
|
|
2243
|
+
}
|
|
2244
|
+
const width = targetLineWidth(targets);
|
|
2245
|
+
const results = await Promise.all(
|
|
2246
|
+
targets.map(
|
|
2247
|
+
(target) => moneyos.balance(token, {
|
|
2248
|
+
address: target.address,
|
|
2249
|
+
chainId
|
|
2250
|
+
})
|
|
2251
|
+
)
|
|
2252
|
+
);
|
|
2253
|
+
results.forEach((result, index) => {
|
|
2254
|
+
console.log(
|
|
2255
|
+
`${formatTargetLabel(targets[index]).padEnd(width)} ${result.symbol} ${result.amount}`
|
|
2256
|
+
);
|
|
2128
2257
|
});
|
|
2129
|
-
console.log(`${result.amount} ${result.symbol}`);
|
|
2130
2258
|
});
|
|
2131
2259
|
|
|
2132
2260
|
// src/cli/commands/send.ts
|
|
@@ -2695,7 +2823,7 @@ contactCommand.command("remove").description("Remove a saved contact").argument(
|
|
|
2695
2823
|
|
|
2696
2824
|
// src/cli/commands/gasless.ts
|
|
2697
2825
|
import { Command as Command8 } from "commander";
|
|
2698
|
-
import { getGaslessNetworkDefaults as getGaslessNetworkDefaults2 } from "@moneyos/
|
|
2826
|
+
import { getGaslessNetworkDefaults as getGaslessNetworkDefaults2 } from "@moneyos/smart-account";
|
|
2699
2827
|
function formatEnabled(enabled) {
|
|
2700
2828
|
return enabled ? "enabled" : "disabled";
|
|
2701
2829
|
}
|