@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.
- package/bin/fluxa-wallet.js +235 -9
- package/package.json +1 -1
package/bin/fluxa-wallet.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
817
|
-
if (!
|
|
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
|
|
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
|
|
987
|
-
if (!
|
|
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;
|