tollkit-wallet 0.2.0 → 0.2.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/README.md +63 -4
- package/THIRD_PARTY_NOTICES.md +8 -0
- package/dist/actions.d.ts +196 -16
- package/dist/actions.js +46 -6
- package/dist/actions.js.map +1 -1
- package/dist/ai-icons.d.ts +5 -0
- package/dist/ai-icons.js +3 -0
- package/dist/ai-icons.js.map +1 -0
- package/dist/ai.d.ts +77 -0
- package/dist/ai.js +227 -0
- package/dist/ai.js.map +1 -0
- package/dist/bridge.d.ts +148 -0
- package/dist/bridge.js +460 -0
- package/dist/bridge.js.map +1 -0
- package/dist/buy.d.ts +17 -0
- package/dist/buy.js +23 -0
- package/dist/buy.js.map +1 -0
- package/dist/cli.js +82 -3
- package/dist/cli.js.map +1 -1
- package/dist/connect.d.ts +29 -0
- package/dist/connect.js +227 -0
- package/dist/connect.js.map +1 -0
- package/dist/dapp.d.ts +89 -0
- package/dist/dapp.js +505 -0
- package/dist/dapp.js.map +1 -0
- package/dist/dashboard.d.ts +5 -0
- package/dist/dashboard.js +203 -2
- package/dist/dashboard.js.map +1 -1
- package/dist/elizaos.js +2 -0
- package/dist/elizaos.js.map +1 -1
- package/dist/holdings.d.ts +92 -0
- package/dist/holdings.js +200 -0
- package/dist/holdings.js.map +1 -0
- package/dist/keystore.d.ts +58 -11
- package/dist/keystore.js +87 -11
- package/dist/keystore.js.map +1 -1
- package/dist/ledger.d.ts +1 -1
- package/dist/mcp.d.ts +7 -2
- package/dist/mcp.js +11 -5
- package/dist/mcp.js.map +1 -1
- package/dist/netguard.d.ts +8 -0
- package/dist/netguard.js +44 -0
- package/dist/netguard.js.map +1 -0
- package/dist/paths.d.ts +5 -0
- package/dist/paths.js +5 -0
- package/dist/paths.js.map +1 -1
- package/dist/policy.d.ts +4 -4
- package/dist/rules.d.ts +11 -2
- package/dist/rules.js +23 -1
- package/dist/rules.js.map +1 -1
- package/dist/sell.d.ts +60 -0
- package/dist/sell.js +71 -0
- package/dist/sell.js.map +1 -0
- package/dist/stake.d.ts +84 -0
- package/dist/stake.js +158 -0
- package/dist/stake.js.map +1 -0
- package/dist/telegram.d.ts +2 -0
- package/dist/telegram.js +4 -0
- package/dist/telegram.js.map +1 -1
- package/dist/ui.js +463 -36
- package/dist/ui.js.map +1 -1
- package/dist/wallet.d.ts +57 -2
- package/dist/wallet.js +185 -4
- package/dist/wallet.js.map +1 -1
- package/extension/PRIVACY.md +19 -0
- package/extension/README.md +16 -0
- package/extension/background.js +88 -0
- package/extension/content.js +34 -0
- package/extension/icons/icon.svg +1 -0
- package/extension/icons/icon128.png +0 -0
- package/extension/icons/icon16.png +0 -0
- package/extension/icons/icon32.png +0 -0
- package/extension/icons/icon48.png +0 -0
- package/extension/inpage.js +129 -0
- package/extension/manifest.json +15 -0
- package/extension/popup.html +35 -0
- package/extension/popup.js +39 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ Swaps cost a flat 0.5%, shown before every trade. On some Base and Ethereum pair
|
|
|
25
25
|
```
|
|
26
26
|
npm install -g tollkit-wallet
|
|
27
27
|
tollkit-wallet init # choose a password; prints your Base/Ethereum and Solana addresses
|
|
28
|
-
tollkit-wallet budget # see limits; change with e.g. budget per_trade_usd=100
|
|
28
|
+
tollkit-wallet budget # see limits; change with e.g. budget per_trade_usd=100 (or in the dashboard's Settings tab)
|
|
29
29
|
tollkit-wallet telegram <bot-token> <chat-id> # optional: approvals in Telegram
|
|
30
30
|
```
|
|
31
31
|
|
|
@@ -56,7 +56,11 @@ The agent has no tool for this.
|
|
|
56
56
|
}
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
Tools: `wallet_status`, `wallet_balances`, `swap_quote`, `swap`, `pay_fetch`, `seller_check`, `receipts`, `autopilot_propose`, `autopilot_rules`, `autopilot_cancel`, `paper_swap`, `paper_status`. There is no tool for changing limits, approvals or keys.
|
|
59
|
+
Tools: `wallet_status`, `wallet_balances`, `swap_quote`, `swap`, `pay_fetch`, `seller_check`, `receipts`, `market_prices`, `price_history`, `autopilot_propose`, `autopilot_rules`, `autopilot_cancel`, `paper_swap`, `paper_status`. There is no tool for changing limits, approvals or keys.
|
|
60
|
+
|
|
61
|
+
The easiest way: open the dashboard (`tollkit-wallet ui`), click **Connect your AI**, type your wallet password and click **Add** next to your app. It finds Claude desktop, Claude Code, Cursor, Codex and Gemini CLI on your computer and adds the wallet to their settings for you (keeping a backup of any file it changes); VS Code opens to confirm. Each app also has the steps to do it by hand.
|
|
62
|
+
|
|
63
|
+
The app needs to unlock the wallet on its own, so adding an app saves your password to `~/.tollkit-wallet/password`, readable only by your user account (or run `tollkit-wallet password-file` to do just that step). Anyone who can read that file and your wallet folder can spend within your limits, so keep both on this computer.
|
|
60
64
|
|
|
61
65
|
## Use with Coinbase AgentKit
|
|
62
66
|
|
|
@@ -69,7 +73,7 @@ const wallet = await TollkitWallet.open(process.env.TOLLKIT_WALLET_PASSWORD!);
|
|
|
69
73
|
const agentkit = await AgentKit.from({ walletProvider, actionProviders: [tollkitWalletActionProvider(wallet)] });
|
|
70
74
|
```
|
|
71
75
|
|
|
72
|
-
This adds `
|
|
76
|
+
This adds the same 14 tools as the MCP server, with a `tollkit_` prefix (`tollkit_swap`, `tollkit_pay_fetch`, `tollkit_autopilot_propose`, …). They use the Tollkit wallet's own keys and limits, whatever AgentKit wallet provider you use.
|
|
73
77
|
|
|
74
78
|
## Use with ElizaOS
|
|
75
79
|
|
|
@@ -80,6 +84,14 @@ import { tollkitWalletPlugin } from "tollkit-wallet/elizaos";
|
|
|
80
84
|
|
|
81
85
|
Set `TOLLKIT_WALLET_PASSWORD` (or `TOLLKIT_WALLET_PASSWORD_FILE`) in the agent's settings or environment. The agent's model reads the request ("swap 25 USDC to SOL"), and the wallet checks it against your limits before anything is signed.
|
|
82
86
|
|
|
87
|
+
## Use with websites (browser extension)
|
|
88
|
+
|
|
89
|
+
The Tollkit extension for Chrome, Brave and Edge lets websites connect to this wallet the way they connect to MetaMask or Phantom: Base and Ethereum apps through the standard Ethereum provider (EIP-1193/EIP-6963), Solana apps through the Wallet Standard.
|
|
90
|
+
|
|
91
|
+
Keys stay in Tollkit. When a site asks to connect, sign or send, the request shows up in the dashboard's Approvals tab with the site's name and the details. Transactions are checked against the network first. Nothing happens until you approve. Read-only calls go straight through.
|
|
92
|
+
|
|
93
|
+
To add it: run `tollkit-wallet extension` for the folder and steps (Developer mode, then Load unpacked), then pair it from **Settings → Pair a browser**. Connected sites are listed in Settings, where you can disconnect them. The dashboard has to be open for sites to use the wallet.
|
|
94
|
+
|
|
83
95
|
## Use from code
|
|
84
96
|
|
|
85
97
|
```ts
|
|
@@ -88,6 +100,45 @@ const w = await TollkitWallet.open(process.env.TOLLKIT_WALLET_PASSWORD!);
|
|
|
88
100
|
const r = await w.pay("https://api.example.com/paid-endpoint");
|
|
89
101
|
```
|
|
90
102
|
|
|
103
|
+
## Backup and recovery
|
|
104
|
+
|
|
105
|
+
New wallets (0.2.2 and later) are made from a 12-word recovery phrase. It's shown once when you create the wallet, and you can see it again with `tollkit-wallet backup` or **Back up** in the dashboard (password needed). The dashboard asks you to confirm three of the words before it counts as backed up.
|
|
106
|
+
|
|
107
|
+
The phrase uses the same derivation paths as MetaMask and Phantom (Base/Ethereum `m/44'/60'/0'/0/0`, Solana `m/44'/501'/0'/0'`), so it restores the same addresses there too.
|
|
108
|
+
|
|
109
|
+
To restore: `tollkit-wallet restore` and type the phrase. Wallets made before 0.2.2 have no phrase; their backup is the two private keys (`tollkit-wallet backup` shows them), restored with `tollkit-wallet restore --keys`. Add `--replace` to restore over an existing wallet; its files are kept, renamed with `.replaced-<time>`.
|
|
110
|
+
|
|
111
|
+
## Tokens and price charts
|
|
112
|
+
|
|
113
|
+
The dashboard's Home tab lists every token the wallet holds that has a price, with its value and 24-hour change. Tap a token for a price chart (1D, 1W, 1M, 1Y). Prices and charts come from DefiLlama.
|
|
114
|
+
|
|
115
|
+
How tokens are found:
|
|
116
|
+
- Solana: every SPL and Token-2022 token account the address owns.
|
|
117
|
+
- Ethereum: Blockscout's public token list for the address.
|
|
118
|
+
- Base: tokens you've swapped into with this wallet, plus any you add with **Add a token** (paste the contract address). Base has no free public token index that works without a key, so the wallet doesn't scan for others.
|
|
119
|
+
|
|
120
|
+
Tokens with no price (most airdropped spam) are hidden and counted below the list. Added tokens are saved in `tokens.json` in the wallet folder.
|
|
121
|
+
|
|
122
|
+
## Buy crypto with a card
|
|
123
|
+
|
|
124
|
+
**Buy** on the Home tab opens Coinbase's checkout to buy USDC or ETH on Base or Ethereum, or USDC or SOL on Solana, sent straight to this wallet's address. The wallet asks Tollkit's server for a single-use Coinbase Onramp link; only your public address, the network, the coin and the amount are sent. Coinbase handles the payment and any ID checks, and its own fees and limits apply.
|
|
125
|
+
|
|
126
|
+
## Cash out to your bank
|
|
127
|
+
|
|
128
|
+
**Sell** on the Home tab sells USDC, ETH or SOL through Coinbase to your bank or PayPal. You need a Coinbase account. The wallet opens Coinbase's sell page; you choose where the money goes and click **Cash out now**. Coinbase then gives an address to send the crypto to, and the dashboard shows it with the amount, Coinbase's fee and what you'll receive. Nothing is sent until you confirm with your password. Coinbase allows 30 minutes for the send. Only your public address, the network, the coin and the amount go to Tollkit's server.
|
|
129
|
+
|
|
130
|
+
## Move between networks
|
|
131
|
+
|
|
132
|
+
**Move** on the Home tab sends your own USDC between Base, Ethereum and Solana, or ETH between Base and Ethereum, to this wallet's address on the other network.
|
|
133
|
+
|
|
134
|
+
- USDC uses Circle's own transfer (CCTP): it's burned on one network and minted on the other by Circle, usually in 8 to 20 seconds. Circle's forwarding service pays the network fee on arrival, so you don't need gas there.
|
|
135
|
+
- ETH goes through Across, usually in under a minute.
|
|
136
|
+
- Tollkit's fee is 0.25%. Circle's or Across's fee, and the amount you'll receive at least, are shown before you confirm. Moves need your password and don't count against your spending limits.
|
|
137
|
+
|
|
138
|
+
## Stake SOL
|
|
139
|
+
|
|
140
|
+
**Stake** on the Home tab stakes SOL with a validator you pick from the ones currently voting, listed by how much SOL is staked with them, with their fee. The minimum is set by the network (1 SOL as of October 2026) and read live. Stakes start earning after the current epoch ends (about a day). Unstake any time; once the epoch ends, **Withdraw** returns the SOL to your wallet. The wallet keeps both stake and withdraw authority, and staking needs your password.
|
|
141
|
+
|
|
91
142
|
## Where things live
|
|
92
143
|
|
|
93
144
|
`~/.tollkit-wallet/` (or `TOLLKIT_WALLET_HOME`) holds:
|
|
@@ -116,10 +167,18 @@ tollkit-wallet rule pause <id> # or: rule on <id>, rule cancel <id>
|
|
|
116
167
|
Or use the **Autopilot** tab in the dashboard (`tollkit-wallet ui`). Rule types: limit buy, limit sell, take-profit, stop-loss, trailing stop, and recurring buys (hourly, daily, weekly or a set weekday, with an optional count and maximum price). A take-profit and a stop-loss on the same token are linked: when one fills, the other cancels.
|
|
117
168
|
|
|
118
169
|
- Every fill goes through the same limits, approvals and receipts as any swap, and pays the same 0.5% fee.
|
|
119
|
-
- Rules an agent suggests (`autopilot_propose`) wait for you to turn them on, unless you tick "Let agents turn on autopilot rules without asking me" in
|
|
170
|
+
- Rules an agent suggests (`autopilot_propose`) wait for you to turn them on, unless you tick "Let agents turn on autopilot rules without asking me" in Settings (or `budget agent_rules=auto`).
|
|
120
171
|
- The autopilot runs while the wallet runs: keep the dashboard open, or run `tollkit-wallet autopilot` on a computer or small server that stays on. Only one copy runs rules at a time.
|
|
121
172
|
- Limit orders fill only at their price or better (within 1% for fees and spread). Stops always sell. When selling all of a chain's coin, a little is kept for network fees.
|
|
122
173
|
|
|
174
|
+
### Chat with your AI on the Autopilot tab
|
|
175
|
+
|
|
176
|
+
If Claude Code is installed and signed in on this computer, the Autopilot tab is a chat. Say what you want in your own words ("protect my ETH if it drops hard", "buy SOL on dips, $20 at a time"); Claude checks your balances, live prices and recent price history, explains its thinking, and suggests rules as cards you turn on with one tap. It runs on your own Claude plan.
|
|
177
|
+
|
|
178
|
+
For these chats Claude Code runs with its own tools switched off and only the wallet's advisor tools available (`tollkit-wallet mcp --advisor`: balances, limits, receipts, prices, price history, your rules, and suggesting rules). It can't trade, pay, withdraw or change limits, and its suggestions always wait for you, even if you let other agents turn rules on.
|
|
179
|
+
|
|
180
|
+
**Check-ins:** pick every 1, 4, 12 or 24 hours and Claude reviews your rules against the market and what you've told it, then suggests changes (for example raising a stop-loss after a rise). A suggested change replaces the old rule only when you turn it on. If Telegram is set up, check-in suggestions also arrive there with Approve and Deny. Check-ins run while the dashboard is open.
|
|
181
|
+
|
|
123
182
|
## Paper trading
|
|
124
183
|
|
|
125
184
|
Practise with pretend money at real live prices, fees included, under the same limits:
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -11,3 +11,11 @@ Coin and chain logos in `src/coin-icons.ts` come from web3icons (`@web3icons/cor
|
|
|
11
11
|
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
12
12
|
|
|
13
13
|
The coin and network names and logos are trademarks of their owners and are used only to identify the assets and networks the wallet supports.
|
|
14
|
+
|
|
15
|
+
## Simple Icons
|
|
16
|
+
|
|
17
|
+
The Claude, Cursor, GitHub Copilot and Gemini logos in the dashboard's "Connect your AI" picker (`src/ai-icons.ts`) come from Simple Icons (https://simpleicons.org), whose data is released under CC0 1.0. The logos are trademarks of their owners and are shown only to say which apps work with the wallet.
|
|
18
|
+
|
|
19
|
+
## Wallet Standard (extension/inpage.js)
|
|
20
|
+
|
|
21
|
+
The Solana wallet registration in `extension/inpage.js` follows `registerWallet` from `@wallet-standard/wallet` (https://github.com/wallet-standard/wallet-standard), Apache License 2.0. The feature names and shapes come from `@wallet-standard/features` and `@solana/wallet-standard-features` (Apache License 2.0).
|
package/dist/actions.d.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* addresses.
|
|
6
6
|
*/
|
|
7
7
|
import { z } from "zod";
|
|
8
|
+
export { isLocalUrl } from "./netguard.js";
|
|
8
9
|
import type { TollkitWallet } from "./wallet.js";
|
|
9
10
|
export declare const SwapArgs: z.ZodObject<{
|
|
10
11
|
chain: z.ZodEnum<["base", "ethereum", "solana"]>;
|
|
@@ -32,12 +33,12 @@ export declare const PayArgs: z.ZodObject<{
|
|
|
32
33
|
body: z.ZodOptional<z.ZodString>;
|
|
33
34
|
}, "strip", z.ZodTypeAny, {
|
|
34
35
|
url: string;
|
|
35
|
-
method?: "
|
|
36
|
+
method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | undefined;
|
|
36
37
|
headers?: Record<string, string> | undefined;
|
|
37
38
|
body?: string | undefined;
|
|
38
39
|
}, {
|
|
39
40
|
url: string;
|
|
40
|
-
method?: "
|
|
41
|
+
method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | undefined;
|
|
41
42
|
headers?: Record<string, string> | undefined;
|
|
42
43
|
body?: string | undefined;
|
|
43
44
|
}>;
|
|
@@ -80,12 +81,15 @@ export declare const ProposeArgs: z.ZodObject<{
|
|
|
80
81
|
max_price: z.ZodOptional<z.ZodNumber>;
|
|
81
82
|
group: z.ZodOptional<z.ZodString>;
|
|
82
83
|
expires_at: z.ZodOptional<z.ZodString>;
|
|
84
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
85
|
+
replaces: z.ZodOptional<z.ZodString>;
|
|
83
86
|
}, "strip", z.ZodTypeAny, {
|
|
84
|
-
chain: "base" | "ethereum" | "solana";
|
|
85
87
|
kind: "limit_buy" | "limit_sell" | "stop_loss" | "take_profit" | "trailing_stop" | "dca";
|
|
88
|
+
chain: "base" | "ethereum" | "solana";
|
|
86
89
|
token: string;
|
|
87
90
|
every?: "hour" | "day" | "week" | undefined;
|
|
88
91
|
name?: string | undefined;
|
|
92
|
+
reason?: string | undefined;
|
|
89
93
|
sell_amount?: string | undefined;
|
|
90
94
|
amount_usd?: number | undefined;
|
|
91
95
|
sell_percent?: number | undefined;
|
|
@@ -96,12 +100,14 @@ export declare const ProposeArgs: z.ZodObject<{
|
|
|
96
100
|
max_price?: number | undefined;
|
|
97
101
|
group?: string | undefined;
|
|
98
102
|
expires_at?: string | undefined;
|
|
103
|
+
replaces?: string | undefined;
|
|
99
104
|
}, {
|
|
100
|
-
chain: "base" | "ethereum" | "solana";
|
|
101
105
|
kind: "limit_buy" | "limit_sell" | "stop_loss" | "take_profit" | "trailing_stop" | "dca";
|
|
106
|
+
chain: "base" | "ethereum" | "solana";
|
|
102
107
|
token: string;
|
|
103
108
|
every?: "hour" | "day" | "week" | undefined;
|
|
104
109
|
name?: string | undefined;
|
|
110
|
+
reason?: string | undefined;
|
|
105
111
|
sell_amount?: string | undefined;
|
|
106
112
|
amount_usd?: number | undefined;
|
|
107
113
|
sell_percent?: number | undefined;
|
|
@@ -112,14 +118,16 @@ export declare const ProposeArgs: z.ZodObject<{
|
|
|
112
118
|
max_price?: number | undefined;
|
|
113
119
|
group?: string | undefined;
|
|
114
120
|
expires_at?: string | undefined;
|
|
121
|
+
replaces?: string | undefined;
|
|
115
122
|
}>, "many">>;
|
|
116
123
|
}, "strip", z.ZodTypeAny, {
|
|
117
124
|
rules?: {
|
|
118
|
-
chain: "base" | "ethereum" | "solana";
|
|
119
125
|
kind: "limit_buy" | "limit_sell" | "stop_loss" | "take_profit" | "trailing_stop" | "dca";
|
|
126
|
+
chain: "base" | "ethereum" | "solana";
|
|
120
127
|
token: string;
|
|
121
128
|
every?: "hour" | "day" | "week" | undefined;
|
|
122
129
|
name?: string | undefined;
|
|
130
|
+
reason?: string | undefined;
|
|
123
131
|
sell_amount?: string | undefined;
|
|
124
132
|
amount_usd?: number | undefined;
|
|
125
133
|
sell_percent?: number | undefined;
|
|
@@ -130,15 +138,17 @@ export declare const ProposeArgs: z.ZodObject<{
|
|
|
130
138
|
max_price?: number | undefined;
|
|
131
139
|
group?: string | undefined;
|
|
132
140
|
expires_at?: string | undefined;
|
|
141
|
+
replaces?: string | undefined;
|
|
133
142
|
}[] | undefined;
|
|
134
143
|
text?: string | undefined;
|
|
135
144
|
}, {
|
|
136
145
|
rules?: {
|
|
137
|
-
chain: "base" | "ethereum" | "solana";
|
|
138
146
|
kind: "limit_buy" | "limit_sell" | "stop_loss" | "take_profit" | "trailing_stop" | "dca";
|
|
147
|
+
chain: "base" | "ethereum" | "solana";
|
|
139
148
|
token: string;
|
|
140
149
|
every?: "hour" | "day" | "week" | undefined;
|
|
141
150
|
name?: string | undefined;
|
|
151
|
+
reason?: string | undefined;
|
|
142
152
|
sell_amount?: string | undefined;
|
|
143
153
|
amount_usd?: number | undefined;
|
|
144
154
|
sell_percent?: number | undefined;
|
|
@@ -149,15 +159,16 @@ export declare const ProposeArgs: z.ZodObject<{
|
|
|
149
159
|
max_price?: number | undefined;
|
|
150
160
|
group?: string | undefined;
|
|
151
161
|
expires_at?: string | undefined;
|
|
162
|
+
replaces?: string | undefined;
|
|
152
163
|
}[] | undefined;
|
|
153
164
|
text?: string | undefined;
|
|
154
165
|
}>;
|
|
155
166
|
export declare const RulesListArgs: z.ZodObject<{
|
|
156
167
|
status: z.ZodOptional<z.ZodEnum<["proposed", "active", "paused", "done", "cancelled", "expired", "error"]>>;
|
|
157
168
|
}, "strip", z.ZodTypeAny, {
|
|
158
|
-
status?: "
|
|
169
|
+
status?: "error" | "done" | "proposed" | "active" | "paused" | "cancelled" | "expired" | undefined;
|
|
159
170
|
}, {
|
|
160
|
-
status?: "
|
|
171
|
+
status?: "error" | "done" | "proposed" | "active" | "paused" | "cancelled" | "expired" | undefined;
|
|
161
172
|
}>;
|
|
162
173
|
export declare const RuleIdArgs: z.ZodObject<{
|
|
163
174
|
id: z.ZodString;
|
|
@@ -166,6 +177,58 @@ export declare const RuleIdArgs: z.ZodObject<{
|
|
|
166
177
|
}, {
|
|
167
178
|
id: string;
|
|
168
179
|
}>;
|
|
180
|
+
export declare const HistoryArgs: z.ZodObject<{
|
|
181
|
+
token: z.ZodEnum<["ETH", "WETH", "SOL"]>;
|
|
182
|
+
interval: z.ZodOptional<z.ZodEnum<["15m", "1h", "6h", "1d"]>>;
|
|
183
|
+
points: z.ZodOptional<z.ZodNumber>;
|
|
184
|
+
}, "strip", z.ZodTypeAny, {
|
|
185
|
+
token: "ETH" | "WETH" | "SOL";
|
|
186
|
+
points?: number | undefined;
|
|
187
|
+
interval?: "1h" | "1d" | "15m" | "6h" | undefined;
|
|
188
|
+
}, {
|
|
189
|
+
token: "ETH" | "WETH" | "SOL";
|
|
190
|
+
points?: number | undefined;
|
|
191
|
+
interval?: "1h" | "1d" | "15m" | "6h" | undefined;
|
|
192
|
+
}>;
|
|
193
|
+
/** Coinbase Exchange public candles: [time, low, high, open, close, volume], newest first, at most 300, no key. */
|
|
194
|
+
export declare function priceHistory(a: z.infer<typeof HistoryArgs>, f?: typeof fetch): Promise<{
|
|
195
|
+
ok: boolean;
|
|
196
|
+
refused: {
|
|
197
|
+
code: string;
|
|
198
|
+
reason: string;
|
|
199
|
+
};
|
|
200
|
+
token?: undefined;
|
|
201
|
+
interval?: undefined;
|
|
202
|
+
source?: undefined;
|
|
203
|
+
from?: undefined;
|
|
204
|
+
to?: undefined;
|
|
205
|
+
open?: undefined;
|
|
206
|
+
last?: undefined;
|
|
207
|
+
change_pct?: undefined;
|
|
208
|
+
high?: undefined;
|
|
209
|
+
low?: undefined;
|
|
210
|
+
candles?: undefined;
|
|
211
|
+
} | {
|
|
212
|
+
ok: boolean;
|
|
213
|
+
token: "ETH" | "WETH" | "SOL";
|
|
214
|
+
interval: "1h" | "1d" | "15m" | "6h";
|
|
215
|
+
source: string;
|
|
216
|
+
from: string;
|
|
217
|
+
to: string;
|
|
218
|
+
open: number;
|
|
219
|
+
last: number;
|
|
220
|
+
change_pct: number;
|
|
221
|
+
high: number;
|
|
222
|
+
low: number;
|
|
223
|
+
candles: {
|
|
224
|
+
t: string;
|
|
225
|
+
open: number;
|
|
226
|
+
high: number;
|
|
227
|
+
low: number;
|
|
228
|
+
close: number;
|
|
229
|
+
}[];
|
|
230
|
+
refused?: undefined;
|
|
231
|
+
}>;
|
|
169
232
|
export interface WalletAction<S extends z.ZodTypeAny = z.ZodTypeAny> {
|
|
170
233
|
name: string;
|
|
171
234
|
description: string;
|
|
@@ -216,12 +279,12 @@ export declare const ACTIONS: readonly [WalletAction<z.ZodObject<{}, "strip", z.
|
|
|
216
279
|
body: z.ZodOptional<z.ZodString>;
|
|
217
280
|
}, "strip", z.ZodTypeAny, {
|
|
218
281
|
url: string;
|
|
219
|
-
method?: "
|
|
282
|
+
method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | undefined;
|
|
220
283
|
headers?: Record<string, string> | undefined;
|
|
221
284
|
body?: string | undefined;
|
|
222
285
|
}, {
|
|
223
286
|
url: string;
|
|
224
|
-
method?: "
|
|
287
|
+
method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | undefined;
|
|
225
288
|
headers?: Record<string, string> | undefined;
|
|
226
289
|
body?: string | undefined;
|
|
227
290
|
}>>, WalletAction<z.ZodObject<{
|
|
@@ -242,6 +305,18 @@ export declare const ACTIONS: readonly [WalletAction<z.ZodObject<{}, "strip", z.
|
|
|
242
305
|
}, {
|
|
243
306
|
since?: string | undefined;
|
|
244
307
|
limit?: number | undefined;
|
|
308
|
+
}>>, WalletAction<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>, WalletAction<z.ZodObject<{
|
|
309
|
+
token: z.ZodEnum<["ETH", "WETH", "SOL"]>;
|
|
310
|
+
interval: z.ZodOptional<z.ZodEnum<["15m", "1h", "6h", "1d"]>>;
|
|
311
|
+
points: z.ZodOptional<z.ZodNumber>;
|
|
312
|
+
}, "strip", z.ZodTypeAny, {
|
|
313
|
+
token: "ETH" | "WETH" | "SOL";
|
|
314
|
+
points?: number | undefined;
|
|
315
|
+
interval?: "1h" | "1d" | "15m" | "6h" | undefined;
|
|
316
|
+
}, {
|
|
317
|
+
token: "ETH" | "WETH" | "SOL";
|
|
318
|
+
points?: number | undefined;
|
|
319
|
+
interval?: "1h" | "1d" | "15m" | "6h" | undefined;
|
|
245
320
|
}>>, WalletAction<z.ZodObject<{
|
|
246
321
|
text: z.ZodOptional<z.ZodString>;
|
|
247
322
|
rules: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -260,12 +335,15 @@ export declare const ACTIONS: readonly [WalletAction<z.ZodObject<{}, "strip", z.
|
|
|
260
335
|
max_price: z.ZodOptional<z.ZodNumber>;
|
|
261
336
|
group: z.ZodOptional<z.ZodString>;
|
|
262
337
|
expires_at: z.ZodOptional<z.ZodString>;
|
|
338
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
339
|
+
replaces: z.ZodOptional<z.ZodString>;
|
|
263
340
|
}, "strip", z.ZodTypeAny, {
|
|
264
|
-
chain: "base" | "ethereum" | "solana";
|
|
265
341
|
kind: "limit_buy" | "limit_sell" | "stop_loss" | "take_profit" | "trailing_stop" | "dca";
|
|
342
|
+
chain: "base" | "ethereum" | "solana";
|
|
266
343
|
token: string;
|
|
267
344
|
every?: "hour" | "day" | "week" | undefined;
|
|
268
345
|
name?: string | undefined;
|
|
346
|
+
reason?: string | undefined;
|
|
269
347
|
sell_amount?: string | undefined;
|
|
270
348
|
amount_usd?: number | undefined;
|
|
271
349
|
sell_percent?: number | undefined;
|
|
@@ -276,12 +354,14 @@ export declare const ACTIONS: readonly [WalletAction<z.ZodObject<{}, "strip", z.
|
|
|
276
354
|
max_price?: number | undefined;
|
|
277
355
|
group?: string | undefined;
|
|
278
356
|
expires_at?: string | undefined;
|
|
357
|
+
replaces?: string | undefined;
|
|
279
358
|
}, {
|
|
280
|
-
chain: "base" | "ethereum" | "solana";
|
|
281
359
|
kind: "limit_buy" | "limit_sell" | "stop_loss" | "take_profit" | "trailing_stop" | "dca";
|
|
360
|
+
chain: "base" | "ethereum" | "solana";
|
|
282
361
|
token: string;
|
|
283
362
|
every?: "hour" | "day" | "week" | undefined;
|
|
284
363
|
name?: string | undefined;
|
|
364
|
+
reason?: string | undefined;
|
|
285
365
|
sell_amount?: string | undefined;
|
|
286
366
|
amount_usd?: number | undefined;
|
|
287
367
|
sell_percent?: number | undefined;
|
|
@@ -292,14 +372,16 @@ export declare const ACTIONS: readonly [WalletAction<z.ZodObject<{}, "strip", z.
|
|
|
292
372
|
max_price?: number | undefined;
|
|
293
373
|
group?: string | undefined;
|
|
294
374
|
expires_at?: string | undefined;
|
|
375
|
+
replaces?: string | undefined;
|
|
295
376
|
}>, "many">>;
|
|
296
377
|
}, "strip", z.ZodTypeAny, {
|
|
297
378
|
rules?: {
|
|
298
|
-
chain: "base" | "ethereum" | "solana";
|
|
299
379
|
kind: "limit_buy" | "limit_sell" | "stop_loss" | "take_profit" | "trailing_stop" | "dca";
|
|
380
|
+
chain: "base" | "ethereum" | "solana";
|
|
300
381
|
token: string;
|
|
301
382
|
every?: "hour" | "day" | "week" | undefined;
|
|
302
383
|
name?: string | undefined;
|
|
384
|
+
reason?: string | undefined;
|
|
303
385
|
sell_amount?: string | undefined;
|
|
304
386
|
amount_usd?: number | undefined;
|
|
305
387
|
sell_percent?: number | undefined;
|
|
@@ -310,15 +392,17 @@ export declare const ACTIONS: readonly [WalletAction<z.ZodObject<{}, "strip", z.
|
|
|
310
392
|
max_price?: number | undefined;
|
|
311
393
|
group?: string | undefined;
|
|
312
394
|
expires_at?: string | undefined;
|
|
395
|
+
replaces?: string | undefined;
|
|
313
396
|
}[] | undefined;
|
|
314
397
|
text?: string | undefined;
|
|
315
398
|
}, {
|
|
316
399
|
rules?: {
|
|
317
|
-
chain: "base" | "ethereum" | "solana";
|
|
318
400
|
kind: "limit_buy" | "limit_sell" | "stop_loss" | "take_profit" | "trailing_stop" | "dca";
|
|
401
|
+
chain: "base" | "ethereum" | "solana";
|
|
319
402
|
token: string;
|
|
320
403
|
every?: "hour" | "day" | "week" | undefined;
|
|
321
404
|
name?: string | undefined;
|
|
405
|
+
reason?: string | undefined;
|
|
322
406
|
sell_amount?: string | undefined;
|
|
323
407
|
amount_usd?: number | undefined;
|
|
324
408
|
sell_percent?: number | undefined;
|
|
@@ -329,14 +413,15 @@ export declare const ACTIONS: readonly [WalletAction<z.ZodObject<{}, "strip", z.
|
|
|
329
413
|
max_price?: number | undefined;
|
|
330
414
|
group?: string | undefined;
|
|
331
415
|
expires_at?: string | undefined;
|
|
416
|
+
replaces?: string | undefined;
|
|
332
417
|
}[] | undefined;
|
|
333
418
|
text?: string | undefined;
|
|
334
419
|
}>>, WalletAction<z.ZodObject<{
|
|
335
420
|
status: z.ZodOptional<z.ZodEnum<["proposed", "active", "paused", "done", "cancelled", "expired", "error"]>>;
|
|
336
421
|
}, "strip", z.ZodTypeAny, {
|
|
337
|
-
status?: "
|
|
422
|
+
status?: "error" | "done" | "proposed" | "active" | "paused" | "cancelled" | "expired" | undefined;
|
|
338
423
|
}, {
|
|
339
|
-
status?: "
|
|
424
|
+
status?: "error" | "done" | "proposed" | "active" | "paused" | "cancelled" | "expired" | undefined;
|
|
340
425
|
}>>, WalletAction<z.ZodObject<{
|
|
341
426
|
id: z.ZodString;
|
|
342
427
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -362,3 +447,98 @@ export declare const ACTIONS: readonly [WalletAction<z.ZodObject<{}, "strip", z.
|
|
|
362
447
|
buy: string;
|
|
363
448
|
slippage_bps?: number | undefined;
|
|
364
449
|
}>>, WalletAction<z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>>];
|
|
450
|
+
export declare function proposeRules(w: TollkitWallet, a: z.infer<typeof ProposeArgs>, o?: {
|
|
451
|
+
neverAuto?: boolean;
|
|
452
|
+
}): Promise<{
|
|
453
|
+
ok: boolean;
|
|
454
|
+
refused: {
|
|
455
|
+
code: string;
|
|
456
|
+
reason: string;
|
|
457
|
+
};
|
|
458
|
+
unparsed: string[];
|
|
459
|
+
rules?: undefined;
|
|
460
|
+
note?: undefined;
|
|
461
|
+
} | {
|
|
462
|
+
ok: boolean;
|
|
463
|
+
refused: {
|
|
464
|
+
code: string;
|
|
465
|
+
reason: string;
|
|
466
|
+
};
|
|
467
|
+
rules: {
|
|
468
|
+
id: string;
|
|
469
|
+
status: import("./rules.js").RuleStatus;
|
|
470
|
+
description: string;
|
|
471
|
+
created_by: "owner" | "agent";
|
|
472
|
+
last_price: number | undefined;
|
|
473
|
+
fills: number;
|
|
474
|
+
last_fill: import("./rules.js").Fill | undefined;
|
|
475
|
+
error: string | undefined;
|
|
476
|
+
rule: {
|
|
477
|
+
state: undefined;
|
|
478
|
+
id: string;
|
|
479
|
+
status: import("./rules.js").RuleStatus;
|
|
480
|
+
created_by: "owner" | "agent";
|
|
481
|
+
created_at: string;
|
|
482
|
+
activated_at?: string;
|
|
483
|
+
kind: "limit_buy" | "limit_sell" | "stop_loss" | "take_profit" | "trailing_stop" | "dca";
|
|
484
|
+
chain: "base" | "ethereum" | "solana";
|
|
485
|
+
token: string;
|
|
486
|
+
every?: "hour" | "day" | "week" | undefined;
|
|
487
|
+
name?: string | undefined;
|
|
488
|
+
reason?: string | undefined;
|
|
489
|
+
sell_amount?: string | undefined;
|
|
490
|
+
amount_usd?: number | undefined;
|
|
491
|
+
sell_percent?: number | undefined;
|
|
492
|
+
trigger_price?: number | undefined;
|
|
493
|
+
trail_pct?: number | undefined;
|
|
494
|
+
weekday?: number | undefined;
|
|
495
|
+
times?: number | undefined;
|
|
496
|
+
max_price?: number | undefined;
|
|
497
|
+
group?: string | undefined;
|
|
498
|
+
expires_at?: string | undefined;
|
|
499
|
+
replaces?: string | undefined;
|
|
500
|
+
};
|
|
501
|
+
}[];
|
|
502
|
+
unparsed: string[];
|
|
503
|
+
note?: undefined;
|
|
504
|
+
} | {
|
|
505
|
+
ok: boolean;
|
|
506
|
+
rules: {
|
|
507
|
+
id: string;
|
|
508
|
+
status: import("./rules.js").RuleStatus;
|
|
509
|
+
description: string;
|
|
510
|
+
created_by: "owner" | "agent";
|
|
511
|
+
last_price: number | undefined;
|
|
512
|
+
fills: number;
|
|
513
|
+
last_fill: import("./rules.js").Fill | undefined;
|
|
514
|
+
error: string | undefined;
|
|
515
|
+
rule: {
|
|
516
|
+
state: undefined;
|
|
517
|
+
id: string;
|
|
518
|
+
status: import("./rules.js").RuleStatus;
|
|
519
|
+
created_by: "owner" | "agent";
|
|
520
|
+
created_at: string;
|
|
521
|
+
activated_at?: string;
|
|
522
|
+
kind: "limit_buy" | "limit_sell" | "stop_loss" | "take_profit" | "trailing_stop" | "dca";
|
|
523
|
+
chain: "base" | "ethereum" | "solana";
|
|
524
|
+
token: string;
|
|
525
|
+
every?: "hour" | "day" | "week" | undefined;
|
|
526
|
+
name?: string | undefined;
|
|
527
|
+
reason?: string | undefined;
|
|
528
|
+
sell_amount?: string | undefined;
|
|
529
|
+
amount_usd?: number | undefined;
|
|
530
|
+
sell_percent?: number | undefined;
|
|
531
|
+
trigger_price?: number | undefined;
|
|
532
|
+
trail_pct?: number | undefined;
|
|
533
|
+
weekday?: number | undefined;
|
|
534
|
+
times?: number | undefined;
|
|
535
|
+
max_price?: number | undefined;
|
|
536
|
+
group?: string | undefined;
|
|
537
|
+
expires_at?: string | undefined;
|
|
538
|
+
replaces?: string | undefined;
|
|
539
|
+
};
|
|
540
|
+
}[];
|
|
541
|
+
unparsed: string[];
|
|
542
|
+
note: string;
|
|
543
|
+
refused?: undefined;
|
|
544
|
+
}>;
|
package/dist/actions.js
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
* addresses.
|
|
6
6
|
*/
|
|
7
7
|
import { z } from "zod";
|
|
8
|
+
import { isLocalUrl } from "./netguard.js";
|
|
9
|
+
export { isLocalUrl } from "./netguard.js";
|
|
8
10
|
import { resolveToken, toAtomic } from "./tokens.js";
|
|
9
11
|
import { checkSeller } from "./seller.js";
|
|
10
12
|
import { RuleInput, describeRule, ruleProblem } from "./rules.js";
|
|
@@ -36,6 +38,30 @@ export const ProposeArgs = z.object({
|
|
|
36
38
|
});
|
|
37
39
|
export const RulesListArgs = z.object({ status: z.enum(["proposed", "active", "paused", "done", "cancelled", "expired", "error"]).optional() });
|
|
38
40
|
export const RuleIdArgs = z.object({ id: z.string().min(4).max(40) });
|
|
41
|
+
export const HistoryArgs = z.object({
|
|
42
|
+
token: z.enum(["ETH", "WETH", "SOL"]).describe("ETH (also WETH) or SOL; prices from Coinbase Exchange"),
|
|
43
|
+
interval: z.enum(["15m", "1h", "6h", "1d"]).optional().describe("Candle size (default 1h)"),
|
|
44
|
+
points: z.number().int().min(5).max(200).optional().describe("How many candles, newest last (default 48)"),
|
|
45
|
+
});
|
|
46
|
+
const GRAN = { "15m": 900, "1h": 3600, "6h": 21600, "1d": 86400 };
|
|
47
|
+
/** Coinbase Exchange public candles: [time, low, high, open, close, volume], newest first, at most 300, no key. */
|
|
48
|
+
export async function priceHistory(a, f = fetch) {
|
|
49
|
+
const product = a.token === "SOL" ? "SOL-USD" : "ETH-USD", interval = a.interval ?? "1h";
|
|
50
|
+
const r = await f(`https://api.exchange.coinbase.com/products/${product}/candles?granularity=${GRAN[interval]}`, { headers: { accept: "application/json" }, signal: AbortSignal.timeout(10_000) });
|
|
51
|
+
if (!r.ok)
|
|
52
|
+
return { ok: false, refused: { code: "unavailable", reason: `Price history isn't available right now (HTTP ${r.status}).` } };
|
|
53
|
+
const rows = (await r.json()).sort((x, y) => x[0] - y[0]).slice(-(a.points ?? 48));
|
|
54
|
+
if (!rows.length)
|
|
55
|
+
return { ok: false, refused: { code: "unavailable", reason: "No price history returned." } };
|
|
56
|
+
const closes = rows.map((x) => x[4]), first = rows[0][3], last = closes.at(-1);
|
|
57
|
+
return {
|
|
58
|
+
ok: true, token: a.token, interval, source: "Coinbase Exchange",
|
|
59
|
+
from: new Date(rows[0][0] * 1000).toISOString(), to: new Date(rows.at(-1)[0] * 1000).toISOString(),
|
|
60
|
+
open: first, last, change_pct: +(((last - first) / first) * 100).toFixed(2),
|
|
61
|
+
high: Math.max(...rows.map((x) => x[2])), low: Math.min(...rows.map((x) => x[1])),
|
|
62
|
+
candles: rows.map(([t, low, high, open, close]) => ({ t: new Date(t * 1000).toISOString(), open, high, low, close })),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
39
65
|
async function swapRequest(w, a) {
|
|
40
66
|
const chain = a.chain;
|
|
41
67
|
const [sell, buy] = await Promise.all([resolveToken(chain, a.sell), resolveToken(chain, a.buy)]);
|
|
@@ -71,7 +97,9 @@ export const ACTIONS = [
|
|
|
71
97
|
def({ name: "pay_fetch", spends: true, schema: PayArgs,
|
|
72
98
|
description: "Fetch a URL and pay for it if it asks (x402 or MPP, USDC/USDT on Base, Ethereum or Solana). Checks the seller, screens the recipient against OFAC, stays within the owner's limits. Returns the response body.",
|
|
73
99
|
run: async (w, a) => {
|
|
74
|
-
|
|
100
|
+
if (isLocalUrl(a.url))
|
|
101
|
+
return { paid: false, status: 0, refused: { code: "local_address", reason: "pay_fetch only calls public internet addresses." } };
|
|
102
|
+
const r = await w.pay(a.url, { method: a.method ?? (a.body ? "POST" : "GET"), headers: a.headers, body: a.body }, { publicOnly: true });
|
|
75
103
|
let body;
|
|
76
104
|
if (r.response) {
|
|
77
105
|
const t = await r.response.text();
|
|
@@ -85,8 +113,14 @@ export const ACTIONS = [
|
|
|
85
113
|
def({ name: "receipts", spends: false, schema: ReceiptArgs,
|
|
86
114
|
description: "Recent trades, payments and withdrawals with amounts, fees and transaction hashes.",
|
|
87
115
|
run: async (w, a) => w.receipts(a.since).slice(-(a.limit ?? 50)) }),
|
|
116
|
+
def({ name: "market_prices", spends: false, schema: NoArgs,
|
|
117
|
+
description: "Live USD prices and 24-hour change for ETH, SOL and USDT (Coinbase Exchange; USDC is $1).",
|
|
118
|
+
run: async () => { const f = new PriceFeed(); await f.refresh(); return f.snapshot(); } }),
|
|
119
|
+
def({ name: "price_history", spends: false, schema: HistoryArgs,
|
|
120
|
+
description: "Recent price candles for ETH or SOL (open, high, low, close) with the period's change, high and low. Use it to judge trends and to set sensible trigger prices.",
|
|
121
|
+
run: async (_w, a) => priceHistory(a) }),
|
|
88
122
|
def({ name: "autopilot_propose", spends: false, schema: ProposeArgs,
|
|
89
|
-
description: "Set up autopilot rules: limit buy/sell, stop-loss, take-profit, trailing stop, recurring buy (DCA). Give plain English in `text` (e.g. \"buy $25 of SOL every Monday; sell half my ETH if it rises 10% and all if it falls 8%\") or exact `rules`. Unless the owner allows auto, rules wait for the owner to turn them on in the dashboard; fills follow the owner's limits.",
|
|
123
|
+
description: "Set up autopilot rules: limit buy/sell, stop-loss, take-profit, trailing stop, recurring buy (DCA). Give plain English in `text` (e.g. \"buy $25 of SOL every Monday; sell half my ETH if it rises 10% and all if it falls 8%\") or exact `rules`. Give each rule a short plain `reason`; to change an existing rule, propose its replacement with `replaces: <id>`. Unless the owner allows auto, rules wait for the owner to turn them on in the dashboard; fills follow the owner's limits.",
|
|
90
124
|
run: async (w, a) => proposeRules(w, a) }),
|
|
91
125
|
def({ name: "autopilot_rules", spends: false, schema: RulesListArgs,
|
|
92
126
|
description: "The autopilot's rules with a plain description of each, status, last price seen, fills and any error.",
|
|
@@ -116,7 +150,7 @@ function showRule(r) {
|
|
|
116
150
|
const last = r.state.fills.at(-1);
|
|
117
151
|
return { id: r.id, status: r.status, description: describeRule(r), created_by: r.created_by, last_price: r.state.last_price, fills: r.state.fills.filter((f) => f.ok).length, last_fill: last, error: r.state.last_error, rule: { ...r, state: undefined } };
|
|
118
152
|
}
|
|
119
|
-
async function proposeRules(w, a) {
|
|
153
|
+
export async function proposeRules(w, a, o = {}) {
|
|
120
154
|
let drafts = [...(a.rules ?? [])], unparsed = [];
|
|
121
155
|
if (a.text) {
|
|
122
156
|
const feed = new PriceFeed();
|
|
@@ -132,9 +166,15 @@ async function proposeRules(w, a) {
|
|
|
132
166
|
if (why)
|
|
133
167
|
return { ok: false, refused: { code: "bad_rule", reason: `${describeRule(d)}: ${why}` }, unparsed };
|
|
134
168
|
}
|
|
135
|
-
const store = w.rules(), auto = w.policy.agent_rules === "auto", made = [];
|
|
136
|
-
for (const d of drafts)
|
|
137
|
-
|
|
169
|
+
const store = w.rules(), auto = !o.neverAuto && w.policy.agent_rules === "auto", made = [];
|
|
170
|
+
for (const d of drafts) {
|
|
171
|
+
try {
|
|
172
|
+
made.push(showRule(await store.add(d, "agent", auto)));
|
|
173
|
+
}
|
|
174
|
+
catch (e) {
|
|
175
|
+
return { ok: false, refused: { code: "bad_rule", reason: `${describeRule(d)}: ${e.message}` }, rules: made, unparsed };
|
|
176
|
+
}
|
|
177
|
+
}
|
|
138
178
|
return {
|
|
139
179
|
ok: true, rules: made, unparsed,
|
|
140
180
|
note: auto ? "These rules are on. The autopilot runs while the wallet's dashboard or `tollkit-wallet autopilot` is running." : "These rules are waiting for the owner to turn them on in the dashboard (Autopilot tab) or with `tollkit-wallet rule on <id>`.",
|