agentcard 0.0.22 → 0.0.24
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/dist/src/commands/3ds.d.ts +1 -0
- package/dist/src/commands/3ds.js +45 -0
- package/dist/src/commands/3ds.js.map +1 -0
- package/dist/src/commands/setup.js +43 -6
- package/dist/src/commands/setup.js.map +1 -1
- package/dist/src/commands/signup.js +1 -1
- package/dist/src/commands/signup.js.map +1 -1
- package/dist/src/commands/wallet/balance.d.ts +1 -0
- package/dist/src/commands/wallet/balance.js +19 -0
- package/dist/src/commands/wallet/balance.js.map +1 -0
- package/dist/src/commands/wallet/fetch.d.ts +8 -0
- package/dist/src/commands/wallet/fetch.js +147 -0
- package/dist/src/commands/wallet/fetch.js.map +1 -0
- package/dist/src/commands/wallet/info.d.ts +1 -0
- package/dist/src/commands/wallet/info.js +29 -0
- package/dist/src/commands/wallet/info.js.map +1 -0
- package/dist/src/commands/wallet/send.d.ts +6 -0
- package/dist/src/commands/wallet/send.js +80 -0
- package/dist/src/commands/wallet/send.js.map +1 -0
- package/dist/src/commands/whoami.js +12 -0
- package/dist/src/commands/whoami.js.map +1 -1
- package/dist/src/index.js +38 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/lib/api.d.ts +7 -0
- package/dist/src/lib/api.js +28 -2
- package/dist/src/lib/api.js.map +1 -1
- package/dist/src/lib/policy-intent.d.ts +13 -0
- package/dist/src/lib/policy-intent.js +95 -0
- package/dist/src/lib/policy-intent.js.map +1 -0
- package/dist/src/lib/privy.d.ts +19 -0
- package/dist/src/lib/privy.js +214 -0
- package/dist/src/lib/privy.js.map +1 -0
- package/dist/src/lib/smart-wallet.d.ts +13 -0
- package/dist/src/lib/smart-wallet.js +90 -0
- package/dist/src/lib/smart-wallet.js.map +1 -0
- package/dist/src/lib/usdc.d.ts +11088 -0
- package/dist/src/lib/usdc.js +42 -0
- package/dist/src/lib/usdc.js.map +1 -0
- package/package.json +7 -2
package/dist/src/index.js
CHANGED
|
@@ -11,10 +11,15 @@ import { limit } from "./commands/limit.js";
|
|
|
11
11
|
import { requestNew } from "./commands/request/new.js";
|
|
12
12
|
import { requestGet } from "./commands/request/get.js";
|
|
13
13
|
import { support } from "./commands/support.js";
|
|
14
|
+
import { threeDS } from "./commands/3ds.js";
|
|
14
15
|
import { mailInfo } from "./commands/mail/info.js";
|
|
15
16
|
import { mailList } from "./commands/mail/list.js";
|
|
16
17
|
import { mailGet } from "./commands/mail/get.js";
|
|
17
18
|
import { mailSend, mailReply } from "./commands/mail/send.js";
|
|
19
|
+
import { walletInfo } from "./commands/wallet/info.js";
|
|
20
|
+
import { walletBalance } from "./commands/wallet/balance.js";
|
|
21
|
+
import { walletSend } from "./commands/wallet/send.js";
|
|
22
|
+
import { walletFetch } from "./commands/wallet/fetch.js";
|
|
18
23
|
import { getLocalVersion } from "./lib/update-check.js";
|
|
19
24
|
import { attachCommandTracking } from "./lib/track-command.js";
|
|
20
25
|
const program = new Command();
|
|
@@ -33,6 +38,7 @@ Examples:
|
|
|
33
38
|
$ agentcard limit Show spend limit / spent / remaining
|
|
34
39
|
$ agentcard limit --amount 250 Raise your spend limit to $250
|
|
35
40
|
$ agentcard request new --amount 10 Issue a single-use $10 Visa card
|
|
41
|
+
$ agentcard 3ds List recent 3DS verification codes
|
|
36
42
|
$ agentcard request get <id> Re-fetch PAN/CVV/expiry for a request
|
|
37
43
|
$ agentcard request get List all your card requests
|
|
38
44
|
$ agentcard mail list List agent email threads
|
|
@@ -73,7 +79,7 @@ program
|
|
|
73
79
|
// -- Setup & limit ----------------------------------------------------------
|
|
74
80
|
program
|
|
75
81
|
.command("setup")
|
|
76
|
-
.description("Set up or update your
|
|
82
|
+
.description("Set up or update your payment method and optional profile")
|
|
77
83
|
.option("--first-name <name>", "First name")
|
|
78
84
|
.option("--last-name <name>", "Last name")
|
|
79
85
|
.option("--phone <phone>", "Phone number in E.164 format, e.g. +14155551234")
|
|
@@ -98,6 +104,10 @@ request
|
|
|
98
104
|
.description("Get one request by ID, or list all requests")
|
|
99
105
|
.argument("[id]", "Request ID")
|
|
100
106
|
.action(requestGet);
|
|
107
|
+
program
|
|
108
|
+
.command("3ds")
|
|
109
|
+
.description("List 3DS verification codes received in the last 5 minutes")
|
|
110
|
+
.action(threeDS);
|
|
101
111
|
// -- Legacy inventory cards -------------------------------------------------
|
|
102
112
|
program
|
|
103
113
|
.command("create")
|
|
@@ -155,6 +165,33 @@ mail
|
|
|
155
165
|
.argument("<thread-id>", "Thread ID")
|
|
156
166
|
.option("--body <body>", "Reply body")
|
|
157
167
|
.action((threadId, opts) => mailReply(threadId, opts));
|
|
168
|
+
// -- Wallet -----------------------------------------------------------------
|
|
169
|
+
const wallet = program
|
|
170
|
+
.command("wallet")
|
|
171
|
+
.description("Self-custodial USDC wallet on Base (gas sponsored)");
|
|
172
|
+
wallet
|
|
173
|
+
.command("info")
|
|
174
|
+
.description("Show wallet address and USDC balance")
|
|
175
|
+
.action(walletInfo);
|
|
176
|
+
wallet
|
|
177
|
+
.command("balance")
|
|
178
|
+
.description("Print USDC balance (scriptable)")
|
|
179
|
+
.action(walletBalance);
|
|
180
|
+
wallet
|
|
181
|
+
.command("send")
|
|
182
|
+
.description("Send USDC on Base (gas sponsored)")
|
|
183
|
+
.option("--to <address>", "Recipient address (0x...)")
|
|
184
|
+
.option("--amount <usdc>", "Amount in USDC (e.g. 1.5)")
|
|
185
|
+
.action(walletSend);
|
|
186
|
+
wallet
|
|
187
|
+
.command("fetch")
|
|
188
|
+
.description("Fetch a URL with x402 auto-payment (USDC on Base)")
|
|
189
|
+
.argument("<url>", "URL to fetch")
|
|
190
|
+
.option("-X, --method <method>", "HTTP method (default GET)")
|
|
191
|
+
.option("-H, --header <header...>", 'Header line, "Key: Value"')
|
|
192
|
+
.option("-d, --data <body>", "Request body")
|
|
193
|
+
.option("--max-cost <usdc>", "Maximum USDC the call can charge")
|
|
194
|
+
.action(walletFetch);
|
|
158
195
|
// -- Support ----------------------------------------------------------------
|
|
159
196
|
program
|
|
160
197
|
.command("support")
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAC9B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAE/B,OAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,uDAAuD,CAAC;KACpE,OAAO,CAAC,eAAe,EAAE,CAAC;KAC1B,kBAAkB,EAAE;KACpB,WAAW,CACV,OAAO,EACP
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/src/lib/api.d.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
export declare const API_URL: string;
|
|
2
|
+
export declare class ApiError extends Error {
|
|
3
|
+
status: number;
|
|
4
|
+
body: unknown;
|
|
5
|
+
constructor(message: string, status: number, body: unknown);
|
|
6
|
+
}
|
|
1
7
|
interface ApiOptions {
|
|
2
8
|
auth?: boolean;
|
|
3
9
|
}
|
|
10
|
+
export declare function requireAuthToken(): string;
|
|
4
11
|
export declare function get<T>(path: string, options?: ApiOptions): Promise<T>;
|
|
5
12
|
export declare function post<T>(path: string, body?: unknown, options?: ApiOptions): Promise<T>;
|
|
6
13
|
export declare function patch<T>(path: string, body?: unknown, options?: ApiOptions): Promise<T>;
|
package/dist/src/lib/api.js
CHANGED
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import { getConfig } from "./config.js";
|
|
3
|
-
const API_URL = process.env.AGENTCARD_API_URL || "https://agentcard.ai";
|
|
3
|
+
export const API_URL = process.env.AGENTCARD_API_URL || "https://agentcard.ai";
|
|
4
|
+
// Thrown by `request()` when the API returns a non-OK response. Callers that
|
|
5
|
+
// care about specific HTTP statuses (e.g. 409 = wallet not provisioned) can
|
|
6
|
+
// branch on `err.status` after `instanceof ApiError`.
|
|
7
|
+
export class ApiError extends Error {
|
|
8
|
+
status;
|
|
9
|
+
body;
|
|
10
|
+
constructor(message, status, body) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.name = "ApiError";
|
|
13
|
+
this.status = status;
|
|
14
|
+
this.body = body;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
// Returns the bearer token for the current CLI session, or exits if missing.
|
|
18
|
+
// Used by callers that need to attach Authorization to non-fetch transports
|
|
19
|
+
// (viem http() / alchemy wallet transport) which sit outside `request()`.
|
|
20
|
+
export function requireAuthToken() {
|
|
21
|
+
const cfg = getConfig();
|
|
22
|
+
if (!cfg.token) {
|
|
23
|
+
console.error(chalk.red("Not logged in. Run `agentcard signup` first."));
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
return cfg.token;
|
|
27
|
+
}
|
|
4
28
|
async function request(method, path, body, options = { auth: true }) {
|
|
5
29
|
const headers = {
|
|
6
30
|
"Content-Type": "application/json",
|
|
@@ -26,14 +50,16 @@ async function request(method, path, body, options = { auth: true }) {
|
|
|
26
50
|
if (!res.ok) {
|
|
27
51
|
const text = await res.text();
|
|
28
52
|
let message;
|
|
53
|
+
let body = text;
|
|
29
54
|
try {
|
|
30
55
|
const json = JSON.parse(text);
|
|
56
|
+
body = json;
|
|
31
57
|
message = json.error || json.message || text;
|
|
32
58
|
}
|
|
33
59
|
catch {
|
|
34
60
|
message = text;
|
|
35
61
|
}
|
|
36
|
-
throw new
|
|
62
|
+
throw new ApiError(message, res.status, body);
|
|
37
63
|
}
|
|
38
64
|
return res.json();
|
|
39
65
|
}
|
package/dist/src/lib/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/lib/api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/lib/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type UserOperation } from "viem/account-abstraction";
|
|
2
|
+
export type RegisteredUserOp = Omit<UserOperation<"0.7">, "signature">;
|
|
3
|
+
export declare function lookupUserOp(wireHash: string): RegisteredUserOp | undefined;
|
|
4
|
+
export declare function withPreparedUserOps<T>(ops: RegisteredUserOp[], fn: () => Promise<T>): Promise<T>;
|
|
5
|
+
export declare function serializeUserOp(op: RegisteredUserOp): object;
|
|
6
|
+
export interface RegisteredTypedData {
|
|
7
|
+
domain: Record<string, unknown>;
|
|
8
|
+
types: Record<string, unknown>;
|
|
9
|
+
primaryType: string;
|
|
10
|
+
message: Record<string, unknown>;
|
|
11
|
+
}
|
|
12
|
+
export declare function withTypedDataIntent<T>(td: RegisteredTypedData, fn: () => Promise<T>): Promise<T>;
|
|
13
|
+
export declare function getCurrentTypedDataIntent(): RegisteredTypedData | null;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// Binds extra context to in-flight sign requests so /api/wallet/rpc's policy
|
|
2
|
+
// can decode them. Two registries live here:
|
|
3
|
+
//
|
|
4
|
+
// 1. userOp registry — when the smart-wallet client asks our LocalAccount
|
|
5
|
+
// to sign a userOp hash via secp256k1_sign, the bare hash is all the
|
|
6
|
+
// adapter sees. The backend policy needs the prepared userOp to verify
|
|
7
|
+
// the binding (`hashMessage({raw: getUserOperationHash(op)}) === hash`)
|
|
8
|
+
// and decode callData. We register expected-hash → userOp ahead of the
|
|
9
|
+
// sign so the adapter can attach it as `intent.userOp` at sign time.
|
|
10
|
+
//
|
|
11
|
+
// 2. typedData intent — MAv2's signTypedData wraps the EIP-3009 in a
|
|
12
|
+
// ReplaySafeHash envelope before signing. The /api/wallet/rpc payload
|
|
13
|
+
// carries the wrapper, not the original typed data, and the backend
|
|
14
|
+
// can't reverse `hashTypedData` back to the EIP-3009 fields. We
|
|
15
|
+
// register the original typed data here so the adapter can pass it as
|
|
16
|
+
// `intent.typedData` for the backend to bind against the wrapper.
|
|
17
|
+
import { hashMessage, } from "viem";
|
|
18
|
+
import { getUserOperationHash, } from "viem/account-abstraction";
|
|
19
|
+
import { base } from "viem/chains";
|
|
20
|
+
// Standard EntryPoint v0.7 — same address on every EVM chain.
|
|
21
|
+
const ENTRYPOINT_V07 = "0x0000000071727De22E5E9d8BAf0edAc6f37da032";
|
|
22
|
+
const userOpRegistry = new Map();
|
|
23
|
+
function registerUserOp(op) {
|
|
24
|
+
const userOpHash = getUserOperationHash({
|
|
25
|
+
chainId: base.id,
|
|
26
|
+
entryPointAddress: ENTRYPOINT_V07,
|
|
27
|
+
entryPointVersion: "0.7",
|
|
28
|
+
userOperation: { ...op, signature: "0x" },
|
|
29
|
+
});
|
|
30
|
+
// signMessage's raw branch hashes via hashMessage({ raw: userOpHash }) before
|
|
31
|
+
// sending to /api/wallet/rpc, so key by the resulting wire hash.
|
|
32
|
+
const wireHash = hashMessage({ raw: userOpHash }).toLowerCase();
|
|
33
|
+
userOpRegistry.set(wireHash, op);
|
|
34
|
+
}
|
|
35
|
+
function clearUserOpRegistry() {
|
|
36
|
+
userOpRegistry.clear();
|
|
37
|
+
}
|
|
38
|
+
export function lookupUserOp(wireHash) {
|
|
39
|
+
return userOpRegistry.get(wireHash.toLowerCase());
|
|
40
|
+
}
|
|
41
|
+
// Run an Alchemy sign flow with the prepared userOp(s) registered. Within
|
|
42
|
+
// `fn`, any secp256k1_sign whose hash matches a registered userOp gets sent
|
|
43
|
+
// to /api/wallet/rpc with the userOp attached as intent — so the backend
|
|
44
|
+
// can verify the binding + decode callData for the spend check.
|
|
45
|
+
export async function withPreparedUserOps(ops, fn) {
|
|
46
|
+
for (const op of ops)
|
|
47
|
+
registerUserOp(op);
|
|
48
|
+
try {
|
|
49
|
+
return await fn();
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
clearUserOpRegistry();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Serialize a registered userOp for the /api/wallet/rpc `intent` field.
|
|
56
|
+
// Backend's Zod schema expects every numeric field as a string.
|
|
57
|
+
export function serializeUserOp(op) {
|
|
58
|
+
const out = {
|
|
59
|
+
sender: op.sender,
|
|
60
|
+
nonce: op.nonce.toString(),
|
|
61
|
+
callData: op.callData,
|
|
62
|
+
callGasLimit: op.callGasLimit.toString(),
|
|
63
|
+
verificationGasLimit: op.verificationGasLimit.toString(),
|
|
64
|
+
preVerificationGas: op.preVerificationGas.toString(),
|
|
65
|
+
maxFeePerGas: op.maxFeePerGas.toString(),
|
|
66
|
+
maxPriorityFeePerGas: op.maxPriorityFeePerGas.toString(),
|
|
67
|
+
};
|
|
68
|
+
if (op.factory)
|
|
69
|
+
out.factory = op.factory;
|
|
70
|
+
if (op.factoryData)
|
|
71
|
+
out.factoryData = op.factoryData;
|
|
72
|
+
if (op.paymaster)
|
|
73
|
+
out.paymaster = op.paymaster;
|
|
74
|
+
if (op.paymasterData)
|
|
75
|
+
out.paymasterData = op.paymasterData;
|
|
76
|
+
if (op.paymasterVerificationGasLimit !== undefined)
|
|
77
|
+
out.paymasterVerificationGasLimit = op.paymasterVerificationGasLimit.toString();
|
|
78
|
+
if (op.paymasterPostOpGasLimit !== undefined)
|
|
79
|
+
out.paymasterPostOpGasLimit = op.paymasterPostOpGasLimit.toString();
|
|
80
|
+
return out;
|
|
81
|
+
}
|
|
82
|
+
let currentTypedDataIntent = null;
|
|
83
|
+
export async function withTypedDataIntent(td, fn) {
|
|
84
|
+
currentTypedDataIntent = td;
|
|
85
|
+
try {
|
|
86
|
+
return await fn();
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
currentTypedDataIntent = null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
export function getCurrentTypedDataIntent() {
|
|
93
|
+
return currentTypedDataIntent;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=policy-intent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-intent.js","sourceRoot":"","sources":["../../../src/lib/policy-intent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type Address, type LocalAccount } from "viem";
|
|
2
|
+
export declare function ensureWalletReady(): Promise<void>;
|
|
3
|
+
export interface WalletConfig {
|
|
4
|
+
privyAppId: string;
|
|
5
|
+
chainId: number;
|
|
6
|
+
network: string;
|
|
7
|
+
rpcUrl: string;
|
|
8
|
+
walletApiUrl: string;
|
|
9
|
+
gasPolicyId: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function getWalletConfig(): Promise<WalletConfig>;
|
|
12
|
+
interface SessionState {
|
|
13
|
+
walletId: string;
|
|
14
|
+
address: Address;
|
|
15
|
+
authorizationKey: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function getWalletSession(): Promise<SessionState>;
|
|
18
|
+
export declare function getPrivyLocalAccount(): Promise<LocalAccount>;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
// Privy bridge: HPKE handshake to fetch the user's authorization_key, plus a
|
|
2
|
+
// viem LocalAccount that signs every request through /api/wallet/rpc (the
|
|
3
|
+
// backend cosigns + forwards to Privy with App auth). No Alchemy or x402
|
|
4
|
+
// concerns here — those live in smart-wallet.ts.
|
|
5
|
+
import canonicalize from "canonicalize";
|
|
6
|
+
import { CipherSuite, DhkemP256HkdfSha256, HkdfSha256, } from "@hpke/core";
|
|
7
|
+
import { Chacha20Poly1305 } from "@hpke/chacha20poly1305";
|
|
8
|
+
import { createSign } from "node:crypto";
|
|
9
|
+
import { toAccount } from "viem/accounts";
|
|
10
|
+
import { hashMessage, } from "viem";
|
|
11
|
+
import chalk from "chalk";
|
|
12
|
+
import { get, post } from "./api.js";
|
|
13
|
+
import { lookupUserOp, serializeUserOp, getCurrentTypedDataIntent, } from "./policy-intent.js";
|
|
14
|
+
// Pre-flight check for wallet-bound CLI commands. Existing users from before
|
|
15
|
+
// the wallets PR shipped won't have a Wallet row yet; rather than letting
|
|
16
|
+
// them fall into the cryptic 409 from /api/wallet/session-key, fail fast
|
|
17
|
+
// with a clear self-heal hint. `agentcard setup` is idempotent — it skips
|
|
18
|
+
// payment method, profile, and agent email if those are already set, and
|
|
19
|
+
// just provisions + 7702-delegates the wallet.
|
|
20
|
+
export async function ensureWalletReady() {
|
|
21
|
+
const me = await get("/api/me");
|
|
22
|
+
if (!me.walletAddress) {
|
|
23
|
+
console.error(chalk.red("Wallet isn't set up yet. Run `agentcard setup` to provision it — your payment method and profile will be preserved."));
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
let walletConfig = null;
|
|
28
|
+
export async function getWalletConfig() {
|
|
29
|
+
if (walletConfig)
|
|
30
|
+
return walletConfig;
|
|
31
|
+
walletConfig = await get("/api/wallet/config");
|
|
32
|
+
return walletConfig;
|
|
33
|
+
}
|
|
34
|
+
async function setupHpkeRecipient() {
|
|
35
|
+
const suite = new CipherSuite({
|
|
36
|
+
kem: new DhkemP256HkdfSha256(),
|
|
37
|
+
kdf: new HkdfSha256(),
|
|
38
|
+
aead: new Chacha20Poly1305(),
|
|
39
|
+
});
|
|
40
|
+
const kp = await suite.kem.generateKeyPair();
|
|
41
|
+
const pub = await globalThis.crypto.subtle.exportKey("spki", kp.publicKey);
|
|
42
|
+
return {
|
|
43
|
+
publicKeySpki: new Uint8Array(pub),
|
|
44
|
+
decrypt: async (enc, ct) => {
|
|
45
|
+
const r = await suite.createRecipientContext({
|
|
46
|
+
recipientKey: kp.privateKey,
|
|
47
|
+
enc,
|
|
48
|
+
});
|
|
49
|
+
return new Uint8Array(await r.open(ct));
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export async function getWalletSession() {
|
|
54
|
+
const recipient = await setupHpkeRecipient();
|
|
55
|
+
const recipientPubB64 = Buffer.from(recipient.publicKeySpki).toString("base64");
|
|
56
|
+
const { token: userJwt } = await post("/api/auth/jwt", {});
|
|
57
|
+
const res = await post("/api/wallet/session-key", {
|
|
58
|
+
recipient_public_key: recipientPubB64,
|
|
59
|
+
userJwt,
|
|
60
|
+
});
|
|
61
|
+
const decrypted = await recipient.decrypt(Buffer.from(res.encrypted_authorization_key.encapsulated_key, "base64"), Buffer.from(res.encrypted_authorization_key.ciphertext, "base64"));
|
|
62
|
+
return {
|
|
63
|
+
walletId: res.walletId,
|
|
64
|
+
address: res.address,
|
|
65
|
+
authorizationKey: new TextDecoder().decode(decrypted),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
// ---- Privy 2-of-2 cosigning bridge ----------------------------------------
|
|
69
|
+
function pemFromPkcs8B64(b64) {
|
|
70
|
+
return `-----BEGIN PRIVATE KEY-----\n${b64.replace(/^wallet-auth:/, "").replace(/^wallet-api:/, "")}\n-----END PRIVATE KEY-----`;
|
|
71
|
+
}
|
|
72
|
+
function ecdsaSign(privPem, payloadJson) {
|
|
73
|
+
return createSign("sha256")
|
|
74
|
+
.update(Buffer.from(payloadJson, "utf8"))
|
|
75
|
+
.sign({ key: privPem, dsaEncoding: "der" })
|
|
76
|
+
.toString("base64");
|
|
77
|
+
}
|
|
78
|
+
// Recursively convert BigInts to strings for JSON serialization. EIP-3009
|
|
79
|
+
// typed-data messages carry uint256 values as BigInts; the /api/wallet/rpc
|
|
80
|
+
// body has to JSON.stringify cleanly.
|
|
81
|
+
function jsonSafe(value) {
|
|
82
|
+
if (typeof value === "bigint")
|
|
83
|
+
return value.toString();
|
|
84
|
+
if (Array.isArray(value))
|
|
85
|
+
return value.map(jsonSafe);
|
|
86
|
+
if (value !== null && typeof value === "object") {
|
|
87
|
+
const out = {};
|
|
88
|
+
for (const [k, v] of Object.entries(value))
|
|
89
|
+
out[k] = jsonSafe(v);
|
|
90
|
+
return out;
|
|
91
|
+
}
|
|
92
|
+
return value;
|
|
93
|
+
}
|
|
94
|
+
// We sign the canonicalized payload with the user's HPKE-decrypted
|
|
95
|
+
// authorization_key (the user half of the 2-of-2), then POST to
|
|
96
|
+
// /api/wallet/rpc which:
|
|
97
|
+
// 1. re-canonicalizes the payload server-side
|
|
98
|
+
// 2. enforces spend rules (using `intent` for userOp / typedData branches)
|
|
99
|
+
// 3. computes the backend half of the 2-of-2
|
|
100
|
+
// 4. calls Privy with app auth (Basic) + combined signature
|
|
101
|
+
// 5. returns Privy's response verbatim
|
|
102
|
+
//
|
|
103
|
+
// Going through our backend means the Privy app secret never ships in the
|
|
104
|
+
// CLI — same architectural reason we proxy Alchemy.
|
|
105
|
+
async function signRpc(rpcBody, intent) {
|
|
106
|
+
const [session, cfg] = await Promise.all([
|
|
107
|
+
getWalletSession(),
|
|
108
|
+
getWalletConfig(),
|
|
109
|
+
]);
|
|
110
|
+
const payloadToSign = {
|
|
111
|
+
version: 1,
|
|
112
|
+
method: "POST",
|
|
113
|
+
url: `https://api.privy.io/v1/wallets/${session.walletId}/rpc`,
|
|
114
|
+
body: rpcBody,
|
|
115
|
+
headers: { "privy-app-id": cfg.privyAppId },
|
|
116
|
+
};
|
|
117
|
+
const serialized = canonicalize(payloadToSign);
|
|
118
|
+
const userSig = ecdsaSign(pemFromPkcs8B64(session.authorizationKey), serialized);
|
|
119
|
+
// /api/wallet/rpc is always-array. Single sig is just a 1-element batch.
|
|
120
|
+
const item = {
|
|
121
|
+
payload: payloadToSign,
|
|
122
|
+
userSig,
|
|
123
|
+
};
|
|
124
|
+
if (intent)
|
|
125
|
+
item.intent = intent;
|
|
126
|
+
const { results } = await post("/api/wallet/rpc", { signatures: [item] });
|
|
127
|
+
const r = results[0];
|
|
128
|
+
if (!r)
|
|
129
|
+
throw new Error("/api/wallet/rpc returned empty results");
|
|
130
|
+
if (!r.ok) {
|
|
131
|
+
throw new Error(`privy /rpc ${r.status}: ${r.error ?? "<unknown error>"}`);
|
|
132
|
+
}
|
|
133
|
+
return r.data;
|
|
134
|
+
}
|
|
135
|
+
// ---- viem LocalAccount that routes through Privy 2-of-2 -------------------
|
|
136
|
+
export async function getPrivyLocalAccount() {
|
|
137
|
+
const session = await getWalletSession();
|
|
138
|
+
return toAccount({
|
|
139
|
+
address: session.address,
|
|
140
|
+
async signMessage({ message }) {
|
|
141
|
+
// Smart-wallet UserOp hashes arrive as { raw: 32-byte hex }.
|
|
142
|
+
// Sign with raw ECDSA after applying EIP-191 prefixing client-side
|
|
143
|
+
// so MAv2 can recover via 1271.
|
|
144
|
+
const isHexString = typeof message === "string" && /^0x[0-9a-fA-F]+$/.test(message);
|
|
145
|
+
const isRaw = typeof message === "object" && "raw" in message;
|
|
146
|
+
if (isHexString || isRaw) {
|
|
147
|
+
const raw = (isHexString ? message : message.raw);
|
|
148
|
+
const wireHash = hashMessage({ raw });
|
|
149
|
+
// If this hash corresponds to a userOp we registered before kicking
|
|
150
|
+
// off the smart-wallet flow, attach it so the backend can policy-
|
|
151
|
+
// check the underlying call. Without it, /api/wallet/rpc rejects.
|
|
152
|
+
const op = lookupUserOp(wireHash);
|
|
153
|
+
const intent = op ? { userOp: serializeUserOp(op) } : undefined;
|
|
154
|
+
const r = await signRpc({
|
|
155
|
+
chain_type: "ethereum",
|
|
156
|
+
method: "secp256k1_sign",
|
|
157
|
+
params: { hash: wireHash },
|
|
158
|
+
}, intent);
|
|
159
|
+
return r.data.signature;
|
|
160
|
+
}
|
|
161
|
+
const r = await signRpc({
|
|
162
|
+
chain_type: "ethereum",
|
|
163
|
+
method: "personal_sign",
|
|
164
|
+
params: { message: message, encoding: "utf-8" },
|
|
165
|
+
});
|
|
166
|
+
return r.data.signature;
|
|
167
|
+
},
|
|
168
|
+
async signTypedData(parameters) {
|
|
169
|
+
const p = parameters;
|
|
170
|
+
// If a typed-data intent was registered before this signing round (x402
|
|
171
|
+
// path: getX402Signer wraps the call in withTypedDataIntent), attach it
|
|
172
|
+
// so the backend can recover the inner EIP-3009 from the ReplaySafeHash
|
|
173
|
+
// wrapper Alchemy hands us. JSON-safe-ify since EIP-3009 messages carry
|
|
174
|
+
// BigInts for uint256 fields and JSON.stringify chokes on those.
|
|
175
|
+
const td = getCurrentTypedDataIntent();
|
|
176
|
+
const intent = td
|
|
177
|
+
? { typedData: jsonSafe(td) }
|
|
178
|
+
: undefined;
|
|
179
|
+
const r = await signRpc({
|
|
180
|
+
chain_type: "ethereum",
|
|
181
|
+
method: "eth_signTypedData_v4",
|
|
182
|
+
params: {
|
|
183
|
+
typed_data: {
|
|
184
|
+
domain: p.domain,
|
|
185
|
+
types: p.types,
|
|
186
|
+
primary_type: p.primaryType,
|
|
187
|
+
message: p.message,
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
}, intent);
|
|
191
|
+
return r.data.signature;
|
|
192
|
+
},
|
|
193
|
+
async signTransaction() {
|
|
194
|
+
throw new Error("signTransaction is not used; smart wallet flow signs userOps via signMessage");
|
|
195
|
+
},
|
|
196
|
+
async signAuthorization({ chainId, address: contractAddress, nonce }) {
|
|
197
|
+
const r = await signRpc({
|
|
198
|
+
chain_type: "ethereum",
|
|
199
|
+
method: "eth_sign7702Authorization",
|
|
200
|
+
params: { chain_id: chainId, contract: contractAddress, nonce },
|
|
201
|
+
});
|
|
202
|
+
const a = r.data.authorization;
|
|
203
|
+
return {
|
|
204
|
+
address: contractAddress,
|
|
205
|
+
chainId,
|
|
206
|
+
nonce,
|
|
207
|
+
r: a.r,
|
|
208
|
+
s: a.s,
|
|
209
|
+
yParity: a.y_parity,
|
|
210
|
+
};
|
|
211
|
+
},
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=privy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"privy.js","sourceRoot":"","sources":["../../../src/lib/privy.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,0EAA0E;AAC1E,yEAAyE;AACzE,iDAAiD;AAEjD,OAAO,YAAY,MAAM,cAAc,CAAC;AACxC,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,UAAU,GACX,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EACL,WAAW,GAIZ,MAAM,MAAM,CAAC;AACd,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EACL,YAAY,EACZ,eAAe,EACf,yBAAyB,GAE1B,MAAM,oBAAoB,CAAC;AAE5B,6EAA6E;AAC7E,0EAA0E;AAC1E,yEAAyE;AACzE,0EAA0E;AAC1E,yEAAyE;AACzE,+CAA+C;AAC/C,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,MAAM,EAAE,GAAG,MAAM,GAAG,CAAmC,SAAS,CAAC,CAAC;IAClE,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC;QACtB,OAAO,CAAC,KAAK,CACX,KAAK,CAAC,GAAG,CACP,qHAAqH,CACtH,CACF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAcD,IAAI,YAAY,GAAwB,IAAI,CAAC;AAE7C,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,YAAY;QAAE,OAAO,YAAY,CAAC;IACtC,YAAY,GAAG,MAAM,GAAG,CAAe,oBAAoB,CAAC,CAAC;IAC7D,OAAO,YAAY,CAAC;AACtB,CAAC;AASD,KAAK,UAAU,kBAAkB;IAC/B,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC;QAC5B,GAAG,EAAE,IAAI,mBAAmB,EAAE;QAC9B,GAAG,EAAE,IAAI,UAAU,EAAE;QACrB,IAAI,EAAE,IAAI,gBAAgB,EAAE;KAC7B,CAAC,CAAC;IACH,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;IAC7C,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC;IAC3E,OAAO;QACL,aAAa,EAAE,IAAI,UAAU,CAAC,GAAG,CAAC;QAClC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE;YACzB,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC,sBAAsB,CAAC;gBAC3C,YAAY,EAAE,EAAE,CAAC,UAAU;gBAC3B,GAAG;aACJ,CAAC,CAAC;YACH,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1C,CAAC;KACF,CAAC;AACJ,CAAC;AAeD,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,MAAM,SAAS,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAC7C,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAChF,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAAoB,eAAe,EAAE,EAAE,CAAC,CAAC;IAC9E,MAAM,GAAG,GAAG,MAAM,IAAI,CAInB,yBAAyB,EAAE;QAC5B,oBAAoB,EAAE,eAAe;QACrC,OAAO;KACR,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,OAAO,CACvC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,2BAA2B,CAAC,gBAAgB,EAAE,QAAQ,CAAC,EACvE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,2BAA2B,CAAC,UAAU,EAAE,QAAQ,CAAC,CAClE,CAAC;IACF,OAAO;QACL,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,gBAAgB,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC;KACtD,CAAC;AACJ,CAAC;AAED,8EAA8E;AAE9E,SAAS,eAAe,CAAC,GAAW;IAClC,OAAO,gCAAgC,GAAG,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,6BAA6B,CAAC;AACnI,CAAC;AAED,SAAS,SAAS,CAAC,OAAe,EAAE,WAAmB;IACrD,OAAO,UAAU,CAAC,QAAQ,CAAC;SACxB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;SACxC,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;SAC1C,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACxB,CAAC;AAED,0EAA0E;AAC1E,2EAA2E;AAC3E,sCAAsC;AACtC,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;IACvD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACrD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,GAAG,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QACjE,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AASD,mEAAmE;AACnE,gEAAgE;AAChE,yBAAyB;AACzB,gDAAgD;AAChD,6EAA6E;AAC7E,+CAA+C;AAC/C,8DAA8D;AAC9D,yCAAyC;AACzC,EAAE;AACF,0EAA0E;AAC1E,oDAAoD;AACpD,KAAK,UAAU,OAAO,CAAI,OAAe,EAAE,MAAe;IACxD,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACvC,gBAAgB,EAAE;QAClB,eAAe,EAAE;KAClB,CAAC,CAAC;IACH,MAAM,aAAa,GAAG;QACpB,OAAO,EAAE,CAAC;QACV,MAAM,EAAE,MAAe;QACvB,GAAG,EAAE,mCAAmC,OAAO,CAAC,QAAQ,MAAM;QAC9D,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,EAAE,cAAc,EAAE,GAAG,CAAC,UAAU,EAAE;KAC5C,CAAC;IACF,MAAM,UAAU,GAAG,YAAY,CAAC,aAAa,CAAW,CAAC;IACzD,MAAM,OAAO,GAAG,SAAS,CAAC,eAAe,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,UAAU,CAAC,CAAC;IAEjF,yEAAyE;IACzE,MAAM,IAAI,GAAwE;QAChF,OAAO,EAAE,aAAa;QACtB,OAAO;KACR,CAAC;IACF,IAAI,MAAM;QAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACjC,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAC5B,iBAAiB,EACjB,EAAE,UAAU,EAAE,CAAC,IAAI,CAAC,EAAE,CACvB,CAAC;IACF,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACrB,IAAI,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAClE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CACb,cAAc,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,KAAK,IAAI,iBAAiB,EAAE,CAC1D,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,CAAC,IAAS,CAAC;AACrB,CAAC;AAED,8EAA8E;AAE9E,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,MAAM,OAAO,GAAG,MAAM,gBAAgB,EAAE,CAAC;IACzC,OAAO,SAAS,CAAC;QACf,OAAO,EAAE,OAAO,CAAC,OAAO;QAExB,KAAK,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE;YAC3B,6DAA6D;YAC7D,mEAAmE;YACnE,gCAAgC;YAChC,MAAM,WAAW,GACf,OAAO,OAAO,KAAK,QAAQ,IAAI,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAClE,MAAM,KAAK,GAAG,OAAO,OAAO,KAAK,QAAQ,IAAI,KAAK,IAAI,OAAO,CAAC;YAC9D,IAAI,WAAW,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,GAAG,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAE,OAAwB,CAAC,GAAG,CAAQ,CAAC;gBAC3E,MAAM,QAAQ,GAAG,WAAW,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;gBACtC,oEAAoE;gBACpE,kEAAkE;gBAClE,kEAAkE;gBAClE,MAAM,EAAE,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;gBAClC,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;gBAChE,MAAM,CAAC,GAAG,MAAM,OAAO,CACrB;oBACE,UAAU,EAAE,UAAU;oBACtB,MAAM,EAAE,gBAAgB;oBACxB,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;iBAC3B,EACD,MAAM,CACP,CAAC;gBACF,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;YAC1B,CAAC;YACD,MAAM,CAAC,GAAG,MAAM,OAAO,CAA+B;gBACpD,UAAU,EAAE,UAAU;gBACtB,MAAM,EAAE,eAAe;gBACvB,MAAM,EAAE,EAAE,OAAO,EAAE,OAAiB,EAAE,QAAQ,EAAE,OAAO,EAAE;aAC1D,CAAC,CAAC;YACH,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;QAC1B,CAAC;QAED,KAAK,CAAC,aAAa,CAAC,UAAU;YAC5B,MAAM,CAAC,GAAG,UAKT,CAAC;YACF,wEAAwE;YACxE,wEAAwE;YACxE,wEAAwE;YACxE,wEAAwE;YACxE,iEAAiE;YACjE,MAAM,EAAE,GAAG,yBAAyB,EAAE,CAAC;YACvC,MAAM,MAAM,GAAG,EAAE;gBACf,CAAC,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,CAAwB,EAAE;gBACpD,CAAC,CAAC,SAAS,CAAC;YACd,MAAM,CAAC,GAAG,MAAM,OAAO,CACrB;gBACE,UAAU,EAAE,UAAU;gBACtB,MAAM,EAAE,sBAAsB;gBAC9B,MAAM,EAAE;oBACN,UAAU,EAAE;wBACV,MAAM,EAAE,CAAC,CAAC,MAAM;wBAChB,KAAK,EAAE,CAAC,CAAC,KAAK;wBACd,YAAY,EAAE,CAAC,CAAC,WAAW;wBAC3B,OAAO,EAAE,CAAC,CAAC,OAAO;qBACnB;iBACF;aACF,EACD,MAAM,CACP,CAAC;YACF,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;QAC1B,CAAC;QAED,KAAK,CAAC,eAAe;YACnB,MAAM,IAAI,KAAK,CACb,8EAA8E,CAC/E,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,iBAAiB,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE;YAClE,MAAM,CAAC,GAAG,MAAM,OAAO,CAIpB;gBACD,UAAU,EAAE,UAAU;gBACtB,MAAM,EAAE,2BAA2B;gBACnC,MAAM,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,KAAK,EAAE;aAChE,CAAC,CAAC;YACH,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC;YAC/B,OAAO;gBACL,OAAO,EAAE,eAAe;gBACxB,OAAO;gBACP,KAAK;gBACL,CAAC,EAAE,CAAC,CAAC,CAAC;gBACN,CAAC,EAAE,CAAC,CAAC,CAAC;gBACN,OAAO,EAAE,CAAC,CAAC,QAAQ;aACX,CAAC;QACb,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Address, type Hex } from "viem";
|
|
2
|
+
export declare function getSmartWalletClient(): Promise<any>;
|
|
3
|
+
export declare function ensureDelegated(): Promise<void>;
|
|
4
|
+
export interface ClientEvmSigner {
|
|
5
|
+
readonly address: Address;
|
|
6
|
+
signTypedData(message: {
|
|
7
|
+
domain: Record<string, unknown>;
|
|
8
|
+
types: Record<string, unknown>;
|
|
9
|
+
primaryType: string;
|
|
10
|
+
message: Record<string, unknown>;
|
|
11
|
+
}): Promise<Hex>;
|
|
12
|
+
}
|
|
13
|
+
export declare function getX402Signer(): Promise<ClientEvmSigner>;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// Alchemy MAv2 smart wallet bridge: builds the @alchemy/wallet-apis client
|
|
2
|
+
// using our Privy-backed signer, and exposes the helpers built on top of it
|
|
3
|
+
// (7702 setup-time delegation, x402 signer adapter).
|
|
4
|
+
import { base } from "viem/chains";
|
|
5
|
+
import { createSmartWalletClient, alchemyWalletTransport, } from "@alchemy/wallet-apis";
|
|
6
|
+
import { requireAuthToken } from "./api.js";
|
|
7
|
+
import { getPrivyLocalAccount, getWalletConfig } from "./privy.js";
|
|
8
|
+
import { withPreparedUserOps, withTypedDataIntent, } from "./policy-intent.js";
|
|
9
|
+
import { publicClient } from "./usdc.js";
|
|
10
|
+
// Talks to Alchemy via our backend proxy so the API key stays server-side.
|
|
11
|
+
// We pass `url` to override the default (api.g.alchemy.com/v2) and inject
|
|
12
|
+
// the CLI's session token via fetchOptions. We deliberately omit
|
|
13
|
+
// `apiKey`/`jwt` because withAlchemyHeaders would otherwise overwrite our
|
|
14
|
+
// Authorization header.
|
|
15
|
+
export async function getSmartWalletClient() {
|
|
16
|
+
const cfg = await getWalletConfig();
|
|
17
|
+
const account = await getPrivyLocalAccount();
|
|
18
|
+
return createSmartWalletClient({
|
|
19
|
+
signer: account,
|
|
20
|
+
transport: alchemyWalletTransport({
|
|
21
|
+
url: cfg.walletApiUrl,
|
|
22
|
+
fetchOptions: {
|
|
23
|
+
headers: { Authorization: `Bearer ${requireAuthToken()}` },
|
|
24
|
+
},
|
|
25
|
+
}),
|
|
26
|
+
chain: base,
|
|
27
|
+
paymaster: cfg.gasPolicyId ? { policyId: cfg.gasPolicyId } : undefined,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
// 7702-delegate the wallet if it has no code yet. Drives an empty userOp
|
|
31
|
+
// (`execute(0x0, 0, 0x)`) through Alchemy's bundler so the 7702 authorization
|
|
32
|
+
// is included in the bundle. The backend policy classifies this as no-spend.
|
|
33
|
+
//
|
|
34
|
+
// Idempotent — short-circuits via `eth_getCode` if the wallet is already
|
|
35
|
+
// delegated. Safe to call before any signing-only flow (x402, ReplaySafeHash
|
|
36
|
+
// typed-data signing) that won't otherwise originate a userOp.
|
|
37
|
+
export async function ensureDelegated() {
|
|
38
|
+
const client = await getSmartWalletClient();
|
|
39
|
+
const address = client.account.address;
|
|
40
|
+
const code = await publicClient().getCode({ address });
|
|
41
|
+
if (code && code !== "0x")
|
|
42
|
+
return;
|
|
43
|
+
const prepared = await client.prepareCalls({
|
|
44
|
+
calls: [
|
|
45
|
+
{
|
|
46
|
+
to: "0x0000000000000000000000000000000000000000",
|
|
47
|
+
value: 0n,
|
|
48
|
+
data: "0x",
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
});
|
|
52
|
+
// Bootstrap returns an array of [authorization, userOp]. Subsequent prepares
|
|
53
|
+
// would return a plain user-operation-v070 — we accept either.
|
|
54
|
+
const userOps = prepared.type === "user-operation-v070"
|
|
55
|
+
? [prepared.data]
|
|
56
|
+
: prepared.type === "array"
|
|
57
|
+
? prepared.data
|
|
58
|
+
.filter((item) => item.type === "user-operation-v070")
|
|
59
|
+
.map((item) => item.data)
|
|
60
|
+
: (() => {
|
|
61
|
+
throw new Error(`unexpected prepared.type: ${prepared.type}`);
|
|
62
|
+
})();
|
|
63
|
+
const sent = await withPreparedUserOps(userOps, async () => {
|
|
64
|
+
const signed = await client.signPreparedCalls(prepared);
|
|
65
|
+
return client.sendPreparedCalls(signed);
|
|
66
|
+
});
|
|
67
|
+
await client.waitForCallsStatus({ id: sent.id });
|
|
68
|
+
}
|
|
69
|
+
export async function getX402Signer() {
|
|
70
|
+
const client = await getSmartWalletClient();
|
|
71
|
+
return {
|
|
72
|
+
address: client.account.address,
|
|
73
|
+
signTypedData: async (params) => {
|
|
74
|
+
// Register the EIP-3009 we're about to sign so the privy LocalAccount
|
|
75
|
+
// can attach it as `intent.typedData` when Alchemy hands back a
|
|
76
|
+
// ReplaySafeHash wrapper. The backend uses it to bind the wrapper to
|
|
77
|
+
// the inner authorization and run TransferWithAuthorization policy.
|
|
78
|
+
return (await withTypedDataIntent({
|
|
79
|
+
domain: params.domain,
|
|
80
|
+
types: params.types,
|
|
81
|
+
primaryType: params.primaryType,
|
|
82
|
+
message: params.message,
|
|
83
|
+
},
|
|
84
|
+
// Smart wallet method — produces the SemiModular-format 72-byte sig
|
|
85
|
+
// that USDC's bytes overload + 1271 verification accepts.
|
|
86
|
+
async () => (await client.signTypedData(params))));
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=smart-wallet.js.map
|