agentcard 0.0.21 → 0.0.23

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.
Files changed (36) hide show
  1. package/dist/src/commands/setup.js +35 -3
  2. package/dist/src/commands/setup.js.map +1 -1
  3. package/dist/src/commands/signup.js +1 -1
  4. package/dist/src/commands/signup.js.map +1 -1
  5. package/dist/src/commands/wallet/balance.d.ts +1 -0
  6. package/dist/src/commands/wallet/balance.js +19 -0
  7. package/dist/src/commands/wallet/balance.js.map +1 -0
  8. package/dist/src/commands/wallet/fetch.d.ts +8 -0
  9. package/dist/src/commands/wallet/fetch.js +147 -0
  10. package/dist/src/commands/wallet/fetch.js.map +1 -0
  11. package/dist/src/commands/wallet/info.d.ts +1 -0
  12. package/dist/src/commands/wallet/info.js +29 -0
  13. package/dist/src/commands/wallet/info.js.map +1 -0
  14. package/dist/src/commands/wallet/send.d.ts +6 -0
  15. package/dist/src/commands/wallet/send.js +80 -0
  16. package/dist/src/commands/wallet/send.js.map +1 -0
  17. package/dist/src/commands/whoami.js +12 -0
  18. package/dist/src/commands/whoami.js.map +1 -1
  19. package/dist/src/index.js +32 -1
  20. package/dist/src/index.js.map +1 -1
  21. package/dist/src/lib/api.d.ts +7 -0
  22. package/dist/src/lib/api.js +28 -2
  23. package/dist/src/lib/api.js.map +1 -1
  24. package/dist/src/lib/policy-intent.d.ts +13 -0
  25. package/dist/src/lib/policy-intent.js +95 -0
  26. package/dist/src/lib/policy-intent.js.map +1 -0
  27. package/dist/src/lib/privy.d.ts +19 -0
  28. package/dist/src/lib/privy.js +214 -0
  29. package/dist/src/lib/privy.js.map +1 -0
  30. package/dist/src/lib/smart-wallet.d.ts +13 -0
  31. package/dist/src/lib/smart-wallet.js +90 -0
  32. package/dist/src/lib/smart-wallet.js.map +1 -0
  33. package/dist/src/lib/usdc.d.ts +11088 -0
  34. package/dist/src/lib/usdc.js +42 -0
  35. package/dist/src/lib/usdc.js.map +1 -0
  36. package/package.json +7 -2
@@ -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 Error(message);
62
+ throw new ApiError(message, res.status, body);
37
63
  }
38
64
  return res.json();
39
65
  }
@@ -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;AAMxE,KAAK,UAAU,OAAO,CACpB,MAAc,EACd,IAAY,EACZ,IAAc,EACd,UAAsB,EAAE,IAAI,EAAE,IAAI,EAAE;IAEpC,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;KACnC,CAAC;IAEF,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAC3B,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC,CAAC;YACzE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,MAAM,CAAC,KAAK,EAAE,CAAC;IACtD,CAAC;IAED,MAAM,GAAG,GAAG,GAAG,OAAO,GAAG,IAAI,EAAE,CAAC;IAChC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,MAAM;QACN,OAAO;QACP,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;KAC9C,CAAC,CAAC;IAEH,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CACX,KAAK,CAAC,GAAG,CAAC,0DAA0D,CAAC,CACtE,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC9B,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC;QAC/C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO,GAAG,CAAC,IAAI,EAAgB,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,GAAG,CAAI,IAAY,EAAE,OAAoB;IACvD,OAAO,OAAO,CAAI,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,IAAI,CAClB,IAAY,EACZ,IAAc,EACd,OAAoB;IAEpB,OAAO,OAAO,CAAI,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,KAAK,CACnB,IAAY,EACZ,IAAc,EACd,OAAoB;IAEpB,OAAO,OAAO,CAAI,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,GAAG,CACjB,IAAY,EACZ,OAAoB;IAEpB,OAAO,OAAO,CAAI,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AACxD,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":"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"}
@@ -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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smart-wallet.js","sourceRoot":"","sources":["../../../src/lib/smart-wallet.ts"],"names":[],"mappings":"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"}