walletcap 0.2.3__tar.gz → 0.2.4__tar.gz
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.
- {walletcap-0.2.3 → walletcap-0.2.4}/.circleci/config.yml +8 -0
- walletcap-0.2.4/.github/workflows/ci.yml +80 -0
- walletcap-0.2.4/.github/workflows/mcp-registry.yml +47 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/.github/workflows/publish.yml +35 -4
- {walletcap-0.2.3 → walletcap-0.2.4}/CHANGELOG.md +19 -0
- walletcap-0.2.3/README.md → walletcap-0.2.4/PKG-INFO +91 -11
- walletcap-0.2.3/PKG-INFO → walletcap-0.2.4/README.md +68 -34
- walletcap-0.2.4/crash-test/README.md +124 -0
- walletcap-0.2.4/crash-test/agent.mjs +100 -0
- walletcap-0.2.4/crash-test/agentkit-agent.mjs +83 -0
- walletcap-0.2.4/crash-test/ci/check-agentkit.mjs +16 -0
- walletcap-0.2.4/crash-test/cli.mjs +264 -0
- walletcap-0.2.4/crash-test/contracts/build.mjs +94 -0
- walletcap-0.2.4/crash-test/contracts/coinbase-base-mainnet.json +27 -0
- walletcap-0.2.4/crash-test/contracts/walletcap.json +501 -0
- walletcap-0.2.4/crash-test/package.json +75 -0
- walletcap-0.2.4/crash-test/spend-permissions.mjs +180 -0
- walletcap-0.2.4/crash-test/spend-store.mjs +86 -0
- walletcap-0.2.4/crash-test/test/crash-test.test.mjs +135 -0
- walletcap-0.2.4/docs/_config.yml +19 -0
- walletcap-0.2.4/docs/coinbase-agentic-wallet-budget.md +85 -0
- walletcap-0.2.4/docs/coinbase-agentkit-spending-limit.md +69 -0
- walletcap-0.2.4/docs/coinbase-cdp-spend-controls.md +85 -0
- walletcap-0.2.4/docs/coinbase-spend-permissions-cap.md +79 -0
- walletcap-0.2.4/docs/index.md +92 -0
- walletcap-0.2.4/docs/llms.txt +39 -0
- walletcap-0.2.4/docs/python-agent-spending-limit.md +83 -0
- walletcap-0.2.4/docs/social-preview.png +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/docs/vendor-disclosure.md +1 -1
- walletcap-0.2.4/docs/x402-spending-limit.md +80 -0
- walletcap-0.2.4/glama.json +6 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/README.md +12 -1
- {walletcap-0.2.3 → walletcap-0.2.4}/js/index.d.ts +1 -1
- {walletcap-0.2.3 → walletcap-0.2.4}/js/package.json +14 -4
- walletcap-0.2.4/llms.txt +39 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/pyproject.toml +15 -3
- {walletcap-0.2.3 → walletcap-0.2.4}/scripts/ci.sh +7 -0
- walletcap-0.2.4/server.json +53 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/solidity/evm/package.json +1 -1
- {walletcap-0.2.3 → walletcap-0.2.4}/src/walletcap/__init__.py +1 -1
- walletcap-0.2.3/.github/workflows/ci.yml +0 -47
- {walletcap-0.2.3 → walletcap-0.2.4}/.gitignore +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/LICENSE +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/NOTICE +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/SECURITY.md +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/docs/threat-model.md +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/examples/quickstart/README.md +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/examples/quickstart/quickstart.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/examples/quickstart/quickstart.py +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/LICENSE +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/NOTICE +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/_keccak.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/agentic.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/cdp.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/cli.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/errors.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/index.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/ledger.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/money.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/tests/agentic.test.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/tests/agentkit.test.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/tests/budget.test.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/tests/cdp-sdk.test.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/tests/cdp.test.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/tests/cli.test.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/tests/keccak.test.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/tests/money.test.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/tests/processes.test.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/tests/support/fake-awal/dist/index.js +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/tests/support/fake-awal/dist/ipcClient.js +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/tests/support/fake-awal/package.json +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/tests/support/fake-payments-mcp.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/tests/support/payer.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/tests/support/race.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/tests/support/x402-kit.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/tests/support/x402-payer.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/tests/types/agentkit.d.ts +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/tests/types/recipe.ts +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/tests/types/subclass.ts +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/tests/x402-fetch.test.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/tests/x402.test.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/js/x402.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/pytest.ini +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/solidity/README.md +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/solidity/evm/check.mjs +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/solidity/foundry.toml +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/solidity/src/AccountCapSpender.sol +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/solidity/test/AccountCapSpender.t.sol +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/solidity/test/Mocks.sol +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/src/walletcap/__main__.py +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/src/walletcap/_keccak.py +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/src/walletcap/budget.py +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/src/walletcap/errors.py +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/src/walletcap/ledger.py +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/src/walletcap/money.py +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/src/walletcap/py.typed +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/tests/test_budget.py +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/tests/test_keccak.py +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/tests/test_ledger.py +0 -0
- {walletcap-0.2.3 → walletcap-0.2.4}/tests/test_money.py +0 -0
|
@@ -33,6 +33,14 @@ jobs:
|
|
|
33
33
|
cd solidity/evm
|
|
34
34
|
npm install --no-audit --no-fund --no-package-lock
|
|
35
35
|
node check.mjs ..
|
|
36
|
+
- run:
|
|
37
|
+
name: Crash test
|
|
38
|
+
command: |
|
|
39
|
+
cd crash-test
|
|
40
|
+
npm install --no-audit --no-fund --no-package-lock
|
|
41
|
+
npm install --no-save --no-audit --no-fund --no-package-lock ../js
|
|
42
|
+
node contracts/build.mjs --check
|
|
43
|
+
node --test
|
|
36
44
|
|
|
37
45
|
workflows:
|
|
38
46
|
ci:
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
javascript:
|
|
13
|
+
name: JavaScript
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
container: node:22-bookworm
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
|
|
18
|
+
- name: Install the test dependencies
|
|
19
|
+
run: npm install --no-audit --no-fund
|
|
20
|
+
working-directory: js
|
|
21
|
+
- name: Run the suite
|
|
22
|
+
run: node --test
|
|
23
|
+
working-directory: js
|
|
24
|
+
|
|
25
|
+
python:
|
|
26
|
+
name: Python
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
container: node:22-bookworm
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
|
|
31
|
+
- uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e
|
|
32
|
+
- name: Run the suite
|
|
33
|
+
# Node is on PATH here, so the cross-language tests run rather than skip.
|
|
34
|
+
run: uv run --with pytest --python 3.12 pytest -q
|
|
35
|
+
|
|
36
|
+
solidity:
|
|
37
|
+
name: Solidity
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
container: node:22-bookworm
|
|
40
|
+
steps:
|
|
41
|
+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
|
|
42
|
+
- name: Install the check's dependencies
|
|
43
|
+
run: npm install --no-audit --no-fund
|
|
44
|
+
working-directory: solidity/evm
|
|
45
|
+
- name: Drive the contract on an EVM
|
|
46
|
+
run: node check.mjs ..
|
|
47
|
+
working-directory: solidity/evm
|
|
48
|
+
|
|
49
|
+
crash-test:
|
|
50
|
+
name: Crash test
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
container: node:22-bookworm
|
|
53
|
+
steps:
|
|
54
|
+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
|
|
55
|
+
- name: Install the crash test, on this checkout's walletcap
|
|
56
|
+
run: |
|
|
57
|
+
npm install --no-audit --no-fund --no-package-lock
|
|
58
|
+
npm install --no-save --no-audit --no-fund --no-package-lock ../js
|
|
59
|
+
working-directory: crash-test
|
|
60
|
+
- name: Check the shipped contracts match their sources
|
|
61
|
+
run: node contracts/build.mjs --check
|
|
62
|
+
working-directory: crash-test
|
|
63
|
+
- name: Run it
|
|
64
|
+
run: node --test
|
|
65
|
+
working-directory: crash-test
|
|
66
|
+
|
|
67
|
+
crash-test-agentkit:
|
|
68
|
+
name: Crash test (AgentKit)
|
|
69
|
+
runs-on: ubuntu-latest
|
|
70
|
+
container: node:22-bookworm
|
|
71
|
+
steps:
|
|
72
|
+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
|
|
73
|
+
- name: Pack the crash test
|
|
74
|
+
run: npm pack --pack-destination "$RUNNER_TEMP"
|
|
75
|
+
working-directory: crash-test
|
|
76
|
+
# As users run it: AgentKit installed alongside, walletcap from npm.
|
|
77
|
+
- name: Run it with Coinbase AgentKit alongside
|
|
78
|
+
run: npx -y -p "$RUNNER_TEMP"/walletcap-crash-test-*.tgz -p @coinbase/agentkit@0.10.4 walletcap-crash-test --agentkit --json > "$RUNNER_TEMP/agentkit.json"
|
|
79
|
+
- name: Check the AgentKit row
|
|
80
|
+
run: node crash-test/ci/check-agentkit.mjs "$RUNNER_TEMP/agentkit.json"
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
# Publish server.json to the official MCP Registry (registry.modelcontextprotocol.io), by hand.
|
|
3
|
+
# Run it once the npm release that server.json names is out: the registry checks that
|
|
4
|
+
# walletcap@<version> on npm carries "mcpName": "io.github.coriolislabs/walletcap".
|
|
5
|
+
# GitHub OIDC proves the io.github.coriolislabs namespace, so no token is stored.
|
|
6
|
+
# (mcp-publisher's interactive GitHub login can't publish to an organization namespace.)
|
|
7
|
+
name: MCP Registry
|
|
8
|
+
|
|
9
|
+
on:
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
id-token: write
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
publish:
|
|
18
|
+
name: Publish server.json
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
env:
|
|
21
|
+
MCP_PUBLISHER_VERSION: v1.8.7
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
|
|
24
|
+
- name: Check server.json names the npm package's version and mcpName
|
|
25
|
+
run: |
|
|
26
|
+
test "$(jq -r .version server.json)" = "$(jq -r .version js/package.json)"
|
|
27
|
+
test "$(jq -r '.packages[0].version' server.json)" = "$(jq -r .version js/package.json)"
|
|
28
|
+
test "$(jq -r .name server.json)" = "$(jq -r .mcpName js/package.json)"
|
|
29
|
+
- uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
|
|
30
|
+
- name: Download mcp-publisher and verify its Sigstore bundle
|
|
31
|
+
run: |
|
|
32
|
+
set -euo pipefail
|
|
33
|
+
archive=mcp-publisher_linux_amd64.tar.gz
|
|
34
|
+
base_url="https://github.com/modelcontextprotocol/registry/releases/download/${MCP_PUBLISHER_VERSION}"
|
|
35
|
+
curl --fail --location --silent --show-error --output "$archive" "$base_url/$archive"
|
|
36
|
+
curl --fail --location --silent --show-error --output "$archive.sigstore.json" "$base_url/$archive.sigstore.json"
|
|
37
|
+
cosign verify-blob \
|
|
38
|
+
--bundle "$archive.sigstore.json" \
|
|
39
|
+
--certificate-identity "https://github.com/modelcontextprotocol/registry/.github/workflows/release.yml@refs/tags/${MCP_PUBLISHER_VERSION}" \
|
|
40
|
+
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
|
|
41
|
+
"$archive"
|
|
42
|
+
tar xzf "$archive" mcp-publisher
|
|
43
|
+
rm -f "$archive" "$archive.sigstore.json"
|
|
44
|
+
- name: Log in to the registry with GitHub OIDC
|
|
45
|
+
run: ./mcp-publisher login github-oidc
|
|
46
|
+
- name: Publish server.json
|
|
47
|
+
run: ./mcp-publisher publish
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
# Publish
|
|
3
|
-
#
|
|
2
|
+
# Publish when a GitHub Release is published, or by hand.
|
|
3
|
+
# - A release tagged v<version> publishes walletcap to PyPI and npm.
|
|
4
|
+
# - A release tagged crash-test-v<version> publishes walletcap-crash-test to npm, and nothing else.
|
|
5
|
+
# Everything uses trusted publishing, so no token is stored. PyPI matches this repository,
|
|
4
6
|
# the workflow filename (publish.yml) and the "pypi" environment, and attaches PEP 740
|
|
5
|
-
# attestations. npm matches this repository, publish.yml and the "npm" environment,
|
|
6
|
-
# and attaches provenance.
|
|
7
|
+
# attestations. npm matches this repository, publish.yml and the "npm" environment, for
|
|
8
|
+
# each of the two packages, and attaches provenance.
|
|
7
9
|
name: Publish
|
|
8
10
|
|
|
9
11
|
on:
|
|
@@ -18,6 +20,7 @@ permissions:
|
|
|
18
20
|
jobs:
|
|
19
21
|
pypi:
|
|
20
22
|
name: PyPI
|
|
23
|
+
if: github.event_name != 'release' || !startsWith(github.event.release.tag_name, 'crash-test-v')
|
|
21
24
|
runs-on: ubuntu-latest
|
|
22
25
|
environment: pypi
|
|
23
26
|
steps:
|
|
@@ -43,6 +46,7 @@ jobs:
|
|
|
43
46
|
|
|
44
47
|
npm:
|
|
45
48
|
name: npm
|
|
49
|
+
if: github.event_name != 'release' || !startsWith(github.event.release.tag_name, 'crash-test-v')
|
|
46
50
|
runs-on: ubuntu-latest
|
|
47
51
|
environment: npm
|
|
48
52
|
steps:
|
|
@@ -67,3 +71,30 @@ jobs:
|
|
|
67
71
|
- name: Publish to npm with provenance
|
|
68
72
|
working-directory: js
|
|
69
73
|
run: npm publish --provenance
|
|
74
|
+
|
|
75
|
+
crash-test:
|
|
76
|
+
name: npm (crash test)
|
|
77
|
+
if: github.event_name == 'release' && startsWith(github.event.release.tag_name, 'crash-test-v')
|
|
78
|
+
runs-on: ubuntu-latest
|
|
79
|
+
environment: npm
|
|
80
|
+
steps:
|
|
81
|
+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
|
|
82
|
+
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
|
83
|
+
with:
|
|
84
|
+
node-version: "22"
|
|
85
|
+
registry-url: "https://registry.npmjs.org"
|
|
86
|
+
package-manager-cache: false
|
|
87
|
+
- name: Use an npm that supports trusted publishing (11.5.1 or later)
|
|
88
|
+
run: npm install --global npm@11.21.1
|
|
89
|
+
- name: Check the release tag matches the package version
|
|
90
|
+
env:
|
|
91
|
+
TAG: ${{ github.event.release.tag_name }}
|
|
92
|
+
run: test "$TAG" = "crash-test-v$(node -p "require('./crash-test/package.json').version")"
|
|
93
|
+
- name: Run the crash test on the walletcap users get from npm
|
|
94
|
+
working-directory: crash-test
|
|
95
|
+
run: |
|
|
96
|
+
npm install --no-audit --no-fund --no-package-lock
|
|
97
|
+
node --test
|
|
98
|
+
- name: Publish to npm with provenance
|
|
99
|
+
working-directory: crash-test
|
|
100
|
+
run: npm publish --provenance
|
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
|
2
2
|
# Changelog
|
|
3
3
|
|
|
4
|
+
## 0.2.4 — 2026-11-06
|
|
5
|
+
|
|
6
|
+
### Added
|
|
7
|
+
|
|
8
|
+
- `mcpName` in the npm package and a `server.json`, so `walletcap awal-mcp` can be listed in the
|
|
9
|
+
official MCP Registry as `io.github.coriolislabs/walletcap`. `glama.json` names the maintainer
|
|
10
|
+
for Glama.
|
|
11
|
+
- A docs site, https://coriolislabs.github.io/WalletCap/, with one page per integration, and
|
|
12
|
+
`llms.txt`.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- The `create` doc comment in `index.d.ts` said it defaulted to true. It defaults to false.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Package descriptions and search keywords on npm and PyPI, and a README that leads with the
|
|
21
|
+
crash test.
|
|
22
|
+
|
|
4
23
|
## 0.2.3 — 2026-11-06
|
|
5
24
|
|
|
6
25
|
### Changed
|
|
@@ -1,17 +1,84 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: walletcap
|
|
3
|
+
Version: 0.2.4
|
|
4
|
+
Summary: Spend limits for AI agent wallets: a per-payment cap and rolling 24-hour budget that holds across restarts, kept in a SQLite file every process and the npm package share.
|
|
5
|
+
Project-URL: Homepage, https://github.com/coriolislabs/WalletCap
|
|
6
|
+
Project-URL: Repository, https://github.com/coriolislabs/WalletCap
|
|
7
|
+
Project-URL: Issues, https://github.com/coriolislabs/WalletCap/issues
|
|
8
|
+
Author: Coriolis Labs Inc.
|
|
9
|
+
License-Expression: Apache-2.0
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
License-File: NOTICE
|
|
12
|
+
Keywords: agent-payments,agent-wallet,ai-agent,ai-agents,budget,guardrails,spend-limit,spending-limit,stablecoin,usdc,x402
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
1
24
|
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
|
2
|
-
# walletcap
|
|
25
|
+
# walletcap: spend limits for AI agent wallets
|
|
26
|
+
|
|
27
|
+
[](https://www.npmjs.com/package/walletcap)
|
|
28
|
+
[](https://pypi.org/project/walletcap/)
|
|
29
|
+
[](https://github.com/coriolislabs/WalletCap/actions/workflows/ci.yml)
|
|
30
|
+
[](https://github.com/coriolislabs/WalletCap/blob/main/LICENSE)
|
|
31
|
+
|
|
32
|
+
**Spend limits for AI agent wallets that pay in USDC: a per-payment cap and a rolling 24-hour
|
|
33
|
+
budget that holds across restarts, replicas and payment rails.** walletcap plugs into x402
|
|
34
|
+
clients, Coinbase CDP's x402 spend controls, Coinbase AgentKit, the Coinbase Agentic Wallet CLI
|
|
35
|
+
and payments MCP server, and Coinbase Spend Permissions. By ShadowPath.
|
|
36
|
+
|
|
37
|
+
## Crash test: CDP's controls let $1,600–$1,700 past a $150 cap, walletcap lets $0
|
|
38
|
+
|
|
39
|
+
`npx walletcap-crash-test` puts Coinbase's agent spend controls through four ordinary events (a
|
|
40
|
+
restart, 10 replicas, 10 replicas on a shared store, and a payee who asks for EURC), then puts
|
|
41
|
+
walletcap through the same events. CDP's x402 controls are set as Coinbase's README shows, then
|
|
42
|
+
run again on walletcap's `cdpStore` as this README shows. Spend Permissions run Coinbase's
|
|
43
|
+
deployed contract code on a local EVM. Every agent is held to $50 a payment and $150 in any 24
|
|
44
|
+
hours, in USDC on Base. It runs offline in about 15 seconds and sends nothing.
|
|
45
|
+
|
|
46
|
+
```console
|
|
47
|
+
$ npx walletcap-crash-test
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
| CDP x402 spend controls | CDP's controls | walletcap guard | walletcap cdpStore |
|
|
51
|
+
|---|---|---|---|
|
|
52
|
+
| restart, then pay again | $300 signed · $150 over | $150 signed · $0 over | $150 signed · $0 over |
|
|
53
|
+
| 10 replicas | $1,500 signed · $1,350 over | $150 signed · $0 over | $150 signed · $0 over |
|
|
54
|
+
| 10 replicas, shared store 1 ms away | $350 signed · $200 over | $150 signed · $0 over | $150 signed · $0 over |
|
|
55
|
+
| payee asks for EURC, not USDC | 1,000 EURC signed, counted as $0 | refused before signing | refused before signing |
|
|
3
56
|
|
|
4
|
-
|
|
57
|
+
| Spend Permissions | SpendPermissionManager | AccountCapSpender |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| a second permission | $300 pulled · $150 over | $150 pulled · $0 over |
|
|
60
|
+
| across a period boundary, 1 second apart | $300 pulled · $150 over | $150 pulled · $0 over |
|
|
5
61
|
|
|
6
|
-
|
|
62
|
+
Past the $150 cap: $1,700 and 1,000 EURC with CDP's controls, $300 with Spend Permissions; $0
|
|
63
|
+
with walletcap's guard, its cdpStore and AccountCapSpender. The shared-store row varies from
|
|
64
|
+
run to run: in eight runs on 6 November 2026 it was $100 over five times and $200 over three
|
|
65
|
+
times. Those runs used `@coinbase/cdp-sdk` 1.61.0, `@x402/core` 2.30.0, SpendPermissionManager
|
|
66
|
+
1.0.0 and walletcap 0.2.3.
|
|
7
67
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
68
|
+
Add `--agentkit` for Coinbase AgentKit's row: the agent approves a 1¢ offer, and AgentKit signs
|
|
69
|
+
the merchant's first-listed $1.00 on Base mainnet. walletcap, at 2¢ a payment, refuses it before
|
|
70
|
+
signing. [The crash test's README](https://github.com/coriolislabs/WalletCap/tree/main/crash-test)
|
|
71
|
+
says exactly what runs.
|
|
12
72
|
|
|
13
|
-
|
|
14
|
-
|
|
73
|
+
## Install and use
|
|
74
|
+
|
|
75
|
+
```console
|
|
76
|
+
$ npm install walletcap # Node 22.13+, no dependencies
|
|
77
|
+
$ pip install walletcap # Python 3.11+, no dependencies
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The owner creates the budget once. Opening it never creates one; pass `create: true` only for a
|
|
81
|
+
demo or first-run setup:
|
|
15
82
|
|
|
16
83
|
```console
|
|
17
84
|
$ npx walletcap set --wallet 0xYourAgentWallet --per-payment 50 --per-day 150
|
|
@@ -34,8 +101,18 @@ with budget.pay("$12.50"):
|
|
|
34
101
|
send_usdc(payee, "12.50")
|
|
35
102
|
```
|
|
36
103
|
|
|
37
|
-
|
|
38
|
-
|
|
104
|
+
| Integration | Install | Use |
|
|
105
|
+
|---|---|---|
|
|
106
|
+
| [Any x402 client](https://github.com/coriolislabs/WalletCap/blob/main/docs/x402-spending-limit.md) (`@x402/core`, `@x402/fetch`) | `npm install walletcap` | `budget.guard(client)` |
|
|
107
|
+
| [Coinbase CDP x402 spend controls](https://github.com/coriolislabs/WalletCap/blob/main/docs/coinbase-cdp-spend-controls.md) | `npm install walletcap @coinbase/cdp-sdk` | `store: budget.cdpStore({ asset: USDC })` in `applySpendControls` |
|
|
108
|
+
| [Coinbase AgentKit](https://github.com/coriolislabs/WalletCap/blob/main/docs/coinbase-agentkit-spending-limit.md) | `npm install walletcap @coinbase/agentkit` | `budget.guardAgentKit(new X402ActionProvider())` |
|
|
109
|
+
| [Coinbase Agentic Wallet CLI](https://github.com/coriolislabs/WalletCap/blob/main/docs/coinbase-agentic-wallet-budget.md) | `npm install walletcap awal` | `npx walletcap awal x402 pay <url>` |
|
|
110
|
+
| [Coinbase payments MCP server](https://github.com/coriolislabs/WalletCap/blob/main/docs/coinbase-agentic-wallet-budget.md#the-mcp-server-one-entry-in-the-clients-config) | `npx @coinbase/payments-mcp install --client other --no-auto-config` | MCP server command: `npx walletcap awal-mcp --wallet 0x…` |
|
|
111
|
+
| [Coinbase Spend Permissions](https://github.com/coriolislabs/WalletCap/blob/main/docs/coinbase-spend-permissions-cap.md) | deploy `solidity/src/AccountCapSpender.sol` (testnet only, unaudited) | the agent calls `pay(permission, amount, payee)` |
|
|
112
|
+
| [Python](https://github.com/coriolislabs/WalletCap/blob/main/docs/python-agent-spending-limit.md) | `pip install walletcap` | `with budget.pay("$12.50"):` |
|
|
113
|
+
|
|
114
|
+
Each link opens a page with a full snippet. The [Use it](#use-it) section below covers every
|
|
115
|
+
integration too.
|
|
39
116
|
|
|
40
117
|
## Try it without a wallet
|
|
41
118
|
|
|
@@ -298,7 +375,10 @@ only for a demo or a first-run setup.
|
|
|
298
375
|
| `js/` | the npm package `walletcap`: the budget, the x402 guard, the CDP store, the CLI, and the Agentic Wallet CLI wrapper and MCP proxy |
|
|
299
376
|
| `src/walletcap/` | the PyPI package `walletcap`, on the same file format |
|
|
300
377
|
| `solidity/` | `AccountCapSpender`, the on-chain cap for Coinbase Spend Permissions |
|
|
378
|
+
| `crash-test/` | the crash test: CDP's spend controls and walletcap through the same events, in dollars |
|
|
301
379
|
| `tests/` | the Python suite, including the tests that drive both languages against one budget file |
|
|
380
|
+
| `docs/` | the docs site for GitHub Pages: one page per integration, each with a full snippet, plus the threat model |
|
|
381
|
+
| `llms.txt` | a summary of the package and links to the docs, for language models |
|
|
302
382
|
|
|
303
383
|
```console
|
|
304
384
|
$ cd js && npm install && node --test # 65 tests
|
|
@@ -1,40 +1,61 @@
|
|
|
1
|
-
Metadata-Version: 2.5
|
|
2
|
-
Name: walletcap
|
|
3
|
-
Version: 0.2.3
|
|
4
|
-
Summary: One spend budget per wallet for AI agents: counted across every process, replica, key, permission and payment rail.
|
|
5
|
-
Project-URL: Homepage, https://github.com/coriolislabs/WalletCap
|
|
6
|
-
Project-URL: Repository, https://github.com/coriolislabs/WalletCap
|
|
7
|
-
Project-URL: Issues, https://github.com/coriolislabs/WalletCap/issues
|
|
8
|
-
Author: Coriolis Labs Inc.
|
|
9
|
-
License-Expression: Apache-2.0
|
|
10
|
-
License-File: LICENSE
|
|
11
|
-
License-File: NOTICE
|
|
12
|
-
Keywords: agent-payments,ai-agents,budget,guardrails,spend-limit,stablecoin,usdc,x402
|
|
13
|
-
Classifier: Development Status :: 4 - Beta
|
|
14
|
-
Classifier: Intended Audience :: Developers
|
|
15
|
-
Classifier: Programming Language :: Python :: 3
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
-
Classifier: Topic :: Software Development :: Libraries
|
|
20
|
-
Classifier: Typing :: Typed
|
|
21
|
-
Requires-Python: >=3.11
|
|
22
|
-
Description-Content-Type: text/markdown
|
|
23
|
-
|
|
24
1
|
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
|
25
|
-
# walletcap
|
|
2
|
+
# walletcap: spend limits for AI agent wallets
|
|
3
|
+
|
|
4
|
+
[](https://www.npmjs.com/package/walletcap)
|
|
5
|
+
[](https://pypi.org/project/walletcap/)
|
|
6
|
+
[](https://github.com/coriolislabs/WalletCap/actions/workflows/ci.yml)
|
|
7
|
+
[](https://github.com/coriolislabs/WalletCap/blob/main/LICENSE)
|
|
8
|
+
|
|
9
|
+
**Spend limits for AI agent wallets that pay in USDC: a per-payment cap and a rolling 24-hour
|
|
10
|
+
budget that holds across restarts, replicas and payment rails.** walletcap plugs into x402
|
|
11
|
+
clients, Coinbase CDP's x402 spend controls, Coinbase AgentKit, the Coinbase Agentic Wallet CLI
|
|
12
|
+
and payments MCP server, and Coinbase Spend Permissions. By ShadowPath.
|
|
13
|
+
|
|
14
|
+
## Crash test: CDP's controls let $1,600–$1,700 past a $150 cap, walletcap lets $0
|
|
15
|
+
|
|
16
|
+
`npx walletcap-crash-test` puts Coinbase's agent spend controls through four ordinary events (a
|
|
17
|
+
restart, 10 replicas, 10 replicas on a shared store, and a payee who asks for EURC), then puts
|
|
18
|
+
walletcap through the same events. CDP's x402 controls are set as Coinbase's README shows, then
|
|
19
|
+
run again on walletcap's `cdpStore` as this README shows. Spend Permissions run Coinbase's
|
|
20
|
+
deployed contract code on a local EVM. Every agent is held to $50 a payment and $150 in any 24
|
|
21
|
+
hours, in USDC on Base. It runs offline in about 15 seconds and sends nothing.
|
|
22
|
+
|
|
23
|
+
```console
|
|
24
|
+
$ npx walletcap-crash-test
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
| CDP x402 spend controls | CDP's controls | walletcap guard | walletcap cdpStore |
|
|
28
|
+
|---|---|---|---|
|
|
29
|
+
| restart, then pay again | $300 signed · $150 over | $150 signed · $0 over | $150 signed · $0 over |
|
|
30
|
+
| 10 replicas | $1,500 signed · $1,350 over | $150 signed · $0 over | $150 signed · $0 over |
|
|
31
|
+
| 10 replicas, shared store 1 ms away | $350 signed · $200 over | $150 signed · $0 over | $150 signed · $0 over |
|
|
32
|
+
| payee asks for EURC, not USDC | 1,000 EURC signed, counted as $0 | refused before signing | refused before signing |
|
|
26
33
|
|
|
27
|
-
|
|
34
|
+
| Spend Permissions | SpendPermissionManager | AccountCapSpender |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| a second permission | $300 pulled · $150 over | $150 pulled · $0 over |
|
|
37
|
+
| across a period boundary, 1 second apart | $300 pulled · $150 over | $150 pulled · $0 over |
|
|
28
38
|
|
|
29
|
-
|
|
39
|
+
Past the $150 cap: $1,700 and 1,000 EURC with CDP's controls, $300 with Spend Permissions; $0
|
|
40
|
+
with walletcap's guard, its cdpStore and AccountCapSpender. The shared-store row varies from
|
|
41
|
+
run to run: in eight runs on 6 November 2026 it was $100 over five times and $200 over three
|
|
42
|
+
times. Those runs used `@coinbase/cdp-sdk` 1.61.0, `@x402/core` 2.30.0, SpendPermissionManager
|
|
43
|
+
1.0.0 and walletcap 0.2.3.
|
|
30
44
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
45
|
+
Add `--agentkit` for Coinbase AgentKit's row: the agent approves a 1¢ offer, and AgentKit signs
|
|
46
|
+
the merchant's first-listed $1.00 on Base mainnet. walletcap, at 2¢ a payment, refuses it before
|
|
47
|
+
signing. [The crash test's README](https://github.com/coriolislabs/WalletCap/tree/main/crash-test)
|
|
48
|
+
says exactly what runs.
|
|
35
49
|
|
|
36
|
-
|
|
37
|
-
|
|
50
|
+
## Install and use
|
|
51
|
+
|
|
52
|
+
```console
|
|
53
|
+
$ npm install walletcap # Node 22.13+, no dependencies
|
|
54
|
+
$ pip install walletcap # Python 3.11+, no dependencies
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The owner creates the budget once. Opening it never creates one; pass `create: true` only for a
|
|
58
|
+
demo or first-run setup:
|
|
38
59
|
|
|
39
60
|
```console
|
|
40
61
|
$ npx walletcap set --wallet 0xYourAgentWallet --per-payment 50 --per-day 150
|
|
@@ -57,8 +78,18 @@ with budget.pay("$12.50"):
|
|
|
57
78
|
send_usdc(payee, "12.50")
|
|
58
79
|
```
|
|
59
80
|
|
|
60
|
-
|
|
61
|
-
|
|
81
|
+
| Integration | Install | Use |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| [Any x402 client](https://github.com/coriolislabs/WalletCap/blob/main/docs/x402-spending-limit.md) (`@x402/core`, `@x402/fetch`) | `npm install walletcap` | `budget.guard(client)` |
|
|
84
|
+
| [Coinbase CDP x402 spend controls](https://github.com/coriolislabs/WalletCap/blob/main/docs/coinbase-cdp-spend-controls.md) | `npm install walletcap @coinbase/cdp-sdk` | `store: budget.cdpStore({ asset: USDC })` in `applySpendControls` |
|
|
85
|
+
| [Coinbase AgentKit](https://github.com/coriolislabs/WalletCap/blob/main/docs/coinbase-agentkit-spending-limit.md) | `npm install walletcap @coinbase/agentkit` | `budget.guardAgentKit(new X402ActionProvider())` |
|
|
86
|
+
| [Coinbase Agentic Wallet CLI](https://github.com/coriolislabs/WalletCap/blob/main/docs/coinbase-agentic-wallet-budget.md) | `npm install walletcap awal` | `npx walletcap awal x402 pay <url>` |
|
|
87
|
+
| [Coinbase payments MCP server](https://github.com/coriolislabs/WalletCap/blob/main/docs/coinbase-agentic-wallet-budget.md#the-mcp-server-one-entry-in-the-clients-config) | `npx @coinbase/payments-mcp install --client other --no-auto-config` | MCP server command: `npx walletcap awal-mcp --wallet 0x…` |
|
|
88
|
+
| [Coinbase Spend Permissions](https://github.com/coriolislabs/WalletCap/blob/main/docs/coinbase-spend-permissions-cap.md) | deploy `solidity/src/AccountCapSpender.sol` (testnet only, unaudited) | the agent calls `pay(permission, amount, payee)` |
|
|
89
|
+
| [Python](https://github.com/coriolislabs/WalletCap/blob/main/docs/python-agent-spending-limit.md) | `pip install walletcap` | `with budget.pay("$12.50"):` |
|
|
90
|
+
|
|
91
|
+
Each link opens a page with a full snippet. The [Use it](#use-it) section below covers every
|
|
92
|
+
integration too.
|
|
62
93
|
|
|
63
94
|
## Try it without a wallet
|
|
64
95
|
|
|
@@ -321,7 +352,10 @@ only for a demo or a first-run setup.
|
|
|
321
352
|
| `js/` | the npm package `walletcap`: the budget, the x402 guard, the CDP store, the CLI, and the Agentic Wallet CLI wrapper and MCP proxy |
|
|
322
353
|
| `src/walletcap/` | the PyPI package `walletcap`, on the same file format |
|
|
323
354
|
| `solidity/` | `AccountCapSpender`, the on-chain cap for Coinbase Spend Permissions |
|
|
355
|
+
| `crash-test/` | the crash test: CDP's spend controls and walletcap through the same events, in dollars |
|
|
324
356
|
| `tests/` | the Python suite, including the tests that drive both languages against one budget file |
|
|
357
|
+
| `docs/` | the docs site for GitHub Pages: one page per integration, each with a full snippet, plus the threat model |
|
|
358
|
+
| `llms.txt` | a summary of the package and links to the docs, for language models |
|
|
325
359
|
|
|
326
360
|
```console
|
|
327
361
|
$ cd js && npm install && node --test # 65 tests
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
|
2
|
+
# walletcap crash test
|
|
3
|
+
|
|
4
|
+
This puts Coinbase's agent spend controls through the events that hand an AI agent a fresh budget, runs walletcap through the same events, and counts what gets past the cap.
|
|
5
|
+
|
|
6
|
+
| Control | Events |
|
|
7
|
+
|---|---|
|
|
8
|
+
| CDP's x402 controls, on their own store and on walletcap's | a restart, replicas, a shared store, a payee who switches assets |
|
|
9
|
+
| Spend Permissions | a second permission, a period boundary |
|
|
10
|
+
| AgentKit (`--agentkit`) | a merchant who lists a bigger offer first |
|
|
11
|
+
|
|
12
|
+
It runs offline in under fifteen seconds and sends nothing.
|
|
13
|
+
|
|
14
|
+
```console
|
|
15
|
+
$ npx walletcap-crash-test
|
|
16
|
+
|
|
17
|
+
walletcap crash test: Coinbase's agent spend controls
|
|
18
|
+
@coinbase/cdp-sdk 1.61.0 · @x402/core 2.30.0 · SpendPermissionManager 1.0.0 · walletcap 0.2.3
|
|
19
|
+
Every agent is held to $50 a payment and $150 in any 24 hours, in USDC on Base.
|
|
20
|
+
|
|
21
|
+
CDP x402 spend controls CDP's controls walletcap guard walletcap cdpStore
|
|
22
|
+
restart, then pay again $300 signed · $150 over $150 signed · $0 over $150 signed · $0 over
|
|
23
|
+
10 replicas $1,500 signed · $1,350 over $150 signed · $0 over $150 signed · $0 over
|
|
24
|
+
10 replicas, shared store 1 ms away $350 signed · $200 over $150 signed · $0 over $150 signed · $0 over
|
|
25
|
+
payee asks for EURC, not USDC 1,000 EURC signed, counted as $0 refused before signing refused before signing
|
|
26
|
+
|
|
27
|
+
Spend Permissions SpendPermissionManager AccountCapSpender
|
|
28
|
+
a second permission $300 pulled · $150 over $150 pulled · $0 over
|
|
29
|
+
across a period boundary, 1 second apart $300 pulled · $150 over $150 pulled · $0 over
|
|
30
|
+
|
|
31
|
+
Past the $150 cap: $1,700 and 1,000 EURC with CDP's controls, $300 with Spend Permissions;
|
|
32
|
+
$0 with walletcap's guard and AccountCapSpender; $0 with CDP's controls on walletcap's cdpStore.
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
It needs Node 22.13 or later. Add `--json` for machine-readable results; each event's `cdp`, `walletcap` and `cdpStore` hold the three columns. The process exits 1 if walletcap's guard, CDP's controls on walletcap's cdpStore, or any other walletcap control lets anything past the cap.
|
|
36
|
+
|
|
37
|
+
To run it from this repository instead: `cd crash-test && npm install && npm start`.
|
|
38
|
+
|
|
39
|
+
## What runs
|
|
40
|
+
|
|
41
|
+
Every agent is a separate Node process with its own throwaway key. It builds an `@x402/core` client with the exact EVM scheme and tries its payments.
|
|
42
|
+
|
|
43
|
+
The three controls:
|
|
44
|
+
- **CDP's controls:** `applySpendControls` from `@coinbase/cdp-sdk/x402`, the same guardrails `CdpX402Client` uses. The settings follow Coinbase's README example: per-payment and cumulative caps in USDC, Base only, and no asset allowlist. Like `CdpX402Client`, the agent turns off x402's own default cap.
|
|
45
|
+
- **walletcap guard:** `budget.guard()` on the same client. The owner sets the budget once, and every agent opens the same file.
|
|
46
|
+
- **walletcap cdpStore:** CDP's own `applySpendControls` again, set exactly as [walletcap's README](https://github.com/coriolislabs/WalletCap#coinbase-cdp-spend-controls) shows: the same caps, `allowedAssets: [USDC]`, and `store: budget.cdpStore({ asset: USDC })`. The owner sets the budget once, and every agent, replica or restart opens the same file, so CDP's ledger is that file.
|
|
47
|
+
|
|
48
|
+
The events, each from a fresh start, once per control:
|
|
49
|
+
|
|
50
|
+
| Event | What happens |
|
|
51
|
+
|---|---|
|
|
52
|
+
| Restart | One process pays until it is refused. A second process, the restart, pays again. |
|
|
53
|
+
| 10 replicas | Ten processes start together and pay. |
|
|
54
|
+
| 10 replicas, shared store | The same, with CDP's ledger in one shared store built to its `SpendStore` interface. In the cdpStore column, walletcap's store answers each call after the same 1 ms. |
|
|
55
|
+
| EURC instead of USDC | The payee asks for 1,000 EURC. |
|
|
56
|
+
|
|
57
|
+
The shared store is what Coinbase's docs advise for replicas: "implement this interface against a shared durable backend (Redis, Postgres, DynamoDB, etc.)". The store in `spend-store.mjs` does exactly what the interface says, and answers each call after 1 ms, as a network database does.
|
|
58
|
+
|
|
59
|
+
The interface has no single step that both checks the cap and records the payment. CDP reads the total, decides, then appends, and its lock covers one process. Replicas can read the same total before any of them appends. How many overlap varies from run to run.
|
|
60
|
+
|
|
61
|
+
walletcap's cdpStore sits behind the same interface, so CDP still reads, decides, then appends. Its `append` re-checks the cap inside one SQLite write transaction and throws if the payment would go past it. CDP appends before it signs, so a payment the store refuses is never signed. In the replica rows, the re-check usually refuses a few payments that CDP's own check had passed (`budget_budget` in `--json`); how many varies from run to run. In the EURC row, CDP's `allowedAssets`, which walletcap's README sets, refuses before the store is asked.
|
|
62
|
+
|
|
63
|
+
## Coinbase Spend Permissions
|
|
64
|
+
|
|
65
|
+
Coinbase's `SpendPermissionManager` v1.0.0 and Smart Wallet run on an in-process EVM. Their code is the exact runtime code deployed on Base mainnet, read once with `eth_getCode` and shipped in `contracts/coinbase-base-mainnet.json` with each code hash, so the crash test needs no network.
|
|
66
|
+
|
|
67
|
+
A Smart Wallet holds $1,000 of a test token that stands in for USDC, and grants the agent permissions of $150 a day.
|
|
68
|
+
|
|
69
|
+
| Event | What happens |
|
|
70
|
+
|---|---|
|
|
71
|
+
| A second permission | The wallet grants two permissions with different salts, and the agent pulls $150 from each. |
|
|
72
|
+
| A period boundary | The agent pulls $150 in the last second of one day and $150 in the first second of the next. |
|
|
73
|
+
|
|
74
|
+
The manager counts each permission, and each period, on its own, so both events pull $300. Within one permission and one period it holds: the test suite checks that a fourth $50 is refused with `ExceededSpendPermission`.
|
|
75
|
+
|
|
76
|
+
walletcap's side: the wallet grants the same permissions to `AccountCapSpender`, walletcap's on-chain spender. It counts every permission against one rolling $150 cap and refuses the second $150 with `OverBudget`. `AccountCapSpender` is unaudited.
|
|
77
|
+
|
|
78
|
+
`node contracts/build.mjs --check` checks two things: that each piece of Coinbase code still matches its recorded hash, and that the shipped `AccountCapSpender` still compiles from `solidity/`. `--fetch` re-reads Coinbase's code from Base mainnet.
|
|
79
|
+
|
|
80
|
+
## Coinbase AgentKit (`--agentkit`)
|
|
81
|
+
|
|
82
|
+
```console
|
|
83
|
+
$ npx -p walletcap-crash-test -p @coinbase/agentkit@0.10.4 walletcap-crash-test --agentkit
|
|
84
|
+
|
|
85
|
+
Coinbase AgentKit 0.10.4: the agent approves the merchant's 1¢ offer on Base Sepolia; the merchant
|
|
86
|
+
lists $1.00 on Base mainnet, to another address, first.
|
|
87
|
+
|
|
88
|
+
AgentKit signed $1.00 on Base mainnet to the first-listed address, valid 4 days; reported $0.01 on Base Sepolia
|
|
89
|
+
walletcap, 2¢ a payment refused before signing
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The AgentKit row runs AgentKit's own `retry_http_request_with_x402` action against a merchant on `127.0.0.1`. The agent hands it the 1¢ offer it approved, which is how AgentKit's flow works.
|
|
93
|
+
|
|
94
|
+
What AgentKit does with it:
|
|
95
|
+
- It checks only that the approved offer's network is one the wallet supports.
|
|
96
|
+
- It then builds a fresh x402 client, which pays whatever the merchant listed first.
|
|
97
|
+
- Its answer reports the approved offer, not the one it signed.
|
|
98
|
+
|
|
99
|
+
walletcap's `budget.guardAgentKit()`, at 2¢ a payment, refuses the $1.00 before anything is signed.
|
|
100
|
+
|
|
101
|
+
AgentKit is opt-in because it installs about 1.3 GB. Its wallet providers also send an analytics event with the wallet's address when they start. The crash test turns that off and blocks every request except the one to the local merchant.
|
|
102
|
+
|
|
103
|
+
## What "signed" means
|
|
104
|
+
|
|
105
|
+
Nothing is sent. Each payment is an x402 authorization (EIP-3009) signed with a key that holds nothing. A payee holding one could settle it on Base until it expires, so signing is the moment the money is committed. The crash test counts what each control lets the agent sign.
|
|
106
|
+
|
|
107
|
+
## What it doesn't cover
|
|
108
|
+
|
|
109
|
+
- **Settlement of x402 payments.** For x402 it measures what the client-side control lets the agent sign, not what lands on chain. The Spend Permissions rows do move tokens on the local EVM.
|
|
110
|
+
- **More than one machine.** The replicas share one machine, and walletcap's budget file, behind both its guard and its cdpStore, is single-host.
|
|
111
|
+
- **A revoke in the same block.** A revoke that lands after the agent's payment in the same block doesn't stop that payment, with either control. Neither control can make a revoke retroactive.
|
|
112
|
+
- **Other vendors' controls.** Coinbase's CDP x402 controls, Spend Permissions and AgentKit are covered so far. The Agentic Wallet, Safe, MetaMask, Tempo and AP2 come next.
|
|
113
|
+
|
|
114
|
+
Coinbase's contract code in `contracts/coinbase-base-mainnet.json` comes from [coinbase/spend-permissions](https://github.com/coinbase/spend-permissions) and [coinbase/smart-wallet](https://github.com/coinbase/smart-wallet), both under the MIT license.
|
|
115
|
+
|
|
116
|
+
## Releasing
|
|
117
|
+
|
|
118
|
+
To release a new version:
|
|
119
|
+
1. Bump `version` in `crash-test/package.json` and merge the change.
|
|
120
|
+
2. Publish a GitHub Release tagged `crash-test-v<version>`. Untick "Set as the latest release", so walletcap's own release stays the latest.
|
|
121
|
+
|
|
122
|
+
The Publish workflow then runs the crash test against the walletcap on npm and publishes with provenance. Releases tagged `v<version>` publish walletcap only.
|
|
123
|
+
|
|
124
|
+
To have the same measurement run against your own agent, inside your walls, with every control on and a signed result, [ask for a ShadowPath report](mailto:paul@coriolislabs.ca).
|