@thirdfy/agent-cli 0.1.28 → 0.1.31

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 CHANGED
@@ -4,6 +4,26 @@ All notable changes to `@thirdfy/agent-cli` are documented here. The format is b
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.1.31] - 2026-05-07
8
+
9
+ ### Fixed
10
+
11
+ - **Swap amounts (self / build-tx / execute-intent):** When using `amountInHuman` + `tokenInDecimals`, prepared params now set canonical `amountIn` to the **human decimal** string (matching `amountInRaw` normalization). Previously `amountIn` incorrectly carried base-unit raw integers, which could mis-size swaps outside the managed-wallet execute path.
12
+
13
+ ## [0.1.30] - 2026-05-07
14
+
15
+ ### Fixed
16
+
17
+ - **Swap amounts:** `amountInRaw` now requires `tokenInDecimals`; without it the CLI errors instead of sending base units as a human `amountIn` (catastrophic mis-size risk).
18
+ - **Managed wallet payload:** Legacy `amountIn` is treated as a **human decimal** string (API contract); base units require `amountInRaw` + `tokenInDecimals`.
19
+ - **Managed wallet payload:** `legacy_human` path strips `tokenInDecimals` from the execute payload for consistency.
20
+
21
+ ## [0.1.29] - 2026-05-07
22
+
23
+ ### Fixed
24
+
25
+ - **Managed wallet swaps:** Normalize `amountInRaw` / `amountInHuman` into the single human `amountIn` field required by Thirdfy managed-wallet swap execution, preventing ambiguous amount payloads for `agent_wallet` agents.
26
+
7
27
  ## [0.1.28] - 2026-05-05
8
28
 
9
29
  ### Added
package/README.md CHANGED
@@ -40,7 +40,7 @@ npx @thirdfy/agent-cli --help
40
40
 
41
41
  ## Release notes
42
42
 
43
- Version history and highlights: [CHANGELOG.md](./CHANGELOG.md). Recent CLI releases document provider discovery parity, metadata-first `actions --provider` filtering, earn deposit guards, portfolio analytics commands, and README refresh through **v0.1.28**.
43
+ Version history and highlights: [CHANGELOG.md](./CHANGELOG.md). Highlights through **v0.1.31** include provider discovery parity, portfolio analytics, managed-wallet swap normalization, and **self/build-tx** swap human-decimal `amountIn` parity when using `amountInHuman` + `tokenInDecimals`.
44
44
 
45
45
  **Maintainers — npm:** follow [docs/releasing.md](./docs/releasing.md). From a clone with gitignored `.env`, use `npm run publish:npm:local -- --dry-run` then `npm run publish:npm:local`. Or run `npm run release:npm` after exporting tokens in the shell. Never commit npm tokens — use [.env.example](./.env.example) as a template only.
46
46
 
@@ -53,8 +53,8 @@ export THIRDFY_OWNER_SESSION_TOKEN="..."
53
53
 
54
54
  thirdfy-agent actions --agent-api-key "$AGENT_API_KEY" --json
55
55
  thirdfy-agent profile init --profile personal --json
56
- thirdfy-agent preflight --agent-api-key "$AGENT_API_KEY" --action swap --params '{"tokenIn":"0x...","tokenOut":"0x...","amountInRaw":"1000000"}' --estimated-amount-usd 25 --json
57
- thirdfy-agent run --agent-api-key "$AGENT_API_KEY" --action swap --params '{"tokenIn":"0x...","tokenOut":"0x...","amountInRaw":"1000000"}' --estimated-amount-usd 25 --json
56
+ thirdfy-agent preflight --agent-api-key "$AGENT_API_KEY" --action swap --params '{"tokenIn":"0x...","tokenOut":"0x...","amountInRaw":"1000000","tokenInDecimals":6}' --estimated-amount-usd 25 --json
57
+ thirdfy-agent run --agent-api-key "$AGENT_API_KEY" --action swap --params '{"tokenIn":"0x...","tokenOut":"0x...","amountInRaw":"1000000","tokenInDecimals":6}' --estimated-amount-usd 25 --json
58
58
  thirdfy-agent intent-status --intent-id "<intentId>" --json
59
59
  ```
60
60
 
@@ -189,7 +189,7 @@ thirdfy-agent run \
189
189
  --run-mode self \
190
190
  --broadcast \
191
191
  --action swap \
192
- --params '{"tokenIn":"0x...","tokenOut":"0x...","amountInRaw":"1000000","chainId":8453}' \
192
+ --params '{"tokenIn":"0x...","tokenOut":"0x...","amountInRaw":"1000000","tokenInDecimals":6,"chainId":8453}' \
193
193
  --json
194
194
  ```
195
195
 
@@ -203,7 +203,7 @@ thirdfy-agent run \
203
203
  --run-mode hybrid \
204
204
  --hybrid-wallet-mode agent_wallet \
205
205
  --action swap \
206
- --params '{"tokenIn":"0x...","tokenOut":"0x...","amountInRaw":"1000000","chainId":8453}' \
206
+ --params '{"tokenIn":"0x...","tokenOut":"0x...","amountInRaw":"1000000","tokenInDecimals":6,"chainId":8453}' \
207
207
  --estimated-amount-usd 25 \
