@heyamiko/amiko-cli 0.2.3 → 0.3.0
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 +87 -137
- package/dist/index.js +264 -82
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Amiko CLI
|
|
2
2
|
|
|
3
|
-
Manage agents, wallets, credits, and
|
|
3
|
+
Manage agents, wallets, credits, and the MPP marketplace from your terminal. Works for both human users and AI agents running on OpenClaw.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -19,38 +19,34 @@ amiko update
|
|
|
19
19
|
## Quick Start
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
# Connect your account
|
|
23
|
-
amiko connect
|
|
22
|
+
# Connect your account
|
|
23
|
+
amiko connect <CODE> # paste code from Amiko settings
|
|
24
|
+
amiko connect amk_<key> # or use your API key directly
|
|
25
|
+
amiko connect # or open browser to sign in
|
|
24
26
|
|
|
25
|
-
#
|
|
26
|
-
amiko browse
|
|
27
|
-
|
|
28
|
-
# Call an agent (auto-pays via Tempo or API key)
|
|
29
|
-
amiko call titan-research "Summarize the latest news on AI agents"
|
|
30
|
-
|
|
31
|
-
# Check credits and wallet balances
|
|
27
|
+
# Check your balance
|
|
32
28
|
amiko credits balance
|
|
33
29
|
|
|
34
|
-
# Top up credits from agent wallet
|
|
35
|
-
amiko credits topup 10000 --token AMIKO
|
|
30
|
+
# Top up credits from your agent's wallet
|
|
31
|
+
amiko credits topup 10000 --token AMIKO --yes
|
|
32
|
+
|
|
33
|
+
# Browse and call marketplace agents
|
|
34
|
+
amiko browse
|
|
35
|
+
amiko call titan-research "Summarize the latest AI news"
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
##
|
|
38
|
+
## Connect
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
Three ways to authenticate:
|
|
41
41
|
|
|
42
42
|
```bash
|
|
43
|
-
#
|
|
44
|
-
amiko connect
|
|
45
|
-
|
|
46
|
-
# URL flow (for agents on OpenClaw)
|
|
47
|
-
amiko connect <url> # paste connect link from Amiko settings
|
|
48
|
-
|
|
49
|
-
# Legacy Privy login (marketplace features)
|
|
50
|
-
amiko login # sign in via browser
|
|
51
|
-
amiko login --no-browser # print login URL instead
|
|
43
|
+
amiko connect <CODE> # 7-char code from platform settings (recommended)
|
|
44
|
+
amiko connect amk_<key> # API key (shown once at creation)
|
|
45
|
+
amiko connect # browser sign-in flow
|
|
52
46
|
```
|
|
53
47
|
|
|
48
|
+
The connect code is the simplest — generate one from your Amiko settings page, paste it to the agent or terminal.
|
|
49
|
+
|
|
54
50
|
```bash
|
|
55
51
|
amiko whoami # show current auth status
|
|
56
52
|
amiko logout # clear stored credentials
|
|
@@ -58,177 +54,131 @@ amiko logout # clear stored credentials
|
|
|
58
54
|
|
|
59
55
|
## Credits
|
|
60
56
|
|
|
61
|
-
Manage platform credits — check balance and top up from agent wallets.
|
|
62
|
-
|
|
63
57
|
```bash
|
|
64
|
-
amiko credits balance #
|
|
65
|
-
amiko credits topup <amount> # top up credits (amount in credits)
|
|
58
|
+
amiko credits balance # credit balance + wallet balances across all chains
|
|
59
|
+
amiko credits topup <amount> # top up credits (amount in credits, e.g. 10000)
|
|
66
60
|
```
|
|
67
61
|
|
|
68
62
|
**Top-up options:**
|
|
69
63
|
|
|
70
64
|
```bash
|
|
71
|
-
amiko credits topup 10000
|
|
72
|
-
amiko credits topup 10000 --token AMIKO
|
|
73
|
-
amiko credits topup 10000 --token USDC --chain base
|
|
74
|
-
amiko credits topup 5000 --method mpp
|
|
75
|
-
amiko credits topup 10000 --
|
|
65
|
+
amiko credits topup 10000 # auto-select best wallet + token
|
|
66
|
+
amiko credits topup 10000 --token AMIKO # use AMIKO (Solana)
|
|
67
|
+
amiko credits topup 10000 --token USDC --chain base # use USDC on Base
|
|
68
|
+
amiko credits topup 5000 --method mpp # use MPP 402 payment
|
|
69
|
+
amiko credits topup 10000 --wallet Gu2b...QVya # specific wallet address
|
|
70
|
+
amiko credits topup 10000 --yes # skip confirmation
|
|
76
71
|
```
|
|
77
72
|
|
|
73
|
+
**How it works:**
|
|
74
|
+
1. CLI fetches live token price from Jupiter
|
|
75
|
+
2. Transfers tokens from your Crossmint agent wallet to the treasury via billing API
|
|
76
|
+
3. Verifies the on-chain transfer and credits your account
|
|
77
|
+
4. All calls go through `billing.heyamiko.com` — no other dependencies
|
|
78
|
+
|
|
78
79
|
**Supported tokens:** AMIKO, SOL, USDC, USDT, ETH
|
|
79
80
|
**Supported chains:** Solana, Base, Ethereum, Tempo
|
|
80
81
|
|
|
81
|
-
|
|
82
|
-
- `crossmint` — transfer from agent Crossmint wallet to treasury (default)
|
|
83
|
-
- `mpp` — auto-pay via `@solana/mpp` SDK (402 challenge flow)
|
|
84
|
-
- `auto` — try crossmint first, fall back to mpp
|
|
85
|
-
|
|
86
|
-
## Wallet Management
|
|
82
|
+
## Wallet
|
|
87
83
|
|
|
88
84
|
```bash
|
|
89
85
|
amiko wallet create # create MPP wallet on Tempo
|
|
90
86
|
amiko wallet balance [address] # check USDC.e balance
|
|
91
|
-
amiko wallet balance --watch # poll
|
|
92
|
-
amiko wallet topup <amount> #
|
|
93
|
-
amiko wallet
|
|
94
|
-
amiko wallet
|
|
95
|
-
amiko wallet
|
|
96
|
-
amiko wallet whoami # show Tempo wallet identity
|
|
87
|
+
amiko wallet balance --watch # poll every 5s
|
|
88
|
+
amiko wallet topup <amount> # Stripe checkout ($1-$100)
|
|
89
|
+
amiko wallet deposit [address] # USDC.e deposit instructions
|
|
90
|
+
amiko wallet login # Tempo wallet login
|
|
91
|
+
amiko wallet whoami # Tempo wallet identity
|
|
97
92
|
amiko wallet fund # fund via Tempo dashboard
|
|
98
93
|
```
|
|
99
94
|
|
|
100
95
|
## Marketplace
|
|
101
96
|
|
|
102
97
|
```bash
|
|
103
|
-
amiko browse # browse
|
|
104
|
-
amiko browse -c research
|
|
105
|
-
amiko
|
|
106
|
-
amiko browse -q "image gen" # search by keyword
|
|
107
|
-
amiko info <agent> # show agent details + pricing
|
|
98
|
+
amiko browse # browse agents
|
|
99
|
+
amiko browse -c research -l 10 # filter by category
|
|
100
|
+
amiko info <agent> # agent details + pricing
|
|
108
101
|
amiko popular # trending agents
|
|
109
|
-
amiko
|
|
110
|
-
amiko
|
|
111
|
-
amiko leaderboard # top creators by revenue
|
|
102
|
+
amiko activity # recent payments
|
|
103
|
+
amiko leaderboard # top creators
|
|
112
104
|
```
|
|
113
105
|
|
|
114
106
|
## Calling Agents
|
|
115
107
|
|
|
116
108
|
```bash
|
|
117
|
-
amiko call
|
|
118
|
-
|
|
119
|
-
amiko call
|
|
120
|
-
amiko call
|
|
121
|
-
amiko call
|
|
122
|
-
amiko call titan-research "hello" --raw # raw JSON output
|
|
123
|
-
amiko call titan-research "hello" --no-tempo # force API key
|
|
109
|
+
amiko call <agent> "message" # single message
|
|
110
|
+
amiko call <agent> -i # interactive REPL
|
|
111
|
+
echo "input" | amiko call <agent> # pipe input
|
|
112
|
+
amiko call <agent> "msg" --task # task endpoint
|
|
113
|
+
amiko call <agent> "msg" --dry-run # preview cost
|
|
124
114
|
```
|
|
125
115
|
|
|
126
116
|
## Creator Dashboard
|
|
127
117
|
|
|
128
|
-
Requires authentication (`amiko login`).
|
|
129
|
-
|
|
130
118
|
```bash
|
|
131
|
-
amiko creator summary # earnings
|
|
132
|
-
amiko creator listings #
|
|
133
|
-
amiko creator publish <id> # publish a draft
|
|
119
|
+
amiko creator summary # earnings + listings
|
|
120
|
+
amiko creator listings # your agent listings
|
|
121
|
+
amiko creator publish <id> # publish a draft
|
|
134
122
|
amiko creator payout # request payout
|
|
135
123
|
```
|
|
136
124
|
|
|
137
|
-
##
|
|
125
|
+
## Other Commands
|
|
138
126
|
|
|
139
127
|
```bash
|
|
140
|
-
amiko reputation
|
|
141
|
-
amiko
|
|
128
|
+
amiko reputation [address] # TARS score
|
|
129
|
+
amiko discover # MPP service info
|
|
130
|
+
amiko ping # health check
|
|
131
|
+
amiko bridge quote 5 # cross-chain bridge quote
|
|
132
|
+
amiko config show # view config
|
|
133
|
+
amiko config set <key> <value> # set config value
|
|
134
|
+
amiko update # update CLI to latest
|
|
142
135
|
```
|
|
143
136
|
|
|
144
|
-
##
|
|
145
|
-
|
|
146
|
-
```bash
|
|
147
|
-
amiko discover # MPP service info + endpoints
|
|
148
|
-
amiko ping # health check with latency
|
|
149
|
-
```
|
|
137
|
+
## Agent Integration (OpenClaw)
|
|
150
138
|
|
|
151
|
-
|
|
139
|
+
Agents install the CLI and connect with a code from the user:
|
|
152
140
|
|
|
153
141
|
```bash
|
|
154
|
-
|
|
155
|
-
amiko
|
|
156
|
-
amiko
|
|
142
|
+
npm install -g @heyamiko/amiko-cli
|
|
143
|
+
amiko connect <CODE>
|
|
144
|
+
amiko credits balance
|
|
145
|
+
amiko credits topup 10000 --token AMIKO --yes
|
|
157
146
|
```
|
|
158
147
|
|
|
159
|
-
|
|
148
|
+
The CLI auto-detects `.amiko.json` (synced by the platform) when running on an agent.
|
|
160
149
|
|
|
161
|
-
|
|
150
|
+
## Configuration
|
|
162
151
|
|
|
163
|
-
|
|
164
|
-
amiko config show # display configuration
|
|
165
|
-
amiko config set <key> <value> # set a value
|
|
166
|
-
amiko config reset # reset to defaults
|
|
167
|
-
amiko config path # print config file path
|
|
168
|
-
```
|
|
152
|
+
Config: `~/.amiko/config.json`
|
|
169
153
|
|
|
170
154
|
| Key | Default |
|
|
171
155
|
|-----|---------|
|
|
172
|
-
| `apiBase` | `https://mpp.amikomarkets.com` |
|
|
173
156
|
| `billingBase` | `https://billing.heyamiko.com` |
|
|
174
|
-
| `
|
|
175
|
-
| `
|
|
176
|
-
|
|
177
|
-
## Agent Integration (OpenClaw)
|
|
178
|
-
|
|
179
|
-
Agents running on OpenClaw can install and use the CLI to manage credits:
|
|
180
|
-
|
|
181
|
-
```bash
|
|
182
|
-
# 1. User generates connect link from Amiko settings
|
|
183
|
-
# 2. Agent runs:
|
|
184
|
-
amiko connect https://app.heyamiko.com/api/cli/connect/redeem?code=abc123
|
|
185
|
-
|
|
186
|
-
# 3. Agent can now top up credits:
|
|
187
|
-
amiko credits topup 10000 --token AMIKO --yes
|
|
188
|
-
|
|
189
|
-
# Or check balances:
|
|
190
|
-
amiko credits balance
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
The CLI auto-detects `.amiko.json` (synced by the platform) for twin token auth when running on an agent.
|
|
194
|
-
|
|
195
|
-
## Development
|
|
196
|
-
|
|
197
|
-
```bash
|
|
198
|
-
bun install # install dependencies
|
|
199
|
-
bun run dev # run without building
|
|
200
|
-
bun run build # compile to dist/
|
|
201
|
-
bun run typecheck # type-check
|
|
202
|
-
bun test # run tests
|
|
203
|
-
```
|
|
157
|
+
| `apiBase` | `https://mpp.amikomarkets.com` |
|
|
158
|
+
| `siteBase` | `https://platform.heyamiko.com` |
|
|
204
159
|
|
|
205
160
|
## Architecture
|
|
206
161
|
|
|
207
162
|
```
|
|
208
163
|
src/
|
|
209
|
-
├── index.ts
|
|
210
|
-
├── onboarding.ts
|
|
164
|
+
├── index.ts # entry point
|
|
165
|
+
├── onboarding.ts # first-run setup
|
|
211
166
|
├── commands/
|
|
212
|
-
│ ├──
|
|
213
|
-
│ ├──
|
|
214
|
-
│ ├──
|
|
215
|
-
│ ├──
|
|
216
|
-
│ ├── wallet.ts
|
|
217
|
-
│ ├── creator.ts
|
|
218
|
-
│ ├──
|
|
219
|
-
│ ├──
|
|
220
|
-
│
|
|
221
|
-
│ ├── marketplace.ts # activity, leaderboard, popular
|
|
222
|
-
│ ├── login.ts # login, logout, whoami
|
|
223
|
-
│ ├── bridge.ts # cross-chain bridge
|
|
224
|
-
│ └── update.ts # self-update
|
|
167
|
+
│ ├── connect.ts # connect (code, API key, browser)
|
|
168
|
+
│ ├── credits.ts # credits balance + topup
|
|
169
|
+
│ ├── browse.ts # marketplace browsing
|
|
170
|
+
│ ├── call.ts # call agents
|
|
171
|
+
│ ├── wallet.ts # MPP wallet management
|
|
172
|
+
│ ├── creator.ts # creator dashboard
|
|
173
|
+
│ ├── login.ts # Privy browser login
|
|
174
|
+
│ ├── update.ts # self-update
|
|
175
|
+
│ └── ...
|
|
225
176
|
└── lib/
|
|
226
|
-
├──
|
|
227
|
-
├── config.ts
|
|
228
|
-
├──
|
|
229
|
-
├── mpp-topup.ts
|
|
230
|
-
|
|
231
|
-
└── tempo.ts # Tempo CLI detection
|
|
177
|
+
├── config.ts # ~/.amiko/config.json
|
|
178
|
+
├── agent-config.ts # .amiko.json reader
|
|
179
|
+
├── api.ts # HTTP client
|
|
180
|
+
├── mpp-topup.ts # MPP SDK helper
|
|
181
|
+
└── ...
|
|
232
182
|
```
|
|
233
183
|
|
|
234
184
|
Built with [Commander](https://github.com/tj/commander.js), [chalk](https://github.com/chalk/chalk), [ora](https://github.com/sindresorhus/ora), and [@solana/mpp](https://github.com/solana-foundation/mpp-sdk). Bundled with [Bun](https://bun.sh).
|
package/dist/index.js
CHANGED
|
@@ -23311,7 +23311,7 @@ var CONFIG_FILE = join(CONFIG_DIR, "config.json");
|
|
|
23311
23311
|
var DEFAULTS = {
|
|
23312
23312
|
apiBase: "https://mpp.amikomarkets.com",
|
|
23313
23313
|
billingBase: "https://billing.heyamiko.com",
|
|
23314
|
-
siteBase: "https://
|
|
23314
|
+
siteBase: "https://platform.heyamiko.com"
|
|
23315
23315
|
};
|
|
23316
23316
|
var LEGACY_SITE_BASES = new Set([
|
|
23317
23317
|
"https://amiko-markets.vercel.app",
|
|
@@ -23418,6 +23418,7 @@ var SKIP_COMMANDS = new Set([
|
|
|
23418
23418
|
"config",
|
|
23419
23419
|
"login",
|
|
23420
23420
|
"logout",
|
|
23421
|
+
"whoami",
|
|
23421
23422
|
"connect",
|
|
23422
23423
|
"credits",
|
|
23423
23424
|
"update"
|
|
@@ -23436,7 +23437,7 @@ async function runOnboarding(argv) {
|
|
|
23436
23437
|
if (cmd && SKIP_COMMANDS.has(cmd))
|
|
23437
23438
|
return false;
|
|
23438
23439
|
const config = loadConfig();
|
|
23439
|
-
if (config.wallet || config.privyToken || config.apiKey)
|
|
23440
|
+
if (config.wallet || config.privyToken || config.apiKey || config.twinToken || config.agentWallets?.length)
|
|
23440
23441
|
return false;
|
|
23441
23442
|
console.log("");
|
|
23442
23443
|
console.log(heading("Welcome to Amiko CLI"));
|
|
@@ -25336,11 +25337,14 @@ var VALID_KEYS = [
|
|
|
25336
25337
|
"apiBase",
|
|
25337
25338
|
"billingBase",
|
|
25338
25339
|
"siteBase",
|
|
25340
|
+
"platformUrl",
|
|
25339
25341
|
"wallet",
|
|
25340
25342
|
"apiKey",
|
|
25341
25343
|
"privyToken",
|
|
25342
25344
|
"creatorToken",
|
|
25343
25345
|
"userId",
|
|
25346
|
+
"twinId",
|
|
25347
|
+
"twinToken",
|
|
25344
25348
|
"connectedKeyId",
|
|
25345
25349
|
"connectedKeyName",
|
|
25346
25350
|
"connectedKeyPreview"
|
|
@@ -25657,6 +25661,18 @@ function registerLoginCommand(program2) {
|
|
|
25657
25661
|
console.log(heading("Amiko Login"));
|
|
25658
25662
|
console.log(dim(`Authenticate your CLI with your Amiko account.
|
|
25659
25663
|
`));
|
|
25664
|
+
const isHeadless = !process.stdout.isTTY || !process.env.DISPLAY && process.platform === "linux";
|
|
25665
|
+
if (isHeadless) {
|
|
25666
|
+
console.log(source_default.yellow("⚠ No browser available in this environment."));
|
|
25667
|
+
console.log("");
|
|
25668
|
+
console.log(dim("For agents and headless environments, use connect instead:"));
|
|
25669
|
+
console.log("");
|
|
25670
|
+
console.log(source_default.cyan(" amiko connect <CODE>"));
|
|
25671
|
+
console.log("");
|
|
25672
|
+
console.log(dim("Generate a connect code from your Amiko settings page,"));
|
|
25673
|
+
console.log(dim("then run the command above with the code."));
|
|
25674
|
+
process.exit(0);
|
|
25675
|
+
}
|
|
25660
25676
|
if (existingToken) {
|
|
25661
25677
|
console.log(dim("Already signed in."));
|
|
25662
25678
|
if (config.userId)
|
|
@@ -26386,28 +26402,84 @@ function printSuccess(data) {
|
|
|
26386
26402
|
console.log(success("Account connected. You can now run: amiko credits topup <amount>"));
|
|
26387
26403
|
}
|
|
26388
26404
|
function saveCredentials(data) {
|
|
26389
|
-
|
|
26390
|
-
|
|
26391
|
-
|
|
26392
|
-
|
|
26393
|
-
|
|
26394
|
-
|
|
26405
|
+
const update = {};
|
|
26406
|
+
if (data.userId)
|
|
26407
|
+
update.userId = data.userId;
|
|
26408
|
+
if (data.platformUrl)
|
|
26409
|
+
update.platformUrl = data.platformUrl;
|
|
26410
|
+
if (data.billingBase)
|
|
26411
|
+
update.billingBase = data.billingBase;
|
|
26412
|
+
if (data.twinId)
|
|
26413
|
+
update.twinId = data.twinId;
|
|
26414
|
+
if (data.twinToken)
|
|
26415
|
+
update.twinToken = data.twinToken;
|
|
26416
|
+
if (data.privyToken)
|
|
26417
|
+
update.privyToken = data.privyToken;
|
|
26418
|
+
if (data.connectedKeyId)
|
|
26419
|
+
update.connectedKeyId = data.connectedKeyId;
|
|
26420
|
+
if (data.connectedKeyPreview)
|
|
26421
|
+
update.connectedKeyPreview = data.connectedKeyPreview;
|
|
26422
|
+
if (data.connectedKeyName)
|
|
26423
|
+
update.connectedKeyName = data.connectedKeyName;
|
|
26424
|
+
if (data.wallets)
|
|
26425
|
+
update.agentWallets = data.wallets;
|
|
26426
|
+
saveConfig(update);
|
|
26395
26427
|
}
|
|
26396
26428
|
function registerConnectCommand(program2) {
|
|
26397
26429
|
program2.command("connect").description("Connect to an Amiko account (opens browser, or pass a connect URL)").argument("[url]", "Connect URL from Amiko settings (optional — opens browser if omitted)").option("--no-browser", "Print the connect URL instead of opening a browser").action(async (urlStr, opts) => {
|
|
26398
26430
|
if (urlStr) {
|
|
26431
|
+
const input = urlStr.trim();
|
|
26432
|
+
if (input.startsWith("amk_")) {
|
|
26433
|
+
const spinner3 = ora("Connecting with API key...").start();
|
|
26434
|
+
try {
|
|
26435
|
+
const config2 = loadConfig();
|
|
26436
|
+
const billingBase2 = config2.billingBase || "https://billing.heyamiko.com";
|
|
26437
|
+
const res = await fetch(`${billingBase2}/api/auth/bootstrap`, {
|
|
26438
|
+
headers: { Authorization: `Bearer ${input}` }
|
|
26439
|
+
});
|
|
26440
|
+
if (!res.ok) {
|
|
26441
|
+
spinner3.stop();
|
|
26442
|
+
const err = await res.json().catch(() => ({ error: "Invalid API key" }));
|
|
26443
|
+
console.error(error(err.error || `Authentication failed: ${res.status}`));
|
|
26444
|
+
process.exit(1);
|
|
26445
|
+
}
|
|
26446
|
+
const data = await res.json();
|
|
26447
|
+
spinner3.stop();
|
|
26448
|
+
saveConfig({
|
|
26449
|
+
apiKey: input,
|
|
26450
|
+
userId: data.userId,
|
|
26451
|
+
connectedKeyId: data.connectedKey?.id,
|
|
26452
|
+
connectedKeyName: data.connectedKey?.name,
|
|
26453
|
+
connectedKeyPreview: data.connectedKey?.keyPreview
|
|
26454
|
+
});
|
|
26455
|
+
console.log(heading("Connected"));
|
|
26456
|
+
console.log("");
|
|
26457
|
+
console.log(label("User", data.userId));
|
|
26458
|
+
if (data.connectedKey) {
|
|
26459
|
+
console.log(label("Key", `${data.connectedKey.name} (${data.connectedKey.keyPreview})`));
|
|
26460
|
+
}
|
|
26461
|
+
console.log(label("Credits", Number(data.credits?.balance || 0).toLocaleString()));
|
|
26462
|
+
console.log("");
|
|
26463
|
+
console.log(success("Account connected via API key."));
|
|
26464
|
+
} catch (err) {
|
|
26465
|
+
spinner3.stop();
|
|
26466
|
+
console.error(error(err instanceof Error ? err.message : "Failed to connect"));
|
|
26467
|
+
process.exit(1);
|
|
26468
|
+
}
|
|
26469
|
+
return;
|
|
26470
|
+
}
|
|
26399
26471
|
const spinner2 = ora("Connecting...").start();
|
|
26400
26472
|
try {
|
|
26401
26473
|
let code;
|
|
26402
26474
|
let redeemOrigin;
|
|
26403
26475
|
try {
|
|
26404
|
-
const url = new URL(
|
|
26405
|
-
code = url.searchParams.get("code") ||
|
|
26476
|
+
const url = new URL(input);
|
|
26477
|
+
code = url.searchParams.get("code") || input;
|
|
26406
26478
|
redeemOrigin = url.origin;
|
|
26407
26479
|
} catch {
|
|
26408
|
-
code =
|
|
26480
|
+
code = input;
|
|
26409
26481
|
const config2 = loadConfig();
|
|
26410
|
-
redeemOrigin = config2.
|
|
26482
|
+
redeemOrigin = config2.billingBase || "https://billing.heyamiko.com";
|
|
26411
26483
|
}
|
|
26412
26484
|
if (!code) {
|
|
26413
26485
|
spinner2.stop();
|
|
@@ -26439,7 +26511,7 @@ function registerConnectCommand(program2) {
|
|
|
26439
26511
|
}
|
|
26440
26512
|
const config = loadConfig();
|
|
26441
26513
|
const state = randomBytes2(16).toString("hex");
|
|
26442
|
-
const platformUrl = config.platformUrl || process.env.AMIKO_PLATFORM_URL || "https://
|
|
26514
|
+
const platformUrl = config.platformUrl || process.env.AMIKO_PLATFORM_URL || "https://platform.heyamiko.com";
|
|
26443
26515
|
console.log(heading("Amiko Connect"));
|
|
26444
26516
|
console.log(dim(`Connect your CLI to your Amiko account.
|
|
26445
26517
|
`));
|
|
@@ -26508,7 +26580,7 @@ function loadAgentConfig() {
|
|
|
26508
26580
|
return null;
|
|
26509
26581
|
}
|
|
26510
26582
|
function resolveAuth(cliConfig) {
|
|
26511
|
-
if (cliConfig.
|
|
26583
|
+
if (cliConfig.agentWallets?.length) {
|
|
26512
26584
|
return {
|
|
26513
26585
|
mode: "connected",
|
|
26514
26586
|
platformUrl: cliConfig.platformUrl,
|
|
@@ -26516,6 +26588,7 @@ function resolveAuth(cliConfig) {
|
|
|
26516
26588
|
twinId: cliConfig.twinId,
|
|
26517
26589
|
twinToken: cliConfig.twinToken,
|
|
26518
26590
|
platformKey: cliConfig.apiKey,
|
|
26591
|
+
privyToken: cliConfig.privyToken,
|
|
26519
26592
|
connectedKeyId: cliConfig.connectedKeyId,
|
|
26520
26593
|
userId: cliConfig.userId,
|
|
26521
26594
|
agentWallets: cliConfig.agentWallets
|
|
@@ -26526,6 +26599,7 @@ function resolveAuth(cliConfig) {
|
|
|
26526
26599
|
mode: "connected",
|
|
26527
26600
|
billingBase: cliConfig.billingBase,
|
|
26528
26601
|
platformKey: cliConfig.privyToken,
|
|
26602
|
+
privyToken: cliConfig.privyToken,
|
|
26529
26603
|
connectedKeyId: cliConfig.connectedKeyId,
|
|
26530
26604
|
userId: cliConfig.userId
|
|
26531
26605
|
};
|
|
@@ -26621,23 +26695,32 @@ function registerCreditsCommand(program2) {
|
|
|
26621
26695
|
spinner.stop();
|
|
26622
26696
|
console.log(heading("Credits"));
|
|
26623
26697
|
console.log("");
|
|
26624
|
-
|
|
26698
|
+
{
|
|
26625
26699
|
const spinner2 = ora("Fetching credit balance...").start();
|
|
26626
26700
|
try {
|
|
26627
|
-
|
|
26628
|
-
|
|
26629
|
-
|
|
26630
|
-
|
|
26631
|
-
|
|
26632
|
-
|
|
26633
|
-
|
|
26634
|
-
}
|
|
26635
|
-
|
|
26636
|
-
|
|
26637
|
-
|
|
26638
|
-
|
|
26639
|
-
|
|
26701
|
+
let creditsData = null;
|
|
26702
|
+
if (auth.billingBase && auth.platformKey) {
|
|
26703
|
+
const res = await fetch(`${auth.billingBase}/api/credits`, {
|
|
26704
|
+
headers: { Authorization: `Bearer ${auth.platformKey}` }
|
|
26705
|
+
});
|
|
26706
|
+
if (res.ok)
|
|
26707
|
+
creditsData = await res.json();
|
|
26708
|
+
}
|
|
26709
|
+
if (!creditsData && auth.platformUrl && auth.twinId && auth.twinToken) {
|
|
26710
|
+
const res = await fetch(`${auth.platformUrl}/api/agents/${auth.twinId}/credits/balance`, {
|
|
26711
|
+
headers: { Authorization: `Bearer ${auth.twinToken}` }
|
|
26712
|
+
});
|
|
26713
|
+
if (res.ok) {
|
|
26714
|
+
const data = await res.json();
|
|
26715
|
+
creditsData = { balance: data.balance };
|
|
26640
26716
|
}
|
|
26717
|
+
}
|
|
26718
|
+
spinner2.stop();
|
|
26719
|
+
if (creditsData) {
|
|
26720
|
+
console.log(label("Balance", source_default.bold(Number(creditsData.balance || 0).toLocaleString())));
|
|
26721
|
+
console.log("");
|
|
26722
|
+
} else {
|
|
26723
|
+
console.log(dim(" Could not fetch credit balance"));
|
|
26641
26724
|
console.log("");
|
|
26642
26725
|
}
|
|
26643
26726
|
} catch (err) {
|
|
@@ -26664,10 +26747,44 @@ function registerCreditsCommand(program2) {
|
|
|
26664
26747
|
} else {
|
|
26665
26748
|
console.log(label("Agent Wallets", ""));
|
|
26666
26749
|
for (const w of wallets) {
|
|
26667
|
-
const
|
|
26668
|
-
const
|
|
26669
|
-
const
|
|
26670
|
-
|
|
26750
|
+
const rawChain = w.chain ?? "?";
|
|
26751
|
+
const isEvm = ["base", "ethereum", "tempo"].includes(rawChain);
|
|
26752
|
+
const chainLabel = isEvm ? "EVM (Ethereum · Base · Tempo)" : rawChain.charAt(0).toUpperCase() + rawChain.slice(1);
|
|
26753
|
+
const addr = w.wallet_address || "";
|
|
26754
|
+
const shortAddr = addr ? `${addr.slice(0, 6)}...${addr.slice(-4)}` : "";
|
|
26755
|
+
console.log(` ${source_default.bold(chainLabel)} ${dim(shortAddr)}`);
|
|
26756
|
+
let bals = w.balance && typeof w.balance === "object" ? w.balance : null;
|
|
26757
|
+
if (!bals) {
|
|
26758
|
+
try {
|
|
26759
|
+
const balRes = await fetch(`${auth.platformUrl}/api/agents/${auth.twinId}/wallets/${addr}/balance`, { headers: { Authorization: `Bearer ${auth.twinToken}` } });
|
|
26760
|
+
if (balRes.ok) {
|
|
26761
|
+
const balData = await balRes.json();
|
|
26762
|
+
if (balData.chains) {
|
|
26763
|
+
for (const [chainName, chainBals] of Object.entries(balData.chains)) {
|
|
26764
|
+
const chainLabel2 = chainName.charAt(0).toUpperCase() + chainName.slice(1);
|
|
26765
|
+
console.log(dim(` ${chainLabel2}:`));
|
|
26766
|
+
for (const [token, tData] of Object.entries(chainBals)) {
|
|
26767
|
+
const human = parseFloat(tData.amount) / Math.pow(10, tData.decimals);
|
|
26768
|
+
console.log(dim(` ${token.padEnd(8)} ${human.toFixed(6)}`));
|
|
26769
|
+
}
|
|
26770
|
+
}
|
|
26771
|
+
continue;
|
|
26772
|
+
}
|
|
26773
|
+
bals = balData.balances || {};
|
|
26774
|
+
}
|
|
26775
|
+
} catch {
|
|
26776
|
+
console.log(dim(" (balance unavailable)"));
|
|
26777
|
+
continue;
|
|
26778
|
+
}
|
|
26779
|
+
}
|
|
26780
|
+
if (bals) {
|
|
26781
|
+
for (const [token, data2] of Object.entries(bals)) {
|
|
26782
|
+
const human = parseFloat(data2.amount) / Math.pow(10, data2.decimals);
|
|
26783
|
+
if (human > 0 || ["sol", "eth", "usdc", "amiko"].includes(token.toLowerCase())) {
|
|
26784
|
+
console.log(dim(` ${token.padEnd(10)} ${human.toFixed(6)}`));
|
|
26785
|
+
}
|
|
26786
|
+
}
|
|
26787
|
+
}
|
|
26671
26788
|
}
|
|
26672
26789
|
}
|
|
26673
26790
|
console.log("");
|
|
@@ -26697,11 +26814,18 @@ function registerCreditsCommand(program2) {
|
|
|
26697
26814
|
console.error(error("Not connected"));
|
|
26698
26815
|
process.exit(1);
|
|
26699
26816
|
}
|
|
26700
|
-
if (!auth.
|
|
26817
|
+
if (!auth.billingBase) {
|
|
26701
26818
|
spinner.stop();
|
|
26702
|
-
console.error(error("
|
|
26819
|
+
console.error(error("Billing service not configured. Run: amiko connect"));
|
|
26703
26820
|
process.exit(1);
|
|
26704
26821
|
}
|
|
26822
|
+
const authToken = auth.platformKey || auth.privyToken;
|
|
26823
|
+
if (!authToken) {
|
|
26824
|
+
spinner.stop();
|
|
26825
|
+
console.error(error("No API key or auth token. Run: amiko connect"));
|
|
26826
|
+
process.exit(1);
|
|
26827
|
+
}
|
|
26828
|
+
const authHeaders2 = { Authorization: `Bearer ${authToken}`, "Content-Type": "application/json" };
|
|
26705
26829
|
spinner.stop();
|
|
26706
26830
|
if (!options2.yes) {
|
|
26707
26831
|
console.log(warn(`About to top up ${credits2} credits.`));
|
|
@@ -26709,74 +26833,132 @@ function registerCreditsCommand(program2) {
|
|
|
26709
26833
|
console.log("");
|
|
26710
26834
|
}
|
|
26711
26835
|
if (options2.method === "mpp" && auth.userId && auth.connectedKeyId) {
|
|
26712
|
-
const
|
|
26836
|
+
const spinner2 = ora("Topping up credits via MPP...").start();
|
|
26713
26837
|
const mppResult = await mppCreditsTopup({
|
|
26714
26838
|
userId: auth.userId,
|
|
26715
26839
|
keyId: auth.connectedKeyId,
|
|
26716
26840
|
amount: credits2 / 1e4
|
|
26717
26841
|
});
|
|
26718
|
-
|
|
26842
|
+
spinner2.stop();
|
|
26719
26843
|
if (!mppResult.success) {
|
|
26720
26844
|
console.error(error(mppResult.error || "MPP top-up failed"));
|
|
26721
26845
|
process.exit(1);
|
|
26722
26846
|
}
|
|
26723
|
-
console.log(heading("Top-up Complete"));
|
|
26847
|
+
console.log(heading("Top-up Complete (MPP)"));
|
|
26724
26848
|
console.log("");
|
|
26725
|
-
if (mppResult.credits?.
|
|
26726
|
-
console.log(label("
|
|
26727
|
-
|
|
26728
|
-
if (mppResult.credits?.balance !== undefined) {
|
|
26729
|
-
console.log(label("New Balance", `${mppResult.credits.balance} credits`));
|
|
26730
|
-
}
|
|
26731
|
-
console.log("");
|
|
26732
|
-
console.log(success("Credits topped up successfully via MPP."));
|
|
26849
|
+
if (mppResult.credits?.balance)
|
|
26850
|
+
console.log(label("Balance", mppResult.credits.balance));
|
|
26851
|
+
console.log(success("Credits topped up via MPP."));
|
|
26733
26852
|
return;
|
|
26734
26853
|
}
|
|
26735
|
-
const
|
|
26736
|
-
const
|
|
26737
|
-
|
|
26738
|
-
|
|
26739
|
-
if (
|
|
26740
|
-
|
|
26741
|
-
|
|
26742
|
-
|
|
26743
|
-
|
|
26744
|
-
|
|
26745
|
-
|
|
26746
|
-
|
|
26854
|
+
const agentWallet = auth.agentWallets?.find((w) => w.source === "agent");
|
|
26855
|
+
const walletAddr = options2.wallet || agentWallet?.address || auth.agentWallets?.[0]?.address;
|
|
26856
|
+
const walletChain = options2.chain || auth.agentWallets?.find((w) => w.address === walletAddr)?.chain || "solana";
|
|
26857
|
+
const token = options2.token || "AMIKO";
|
|
26858
|
+
if (!walletAddr) {
|
|
26859
|
+
console.error(error("No wallet found. Specify --wallet <address>"));
|
|
26860
|
+
process.exit(1);
|
|
26861
|
+
}
|
|
26862
|
+
const usdAmount = credits2 / 1e4;
|
|
26863
|
+
let tokenAmount;
|
|
26864
|
+
const stablecoins = ["usdc", "usdt", "usdc.e", "usdt0"];
|
|
26865
|
+
if (stablecoins.includes(token.toLowerCase())) {
|
|
26866
|
+
tokenAmount = usdAmount;
|
|
26867
|
+
} else {
|
|
26868
|
+
const spinner2 = ora(`Fetching ${token} price...`).start();
|
|
26869
|
+
try {
|
|
26870
|
+
const MINTS = {
|
|
26871
|
+
AMIKO: "AY1Ww6MxwC3cCiyrandHqLrp4FXvzgcwQTZpJ2FEpump",
|
|
26872
|
+
SOL: "So11111111111111111111111111111111111111112"
|
|
26873
|
+
};
|
|
26874
|
+
const USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
|
|
26875
|
+
const mint = MINTS[token.toUpperCase()];
|
|
26876
|
+
if (!mint) {
|
|
26877
|
+
spinner2.stop();
|
|
26878
|
+
console.error(error(`Unknown token: ${token}`));
|
|
26879
|
+
process.exit(1);
|
|
26880
|
+
}
|
|
26881
|
+
const decimals = token.toUpperCase() === "SOL" ? 9 : 6;
|
|
26882
|
+
const oneToken = Math.pow(10, decimals).toString();
|
|
26883
|
+
const jupRes = await fetch(`https://lite-api.jup.ag/swap/v1/quote?inputMint=${mint}&outputMint=${USDC_MINT}&amount=${oneToken}&slippageBps=100`);
|
|
26884
|
+
if (!jupRes.ok) {
|
|
26885
|
+
spinner2.stop();
|
|
26886
|
+
console.error(error("Failed to fetch token price"));
|
|
26887
|
+
process.exit(1);
|
|
26888
|
+
}
|
|
26889
|
+
const jupData = await jupRes.json();
|
|
26890
|
+
const pricePerToken = parseFloat(jupData.outAmount) / 1e6;
|
|
26891
|
+
tokenAmount = usdAmount / pricePerToken;
|
|
26892
|
+
spinner2.stop();
|
|
26893
|
+
console.log(label("Price", `1 ${token} = $${pricePerToken.toFixed(4)}`));
|
|
26894
|
+
console.log(label("Cost", `${tokenAmount.toFixed(6)} ${token} (~$${usdAmount.toFixed(2)})`));
|
|
26895
|
+
console.log("");
|
|
26896
|
+
} catch {
|
|
26897
|
+
spinner2.stop();
|
|
26898
|
+
console.error(error("Failed to fetch token price"));
|
|
26899
|
+
process.exit(1);
|
|
26900
|
+
}
|
|
26901
|
+
}
|
|
26902
|
+
const TREASURY = "FPiZAf3jEnNfCwfvbv46jdPfHbmSepD4Q6iHiLJDQXvb";
|
|
26903
|
+
const spinner3 = ora("Transferring tokens to treasury...").start();
|
|
26904
|
+
const transferRes = await fetch(`${auth.billingBase}/api/crossmint/wallets/${encodeURIComponent(walletAddr)}/transfer`, {
|
|
26747
26905
|
method: "POST",
|
|
26748
|
-
headers:
|
|
26749
|
-
|
|
26750
|
-
|
|
26751
|
-
|
|
26752
|
-
|
|
26906
|
+
headers: authHeaders2,
|
|
26907
|
+
body: JSON.stringify({
|
|
26908
|
+
to: TREASURY,
|
|
26909
|
+
amount: tokenAmount.toFixed(6),
|
|
26910
|
+
token,
|
|
26911
|
+
chain: walletChain
|
|
26912
|
+
})
|
|
26753
26913
|
});
|
|
26754
|
-
|
|
26755
|
-
|
|
26756
|
-
const err = await
|
|
26757
|
-
console.error(error(err.error || `
|
|
26914
|
+
if (!transferRes.ok) {
|
|
26915
|
+
spinner3.stop();
|
|
26916
|
+
const err = await transferRes.json().catch(() => ({ error: "Transfer failed" }));
|
|
26917
|
+
console.error(error(err.error || `Transfer failed: ${transferRes.status}`));
|
|
26758
26918
|
process.exit(1);
|
|
26759
26919
|
}
|
|
26760
|
-
const
|
|
26761
|
-
|
|
26762
|
-
|
|
26763
|
-
if (
|
|
26764
|
-
console.
|
|
26765
|
-
|
|
26766
|
-
if (data.tokenAmount !== undefined) {
|
|
26767
|
-
console.log(label("Token Amount", `${data.tokenAmount}${data.token ? ` ${data.token}` : ""}`));
|
|
26920
|
+
const transferData = await transferRes.json();
|
|
26921
|
+
const txHash = transferData.txHash;
|
|
26922
|
+
spinner3.stop();
|
|
26923
|
+
if (!txHash) {
|
|
26924
|
+
console.error(error("Transfer sent but no transaction hash returned."));
|
|
26925
|
+
process.exit(1);
|
|
26768
26926
|
}
|
|
26769
|
-
|
|
26770
|
-
|
|
26927
|
+
console.log(label("Tx Hash", dim(txHash.slice(0, 16) + "...")));
|
|
26928
|
+
const keyId = auth.connectedKeyId;
|
|
26929
|
+
if (!keyId) {
|
|
26930
|
+
console.log(warn("No connected API key — transfer sent but credits not verified."));
|
|
26931
|
+
console.log(dim(`Tx: ${txHash}`));
|
|
26932
|
+
process.exit(0);
|
|
26771
26933
|
}
|
|
26772
|
-
|
|
26773
|
-
|
|
26934
|
+
const spinner4 = ora("Verifying and crediting...").start();
|
|
26935
|
+
const verifyRes = await fetch(`${auth.billingBase}/api/user/keys/${keyId}/topup/wallet`, {
|
|
26936
|
+
method: "POST",
|
|
26937
|
+
headers: authHeaders2,
|
|
26938
|
+
body: JSON.stringify({
|
|
26939
|
+
txSignature: txHash,
|
|
26940
|
+
amount: tokenAmount,
|
|
26941
|
+
token: token.toUpperCase()
|
|
26942
|
+
})
|
|
26943
|
+
});
|
|
26944
|
+
spinner4.stop();
|
|
26945
|
+
if (!verifyRes.ok) {
|
|
26946
|
+
const err = await verifyRes.json().catch(() => ({ error: "Verify failed" }));
|
|
26947
|
+
console.error(error(err.error || "Transfer sent but credit verification failed."));
|
|
26948
|
+
console.log(dim(`Tx: ${txHash}`));
|
|
26949
|
+
process.exit(1);
|
|
26774
26950
|
}
|
|
26775
|
-
|
|
26776
|
-
|
|
26951
|
+
const verifyData = await verifyRes.json();
|
|
26952
|
+
console.log(heading("Top-up Complete"));
|
|
26953
|
+
console.log("");
|
|
26954
|
+
console.log(label("Credits", source_default.bold(credits2.toLocaleString())));
|
|
26955
|
+
console.log(label("Token", `${tokenAmount.toFixed(6)} ${token}`));
|
|
26956
|
+
console.log(label("USD", `$${usdAmount.toFixed(2)}`));
|
|
26957
|
+
if (verifyData.credits?.balance) {
|
|
26958
|
+
console.log(label("Balance", source_default.bold(Number(verifyData.credits.balance).toLocaleString())));
|
|
26777
26959
|
}
|
|
26778
26960
|
console.log("");
|
|
26779
|
-
console.log(success("Credits topped up
|
|
26961
|
+
console.log(success("Credits topped up."));
|
|
26780
26962
|
} catch (err) {
|
|
26781
26963
|
spinner.stop();
|
|
26782
26964
|
console.error(error(err instanceof Error ? err.message : "Failed to top up credits"));
|
|
@@ -26837,7 +27019,7 @@ var didOnboard = await runOnboarding(process.argv);
|
|
|
26837
27019
|
if (didOnboard)
|
|
26838
27020
|
process.exit(0);
|
|
26839
27021
|
var program2 = new Command;
|
|
26840
|
-
program2.name("amiko").description("Amiko CLI — manage agents, wallets, credits, and
|
|
27022
|
+
program2.name("amiko").description("Amiko CLI — manage agents, wallets, credits, and the MPP marketplace").version("0.3.0");
|
|
26841
27023
|
registerBrowseCommand(program2);
|
|
26842
27024
|
registerCallCommand(program2);
|
|
26843
27025
|
registerWalletCommand(program2);
|