@fluxa-pay/fluxa-wallet 0.2.0 → 0.2.1

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.
Files changed (2) hide show
  1. package/bin/fluxa-wallet.js +235 -9
  2. package/package.json +1 -1
@@ -5,6 +5,23 @@ var AGENT_ID_API = process.env.AGENT_ID_API || "https://agentid.fluxapay.xyz";
5
5
  var WALLET_API = process.env.WALLET_API || "https://walletapi.fluxapay.xyz";
6
6
  var WALLET_APP = process.env.WALLET_APP || "https://wallet.fluxapay.xyz";
7
7
  var JWT_EXPIRY_BUFFER_SECONDS = 300;
8
+ var SUPPORTED_CURRENCIES = ["USDC", "XRP", "FLUXA_MONETIZE_CREDITS"];
9
+ var CURRENCY_ALIASES = {
10
+ "usdc": "USDC",
11
+ "xrp": "XRP",
12
+ "fluxa_monetize_credits": "FLUXA_MONETIZE_CREDITS",
13
+ "fluxa-monetize-credits": "FLUXA_MONETIZE_CREDITS",
14
+ "fluxa-monetize-credit": "FLUXA_MONETIZE_CREDITS",
15
+ "fluxa_monetize_credit": "FLUXA_MONETIZE_CREDITS",
16
+ "credits": "FLUXA_MONETIZE_CREDITS"
17
+ };
18
+ function resolveCurrency(input) {
19
+ if (SUPPORTED_CURRENCIES.includes(input)) {
20
+ return input;
21
+ }
22
+ const alias = CURRENCY_ALIASES[input.toLowerCase()];
23
+ return alias ?? null;
24
+ }
8
25
  var WalletApiError = class extends Error {
9
26
  status;
10
27
  details;
@@ -111,9 +128,13 @@ function extractHost(url) {
111
128
  }
112
129
  function getCurrencyFromAsset(assetAddress, network) {
113
130
  const normalizedAddress = assetAddress.toLowerCase();
114
- if (normalizedAddress === "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913" && network === "base") {
131
+ const normalizedNetwork = network.toLowerCase();
132
+ if (normalizedAddress === "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913" && (normalizedNetwork === "base" || normalizedNetwork === "eip155:8453")) {
115
133
  return "USDC";
116
134
  }
135
+ if (normalizedNetwork === "fluxa-monetize-credits" || normalizedNetwork.startsWith("fluxa-monetize")) {
136
+ return "FLUXA_MONETIZE_CREDITS";
137
+ }
117
138
  return "USDC";
118
139
  }
119
140
  function parseJWT(jwt) {
@@ -511,7 +532,7 @@ OPTIONS FOR 'mandate-create':
511
532
  --amount <amount> Budget limit in atomic units (required)
512
533
  --seconds <duration> Validity duration in seconds (default: 28800 = 8 hours)
513
534
  --category <category> Category (default: general)
514
- --currency <currency> Currency (default: USDC)
535
+ --currency <currency> Currency (default: USDC). Supported: USDC, XRP, FLUXA_MONETIZE_CREDITS
515
536
 
516
537
  OPTIONS FOR 'mandate-status':
517
538
  --id <mandate_id> Mandate ID to query (required)
@@ -592,8 +613,13 @@ EXAMPLES:
592
613
  function parseArgs(args) {
593
614
  const command = args[0] || "help";
594
615
  const options = {};
616
+ let helpRequested = false;
595
617
  for (let i = 1; i < args.length; i++) {
596
618
  const arg = args[i];
619
+ if (arg === "--help" || arg === "-h") {
620
+ helpRequested = true;
621
+ continue;
622
+ }
597
623
  if (arg.startsWith("--")) {
598
624
  const key = arg.slice(2);
599
625
  const value = args[i + 1];
@@ -605,8 +631,162 @@ function parseArgs(args) {
605
631
  }
606
632
  }
607
633
  }
608
- return { command, options };
634
+ return { command, options, helpRequested };
609
635
  }
636
+ var COMMAND_USAGE = {
637
+ status: `Usage: fluxa-wallet status
638
+
639
+ Check agent configuration status. No options required.
640
+
641
+ Example:
642
+ fluxa-wallet status`,
643
+ init: `Usage: fluxa-wallet init [options]
644
+
645
+ Initialize/register agent ID.
646
+
647
+ Options:
648
+ --name <name> Agent name (or set AGENT_NAME env var)
649
+ --client <info> Client info description (or set CLIENT_INFO env var)
650
+
651
+ Example:
652
+ fluxa-wallet init --name "My Agent" --client "CLI v1.0"`,
653
+ payout: `Usage: fluxa-wallet payout [options]
654
+
655
+ Create a payout to send funds to a wallet address.
656
+
657
+ Options:
658
+ --to <address> Recipient address (required)
659
+ --amount <amount> Amount in smallest units (required)
660
+ --id <payout_id> Unique payout ID (required)
661
+ --network <network> Network (default: base)
662
+ --asset <address> Asset contract address (default: USDC on Base)
663
+
664
+ Example:
665
+ fluxa-wallet payout --to 0x1234...abcd --amount 1000000 --id pay_001`,
666
+ "payout-status": `Usage: fluxa-wallet payout-status --id <payout_id>
667
+
668
+ Query payout status.
669
+
670
+ Options:
671
+ --id <payout_id> Payout ID to query (required)
672
+
673
+ Example:
674
+ fluxa-wallet payout-status --id pay_001`,
675
+ x402: `Usage: fluxa-wallet x402 --payload <json>
676
+
677
+ Generate x402 payment header (v1).
678
+
679
+ Options:
680
+ --payload <json> Full x402 payment payload as JSON (required)
681
+
682
+ Example:
683
+ fluxa-wallet x402 --payload '{"accepts":[{...}]}'`,
684
+ "mandate-create": `Usage: fluxa-wallet mandate-create [options]
685
+
686
+ Create an intent mandate for x402 v3 payments.
687
+
688
+ Options:
689
+ --desc <text> Natural language description (required)
690
+ --amount <amount> Budget limit in atomic units (required)
691
+ --seconds <duration> Validity duration in seconds (default: 28800 = 8h)
692
+ --category <category> Category (default: general)
693
+ --currency <currency> Currency (default: USDC)
694
+
695
+ Supported currencies: USDC, XRP, FLUXA_MONETIZE_CREDITS
696
+ Aliases accepted: credits, fluxa-monetize-credits, fluxa-monetize-credit
697
+
698
+ Examples:
699
+ fluxa-wallet mandate-create --desc "Spend up to 0.1 USDC" --amount 100000
700
+ fluxa-wallet mandate-create --desc "Spend credits" --amount 500 --currency FLUXA_MONETIZE_CREDITS`,
701
+ "mandate-status": `Usage: fluxa-wallet mandate-status --id <mandate_id>
702
+
703
+ Query mandate status.
704
+
705
+ Options:
706
+ --id <mandate_id> Mandate ID to query (required). Use --id, NOT --mandate.
707
+
708
+ Example:
709
+ fluxa-wallet mandate-status --id mand_xxxxxxxxxxxxx`,
710
+ "x402-v3": `Usage: fluxa-wallet x402-v3 --mandate <mandate_id> --payload <json>
711
+
712
+ Generate x402 v3 payment using an intent mandate.
713
+
714
+ Options:
715
+ --mandate <mandate_id> Mandate ID (required)
716
+ --payload <json> Complete HTTP 402 response body (required, must include accepts array)
717
+
718
+ The command automatically matches the accepts entry to the mandate's currency.
719
+ If the 402 response contains multiple accepts (e.g., USDC + credits), only the
720
+ entry matching the mandate currency will be used.
721
+
722
+ Example:
723
+ fluxa-wallet x402-v3 --mandate mand_xxx --payload '{"accepts":[{...}]}'`,
724
+ "paymentlink-create": `Usage: fluxa-wallet paymentlink-create [options]
725
+
726
+ Create a payment link.
727
+
728
+ Options:
729
+ --amount <amount> Amount in smallest units (required)
730
+ --desc <text> Description
731
+ --resource <content> Resource content
732
+ --expires <iso8601> Expiry date (ISO 8601)
733
+ --max-uses <number> Maximum number of uses
734
+ --network <network> Network (default: base)
735
+
736
+ Example:
737
+ fluxa-wallet paymentlink-create --amount 1000000 --desc "Test payment"`,
738
+ "paymentlink-list": `Usage: fluxa-wallet paymentlink-list [options]
739
+
740
+ List payment links.
741
+
742
+ Options:
743
+ --limit <number> Max number of results
744
+
745
+ Example:
746
+ fluxa-wallet paymentlink-list --limit 10`,
747
+ "paymentlink-get": `Usage: fluxa-wallet paymentlink-get --id <link_id>
748
+
749
+ Get payment link details.
750
+
751
+ Options:
752
+ --id <link_id> Payment link ID (required)
753
+
754
+ Example:
755
+ fluxa-wallet paymentlink-get --id lnk_xxxxx`,
756
+ "paymentlink-update": `Usage: fluxa-wallet paymentlink-update --id <link_id> [options]
757
+
758
+ Update a payment link.
759
+
760
+ Options:
761
+ --id <link_id> Payment link ID (required)
762
+ --desc <text> New description
763
+ --resource <content> New resource content
764
+ --status <status> Status: active or disabled
765
+ --expires <iso8601> New expiry date (ISO 8601), "null" to clear
766
+ --max-uses <number> New max uses, "null" to clear
767
+
768
+ Example:
769
+ fluxa-wallet paymentlink-update --id lnk_xxx --status disabled`,
770
+ "paymentlink-delete": `Usage: fluxa-wallet paymentlink-delete --id <link_id>
771
+
772
+ Delete a payment link.
773
+
774
+ Options:
775
+ --id <link_id> Payment link ID (required)
776
+
777
+ Example:
778
+ fluxa-wallet paymentlink-delete --id lnk_xxxxx`,
779
+ "paymentlink-payments": `Usage: fluxa-wallet paymentlink-payments --id <link_id> [options]
780
+
781
+ Get payment records for a payment link.
782
+
783
+ Options:
784
+ --id <link_id> Payment link ID (required)
785
+ --limit <number> Max number of results
786
+
787
+ Example:
788
+ fluxa-wallet paymentlink-payments --id lnk_xxxxx --limit 10`
789
+ };
610
790
  function output(result) {
611
791
  console.log(JSON.stringify(result, null, 2));
612
792
  }
@@ -813,13 +993,20 @@ async function cmdX402(options) {
813
993
  error: 'FluxA Agent ID not initialized. Run "init" first.'
814
994
  };
815
995
  }
816
- const accept = payload.accepts?.[0];
817
- if (!accept) {
996
+ const accepts = payload.accepts;
997
+ if (!Array.isArray(accepts) || accepts.length === 0) {
818
998
  return {
819
999
  success: false,
820
1000
  error: "Invalid payload: missing accepts array"
821
1001
  };
822
1002
  }
1003
+ const accept = accepts.find((a) => a.scheme === "exact") || accepts[0];
1004
+ if (!accept) {
1005
+ return {
1006
+ success: false,
1007
+ error: "Invalid payload: no usable accepts entry found"
1008
+ };
1009
+ }
823
1010
  const request = {
824
1011
  scheme: accept.scheme || "exact",
825
1012
  network: accept.network || DEFAULT_NETWORK,
@@ -862,13 +1049,20 @@ async function cmdMandateCreate(options) {
862
1049
  const limitAmount = options.amount;
863
1050
  const validForSeconds = options.seconds;
864
1051
  const category = options.category || DEFAULT_MANDATE_CATEGORY;
865
- const currency = options.currency || "USDC";
1052
+ const rawCurrency = options.currency || "USDC";
1053
+ const currency = resolveCurrency(rawCurrency);
866
1054
  if (!description || !limitAmount) {
867
1055
  return {
868
1056
  success: false,
869
1057
  error: "Missing required parameters: --desc, --amount"
870
1058
  };
871
1059
  }
1060
+ if (!currency) {
1061
+ return {
1062
+ success: false,
1063
+ error: `Unsupported currency: "${rawCurrency}". Supported currencies: ${SUPPORTED_CURRENCIES.join(", ")}`
1064
+ };
1065
+ }
872
1066
  if (!/^\d+$/.test(limitAmount)) {
873
1067
  return {
874
1068
  success: false,
@@ -983,13 +1177,36 @@ async function cmdX402V3(options) {
983
1177
  error: 'FluxA Agent ID not initialized. Run "init" first.'
984
1178
  };
985
1179
  }
986
- const accept = payload.accepts?.[0];
987
- if (!accept) {
1180
+ const accepts = payload.accepts;
1181
+ if (!Array.isArray(accepts) || accepts.length === 0) {
988
1182
  return {
989
1183
  success: false,
990
1184
  error: "Invalid payload: missing accepts array"
991
1185
  };
992
1186
  }
1187
+ let mandateCurrency = "USDC";
1188
+ try {
1189
+ const mandateInfo = await getMandateStatus(mandateId, auth.jwt);
1190
+ if (mandateInfo.mandate?.currency) {
1191
+ mandateCurrency = mandateInfo.mandate.currency;
1192
+ }
1193
+ } catch (err) {
1194
+ console.error("[cli] Could not fetch mandate currency, defaulting to USDC:", err?.message);
1195
+ }
1196
+ const accept = accepts.find((a) => {
1197
+ if (a.scheme !== "exact") return false;
1198
+ const currency = getCurrencyFromAsset(a.asset || DEFAULT_ASSET, a.network || DEFAULT_NETWORK);
1199
+ return currency === mandateCurrency;
1200
+ });
1201
+ if (!accept) {
1202
+ const availableCurrencies = accepts.map(
1203
+ (a) => getCurrencyFromAsset(a.asset || DEFAULT_ASSET, a.network || DEFAULT_NETWORK)
1204
+ );
1205
+ return {
1206
+ success: false,
1207
+ error: `No accepts entry matches mandate currency "${mandateCurrency}". Available currencies in accepts: [${availableCurrencies.join(", ")}]`
1208
+ };
1209
+ }
993
1210
  try {
994
1211
  const result = await requestX402V3Payment(
995
1212
  {
@@ -1148,7 +1365,16 @@ async function cmdPaymentLinkPayments(options) {
1148
1365
  }
1149
1366
  async function main() {
1150
1367
  const args = process.argv.slice(2);
1151
- const { command, options } = parseArgs(args);
1368
+ const { command, options, helpRequested } = parseArgs(args);
1369
+ if (helpRequested && command !== "help" && command !== "--help" && command !== "-h") {
1370
+ const usage = COMMAND_USAGE[command];
1371
+ if (usage) {
1372
+ console.log(usage);
1373
+ process.exit(0);
1374
+ }
1375
+ printUsage();
1376
+ process.exit(0);
1377
+ }
1152
1378
  ensureDataDirs();
1153
1379
  await loadConfig();
1154
1380
  let result;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluxa-pay/fluxa-wallet",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "FluxA Agent Wallet CLI — payments, payouts, and payment links for AI agents",
5
5
  "type": "module",
6
6
  "bin": {