208
208
  --json
209
209
  ```
@@ -232,7 +232,7 @@ thirdfy-agent doctor self --json
232
232
  For `--action swap`, CLI enforces an explicit amount unit contract:
233
233
 
234
234
  - Provide exactly one of:
235
- - `amountInRaw` (base units integer string), or
235
+ - `amountInRaw` + `tokenInDecimals` (base units integer string), or
236
236
  - `amountInHuman` + `tokenInDecimals` (CLI converts to `amountInRaw`)
237
237
  - Legacy `amountIn` is accepted only as raw integer compatibility input.
238
238
  - Ambiguous payloads (both/none) fail with `AMOUNT_UNIT_AMBIGUOUS`.
@@ -242,7 +242,7 @@ Examples:
242
242
  ```bash
243
243
  # Raw/base units
244
244
  thirdfy-agent run --agent-api-key "$AGENT_API_KEY" --action swap \
245
- --params '{"tokenIn":"0x...","tokenOut":"0x...","amountInRaw":"1000000","chainId":8453}' --json
245
+ --params '{"tokenIn":"0x...","tokenOut":"0x...","amountInRaw":"1000000","tokenInDecimals":6,"chainId":8453}' --json
246
246
 
247
247
  # Human units + decimals
248
248
  thirdfy-agent run --agent-api-key "$AGENT_API_KEY" --action swap \
@@ -335,7 +335,7 @@ thirdfy-agent delegation redeem \
335
335
  --run-mode thirdfy \
336
336
  --agent-api-key "$AGENT_API_KEY" \
337
337
  --action swap \
338
- --params '{"tokenIn":"0x...","tokenOut":"0x...","amountInRaw":"1000000"}' \
338
+ --params '{"tokenIn":"0x...","tokenOut":"0x...","amountInRaw":"1000000","tokenInDecimals":6}' \
339
339
  --estimated-amount-usd 5 \
340
340
  --json
341
341
  ```
@@ -369,7 +369,7 @@ thirdfy-agent managed wallet init --auth-token "$THIRDFY_AUTH_TOKEN" --json
369
369
  # or: --owner-session-token "$THIRDFY_OWNER_SESSION_TOKEN"
370
370
  thirdfy-agent managed wallet grant --auth-token "$THIRDFY_AUTH_TOKEN" --agent-key "0xYOUR_AGENT_KEY" --token-address "0x..." --max-usd-per-day 250 --json
371
371
  # or: --owner-session-token "$THIRDFY_OWNER_SESSION_TOKEN"
372
- thirdfy-agent agent run --agent-api-key "$AGENT_API_KEY" --signer-method fanout_intent --action swap --params '{"tokenIn":"0x...","tokenOut":"0x...","amountInRaw":"1000000"}' --json
372
+ thirdfy-agent agent run --agent-api-key "$AGENT_API_KEY" --signer-method fanout_intent --action swap --params '{"tokenIn":"0x...","tokenOut":"0x...","amountInRaw":"1000000","tokenInDecimals":6}' --json
373
373
  ```
374
374
 
375
375
  ### Signer command model (managed + BYOW)
@@ -683,6 +683,17 @@ function decimalToRawUnits(amountHuman, decimals) {
683
683
  return (wholePart + fracPart).toString();
684
684
  }
685
685
 
686
+ function rawUnitsToDecimalString(amountRaw, decimals) {
687
+ const raw = normalizeIntegerRawAmount(amountRaw);
688
+ const base = 10n ** BigInt(decimals);
689
+ const n = BigInt(raw);
690
+ const whole = n / base;
691
+ const frac = n % base;
692
+ if (decimals === 0 || frac === 0n) return whole.toString();
693
+ const fracText = frac.toString().padStart(decimals, '0').replace(/0+$/, '');
694
+ return `${whole.toString()}.${fracText}`;
695
+ }
696
+
686
697
  function normalizeSwapAmountContract(params) {
687
698
  const hasRaw = params.amountInRaw !== undefined && params.amountInRaw !== null && String(params.amountInRaw).trim() !== '';
688
699
  const hasHuman = params.amountInHuman !== undefined && params.amountInHuman !== null && String(params.amountInHuman).trim() !== '';
@@ -703,34 +714,58 @@ function normalizeSwapAmountContract(params) {
703
714
 
704
715
  if (hasRaw) {
705
716
  const amountInRaw = normalizeIntegerRawAmount(params.amountInRaw);
717
+ const hasDecimals =
718
+ params.tokenInDecimals !== undefined &&
719
+ params.tokenInDecimals !== null &&
720
+ String(params.tokenInDecimals).trim() !== '';
721
+ if (!hasDecimals) {
722
+ throw createCliError(
723
+ 'AMOUNT_UNIT_DECIMALS_REQUIRED',
724
+ 'amountInRaw requires tokenInDecimals (integer 0-36).'
725
+ );
726
+ }
727
+ const decimals = Number(params.tokenInDecimals);
728
+ if (!Number.isInteger(decimals) || decimals < 0 || decimals > 36) {
729
+ throw createCliError(
730
+ 'AMOUNT_UNIT_DECIMALS_REQUIRED',
731
+ 'amountInRaw requires tokenInDecimals (integer 0-36).'
732
+ );
733
+ }
734
+ const amountInHuman = rawUnitsToDecimalString(amountInRaw, decimals);
706
735
  return {
707
736
  params: {
708
737
  ...params,
709
738
  amountInRaw,
710
- amountIn: amountInRaw,
739
+ amountIn: amountInHuman,
740
+ tokenInDecimals: decimals,
711
741
  },
712
742
  swapInput: {
713
743
  amountInRaw,
714
- amountInHuman: null,
715
- tokenInDecimals: null,
744
+ amountInHuman,
745
+ tokenInDecimals: decimals,
716
746
  unitSource: 'raw',
717
747
  },
718
748
  };
719
749
  }
720
750
 
721
751
  if (hasLegacy) {
722
- const amountInRaw = normalizeIntegerRawAmount(params.amountIn, 'AMOUNT_UNIT_INVALID');
752
+ const amountInHuman = String(params.amountIn).trim();
753
+ if (!/^\d+(\.\d+)?$/.test(amountInHuman)) {
754
+ throw createCliError(
755
+ 'AMOUNT_UNIT_INVALID',
756
+ 'Legacy swap amountIn must be a decimal token-unit string (example: "1.25"). For base units use amountInRaw with tokenInDecimals.'
757
+ );
758
+ }
723
759
  return {
724
760
  params: {
725
761
  ...params,
726
- amountInRaw,
727
- amountIn: amountInRaw,
762
+ amountIn: amountInHuman,
728
763
  },
729
764
  swapInput: {
730
- amountInRaw,
731
- amountInHuman: null,
765
+ amountInRaw: null,
766
+ amountInHuman,
732
767
  tokenInDecimals: null,
733
- unitSource: 'legacy_raw',
768
+ unitSource: 'legacy_human',
734
769
  },
735
770
  };
736
771
  }
@@ -759,7 +794,7 @@ function normalizeSwapAmountContract(params) {
759
794
  ...params,
760
795
  amountInHuman,
761
796
  amountInRaw,
762
- amountIn: amountInRaw,
797
+ amountIn: amountInHuman,
763
798
  tokenInDecimals: decimals,
764
799
  },
765
800
  swapInput: {
@@ -3089,6 +3124,26 @@ function buildManagedExecutePayload(flags, options) {
3089
3124
  const params = getPreparedParams(flags);
3090
3125
  const managedParams = { ...params };
3091
3126
  if (flags.__swapInput?.unitSource === 'human' && flags.__swapInput.amountInHuman) {
3127
+ delete managedParams.amountInRaw;
3128
+ delete managedParams.amountInHuman;
3129
+ delete managedParams.tokenInDecimals;
3130
+ managedParams.amountIn = flags.__swapInput.amountInHuman;
3131
+ } else if (flags.__swapInput?.unitSource === 'raw' && flags.__swapInput.amountInRaw) {
3132
+ const decimals = flags.__swapInput.tokenInDecimals;
3133
+ delete managedParams.amountInHuman;
3134
+ delete managedParams.amountInRaw;
3135
+ delete managedParams.tokenInDecimals;
3136
+ if (!Number.isInteger(decimals) || decimals < 0 || decimals > 36) {
3137
+ throw createCliError(
3138
+ 'AMOUNT_UNIT_DECIMALS_REQUIRED',
3139
+ 'amountInRaw requires tokenInDecimals (integer 0-36).'
3140
+ );
3141
+ }
3142
+ managedParams.amountIn = rawUnitsToDecimalString(flags.__swapInput.amountInRaw, decimals);
3143
+ } else if (flags.__swapInput?.unitSource === 'legacy_human' && flags.__swapInput.amountInHuman) {
3144
+ delete managedParams.amountInRaw;
3145
+ delete managedParams.amountInHuman;
3146
+ delete managedParams.tokenInDecimals;
3092
3147
  managedParams.amountIn = flags.__swapInput.amountInHuman;
3093
3148
  }
3094
3149
  const payload = {
@@ -4133,7 +4188,7 @@ Global flags:
4133
4188
  --profile <name> personal | builder | network
4134
4189
  --env <file> load env vars from file
4135
4190
  --timeout <ms> request timeout
4136
- --params <json> for swap: exactly one of {amountInRaw} or {amountInHuman + tokenInDecimals}
4191
+ --params <json> for swap: amountInRaw + tokenInDecimals, or amountInHuman + tokenInDecimals, or legacy human amountIn (decimal string)
4137
4192
  --broadcast with run --run-mode self, sign and broadcast using OWS
4138
4193
  --user-did <did> required for managed wallet server execution paths
4139
4194
  --allow-wallet-mismatch bypass strict funded-wallet vs execution-wallet guard
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thirdfy/agent-cli",
3
- "version": "0.1.28",
3
+ "version": "0.1.31",
4
4
  "description": "Thirdfy Agent CLI for onboarding, governance preflight, execute-intent, and status polling.",
5
5
  "type": "module",
6
6
  "bin": {