@a3stack/accounts 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants.d.ts +64 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +46 -0
- package/dist/constants.js.map +1 -0
- package/dist/gasless-register.d.ts +38 -0
- package/dist/gasless-register.d.ts.map +1 -0
- package/dist/gasless-register.js +41 -0
- package/dist/gasless-register.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/smart-account.d.ts +35 -0
- package/dist/smart-account.d.ts.map +1 -0
- package/dist/smart-account.js +115 -0
- package/dist/smart-account.js.map +1 -0
- package/dist/types.d.ts +73 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +42 -0
- package/src/constants.ts +49 -0
- package/src/gasless-register.ts +47 -0
- package/src/index.ts +36 -0
- package/src/smart-account.ts +143 -0
- package/src/types.ts +76 -0
- package/test/integration.mjs +121 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constants for @a3stack/accounts
|
|
3
|
+
*/
|
|
4
|
+
/** ERC-8004 Identity Registry — same address on all chains */
|
|
5
|
+
export declare const REGISTRY_ADDRESS: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432";
|
|
6
|
+
/** ERC-8004 registration type URI */
|
|
7
|
+
export declare const REGISTRATION_TYPE = "https://eips.ethereum.org/EIPS/eip-8004#registration-v1";
|
|
8
|
+
/** Zero address */
|
|
9
|
+
export declare const ZERO_ADDRESS: "0x0000000000000000000000000000000000000000";
|
|
10
|
+
/** Minimal ABI for ERC-8004 register + Transfer event */
|
|
11
|
+
export declare const REGISTRY_ABI: readonly [{
|
|
12
|
+
readonly name: "register";
|
|
13
|
+
readonly type: "function";
|
|
14
|
+
readonly stateMutability: "nonpayable";
|
|
15
|
+
readonly inputs: readonly [{
|
|
16
|
+
readonly name: "agentURI";
|
|
17
|
+
readonly type: "string";
|
|
18
|
+
}];
|
|
19
|
+
readonly outputs: readonly [{
|
|
20
|
+
readonly name: "";
|
|
21
|
+
readonly type: "uint256";
|
|
22
|
+
}];
|
|
23
|
+
}, {
|
|
24
|
+
readonly name: "setAgentURI";
|
|
25
|
+
readonly type: "function";
|
|
26
|
+
readonly stateMutability: "nonpayable";
|
|
27
|
+
readonly inputs: readonly [{
|
|
28
|
+
readonly name: "agentId";
|
|
29
|
+
readonly type: "uint256";
|
|
30
|
+
}, {
|
|
31
|
+
readonly name: "newURI";
|
|
32
|
+
readonly type: "string";
|
|
33
|
+
}];
|
|
34
|
+
readonly outputs: readonly [];
|
|
35
|
+
}, {
|
|
36
|
+
readonly name: "balanceOf";
|
|
37
|
+
readonly type: "function";
|
|
38
|
+
readonly stateMutability: "view";
|
|
39
|
+
readonly inputs: readonly [{
|
|
40
|
+
readonly name: "owner";
|
|
41
|
+
readonly type: "address";
|
|
42
|
+
}];
|
|
43
|
+
readonly outputs: readonly [{
|
|
44
|
+
readonly name: "";
|
|
45
|
+
readonly type: "uint256";
|
|
46
|
+
}];
|
|
47
|
+
}, {
|
|
48
|
+
readonly name: "Transfer";
|
|
49
|
+
readonly type: "event";
|
|
50
|
+
readonly inputs: readonly [{
|
|
51
|
+
readonly name: "from";
|
|
52
|
+
readonly type: "address";
|
|
53
|
+
readonly indexed: true;
|
|
54
|
+
}, {
|
|
55
|
+
readonly name: "to";
|
|
56
|
+
readonly type: "address";
|
|
57
|
+
readonly indexed: true;
|
|
58
|
+
}, {
|
|
59
|
+
readonly name: "tokenId";
|
|
60
|
+
readonly type: "uint256";
|
|
61
|
+
readonly indexed: true;
|
|
62
|
+
}];
|
|
63
|
+
}];
|
|
64
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,8DAA8D;AAC9D,eAAO,MAAM,gBAAgB,EAAG,4CAAqD,CAAC;AAEtF,qCAAqC;AACrC,eAAO,MAAM,iBAAiB,4DAA4D,CAAC;AAE3F,mBAAmB;AACnB,eAAO,MAAM,YAAY,EAAG,4CAAqD,CAAC;AAElF,yDAAyD;AACzD,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkCf,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constants for @a3stack/accounts
|
|
3
|
+
*/
|
|
4
|
+
/** ERC-8004 Identity Registry — same address on all chains */
|
|
5
|
+
export const REGISTRY_ADDRESS = "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432";
|
|
6
|
+
/** ERC-8004 registration type URI */
|
|
7
|
+
export const REGISTRATION_TYPE = "https://eips.ethereum.org/EIPS/eip-8004#registration-v1";
|
|
8
|
+
/** Zero address */
|
|
9
|
+
export const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
10
|
+
/** Minimal ABI for ERC-8004 register + Transfer event */
|
|
11
|
+
export const REGISTRY_ABI = [
|
|
12
|
+
{
|
|
13
|
+
name: "register",
|
|
14
|
+
type: "function",
|
|
15
|
+
stateMutability: "nonpayable",
|
|
16
|
+
inputs: [{ name: "agentURI", type: "string" }],
|
|
17
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: "setAgentURI",
|
|
21
|
+
type: "function",
|
|
22
|
+
stateMutability: "nonpayable",
|
|
23
|
+
inputs: [
|
|
24
|
+
{ name: "agentId", type: "uint256" },
|
|
25
|
+
{ name: "newURI", type: "string" },
|
|
26
|
+
],
|
|
27
|
+
outputs: [],
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: "balanceOf",
|
|
31
|
+
type: "function",
|
|
32
|
+
stateMutability: "view",
|
|
33
|
+
inputs: [{ name: "owner", type: "address" }],
|
|
34
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: "Transfer",
|
|
38
|
+
type: "event",
|
|
39
|
+
inputs: [
|
|
40
|
+
{ name: "from", type: "address", indexed: true },
|
|
41
|
+
{ name: "to", type: "address", indexed: true },
|
|
42
|
+
{ name: "tokenId", type: "uint256", indexed: true },
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,8DAA8D;AAC9D,MAAM,CAAC,MAAM,gBAAgB,GAAG,4CAAqD,CAAC;AAEtF,qCAAqC;AACrC,MAAM,CAAC,MAAM,iBAAiB,GAAG,yDAAyD,CAAC;AAE3F,mBAAmB;AACnB,MAAM,CAAC,MAAM,YAAY,GAAG,4CAAqD,CAAC;AAElF,yDAAyD;AACzD,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B;QACE,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,UAAU;QAChB,eAAe,EAAE,YAAY;QAC7B,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QAC9C,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;KACzC;IACD;QACE,IAAI,EAAE,aAAa;QACnB,IAAI,EAAE,UAAU;QAChB,eAAe,EAAE,YAAY;QAC7B,MAAM,EAAE;YACN,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;YACpC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE;SACnC;QACD,OAAO,EAAE,EAAE;KACZ;IACD;QACE,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,UAAU;QAChB,eAAe,EAAE,MAAM;QACvB,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QAC5C,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;KACzC;IACD;QACE,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,OAAO;QACb,MAAM,EAAE;YACN,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE;YAChD,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE;YAC9C,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE;SACpD;KACF;CACO,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convenience function for one-shot gasless registration.
|
|
3
|
+
*
|
|
4
|
+
* For more control, use createAgentAccount() directly.
|
|
5
|
+
*/
|
|
6
|
+
import type { CdpCredentials, RegisterOptions, RegisterResult } from "./types.js";
|
|
7
|
+
/**
|
|
8
|
+
* Register an agent on ERC-8004 with zero gas cost (one-shot).
|
|
9
|
+
*
|
|
10
|
+
* Creates a smart account and registers in a single call.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { gaslessRegister } from "@a3stack/accounts";
|
|
15
|
+
*
|
|
16
|
+
* const result = await gaslessRegister(
|
|
17
|
+
* {
|
|
18
|
+
* apiKeyId: process.env.CDP_API_KEY_ID!,
|
|
19
|
+
* apiKeySecret: process.env.CDP_API_KEY_SECRET!,
|
|
20
|
+
* walletSecret: process.env.CDP_WALLET_SECRET!,
|
|
21
|
+
* },
|
|
22
|
+
* {
|
|
23
|
+
* name: "my-agent",
|
|
24
|
+
* description: "An AI agent that does cool things",
|
|
25
|
+
* services: [{ type: "website", url: "https://myagent.ai" }],
|
|
26
|
+
* }
|
|
27
|
+
* );
|
|
28
|
+
*
|
|
29
|
+
* console.log(`Registered at ${result.smartAccountAddress}`);
|
|
30
|
+
* console.log(`Tx: ${result.transactionHash}`);
|
|
31
|
+
* console.log(`Gas cost: $${result.gasCost}`); // $0
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function gaslessRegister(credentials: CdpCredentials, options: RegisterOptions & {
|
|
35
|
+
accountName?: string;
|
|
36
|
+
testnet?: boolean;
|
|
37
|
+
}): Promise<RegisterResult>;
|
|
38
|
+
//# sourceMappingURL=gasless-register.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gasless-register.d.ts","sourceRoot":"","sources":["../src/gasless-register.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAElF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,eAAe,CACnC,WAAW,EAAE,cAAc,EAC3B,OAAO,EAAE,eAAe,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GACrE,OAAO,CAAC,cAAc,CAAC,CAOzB"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convenience function for one-shot gasless registration.
|
|
3
|
+
*
|
|
4
|
+
* For more control, use createAgentAccount() directly.
|
|
5
|
+
*/
|
|
6
|
+
import { createAgentAccount } from "./smart-account.js";
|
|
7
|
+
/**
|
|
8
|
+
* Register an agent on ERC-8004 with zero gas cost (one-shot).
|
|
9
|
+
*
|
|
10
|
+
* Creates a smart account and registers in a single call.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { gaslessRegister } from "@a3stack/accounts";
|
|
15
|
+
*
|
|
16
|
+
* const result = await gaslessRegister(
|
|
17
|
+
* {
|
|
18
|
+
* apiKeyId: process.env.CDP_API_KEY_ID!,
|
|
19
|
+
* apiKeySecret: process.env.CDP_API_KEY_SECRET!,
|
|
20
|
+
* walletSecret: process.env.CDP_WALLET_SECRET!,
|
|
21
|
+
* },
|
|
22
|
+
* {
|
|
23
|
+
* name: "my-agent",
|
|
24
|
+
* description: "An AI agent that does cool things",
|
|
25
|
+
* services: [{ type: "website", url: "https://myagent.ai" }],
|
|
26
|
+
* }
|
|
27
|
+
* );
|
|
28
|
+
*
|
|
29
|
+
* console.log(`Registered at ${result.smartAccountAddress}`);
|
|
30
|
+
* console.log(`Tx: ${result.transactionHash}`);
|
|
31
|
+
* console.log(`Gas cost: $${result.gasCost}`); // $0
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export async function gaslessRegister(credentials, options) {
|
|
35
|
+
const agent = await createAgentAccount(credentials, {
|
|
36
|
+
name: options.accountName ?? `agent-${options.name.toLowerCase().replace(/\s+/g, "-")}`,
|
|
37
|
+
testnet: options.testnet,
|
|
38
|
+
});
|
|
39
|
+
return agent.register(options);
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=gasless-register.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gasless-register.js","sourceRoot":"","sources":["../src/gasless-register.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAGxD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,WAA2B,EAC3B,OAAsE;IAEtE,MAAM,KAAK,GAAG,MAAM,kBAAkB,CAAC,WAAW,EAAE;QAClD,IAAI,EAAE,OAAO,CAAC,WAAW,IAAI,SAAS,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE;QACvF,OAAO,EAAE,OAAO,CAAC,OAAO;KACzB,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @a3stack/accounts — Gasless smart accounts for AI agents
|
|
3
|
+
*
|
|
4
|
+
* Create ERC-4337 smart accounts with automatic gas sponsorship
|
|
5
|
+
* via CDP Paymaster. Register agents on ERC-8004 with zero gas cost.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { createAgentAccount } from "@a3stack/accounts";
|
|
10
|
+
*
|
|
11
|
+
* const agent = await createAgentAccount({
|
|
12
|
+
* apiKeyId: process.env.CDP_API_KEY_ID!,
|
|
13
|
+
* apiKeySecret: process.env.CDP_API_KEY_SECRET!,
|
|
14
|
+
* walletSecret: process.env.CDP_WALLET_SECRET!,
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* // Register on-chain with zero gas
|
|
18
|
+
* const result = await agent.register({
|
|
19
|
+
* name: "My Agent",
|
|
20
|
+
* description: "Does cool stuff",
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export { createAgentAccount } from "./smart-account.js";
|
|
25
|
+
export { gaslessRegister } from "./gasless-register.js";
|
|
26
|
+
export { REGISTRY_ADDRESS, REGISTRY_ABI, REGISTRATION_TYPE } from "./constants.js";
|
|
27
|
+
export type { CdpCredentials, CreateAgentAccountOptions, AgentAccount, RegisterOptions, RegisterResult, UserOperationCall, UserOperationResult, } from "./types.js";
|
|
28
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnF,YAAY,EACV,cAAc,EACd,yBAAyB,EACzB,YAAY,EACZ,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @a3stack/accounts — Gasless smart accounts for AI agents
|
|
3
|
+
*
|
|
4
|
+
* Create ERC-4337 smart accounts with automatic gas sponsorship
|
|
5
|
+
* via CDP Paymaster. Register agents on ERC-8004 with zero gas cost.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { createAgentAccount } from "@a3stack/accounts";
|
|
10
|
+
*
|
|
11
|
+
* const agent = await createAgentAccount({
|
|
12
|
+
* apiKeyId: process.env.CDP_API_KEY_ID!,
|
|
13
|
+
* apiKeySecret: process.env.CDP_API_KEY_SECRET!,
|
|
14
|
+
* walletSecret: process.env.CDP_WALLET_SECRET!,
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* // Register on-chain with zero gas
|
|
18
|
+
* const result = await agent.register({
|
|
19
|
+
* name: "My Agent",
|
|
20
|
+
* description: "Does cool stuff",
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export { createAgentAccount } from "./smart-account.js";
|
|
25
|
+
export { gaslessRegister } from "./gasless-register.js";
|
|
26
|
+
export { REGISTRY_ADDRESS, REGISTRY_ABI, REGISTRATION_TYPE } from "./constants.js";
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CDP Smart Account wrapper for gasless agent operations
|
|
3
|
+
*
|
|
4
|
+
* Uses Coinbase Developer Platform SDK for:
|
|
5
|
+
* - Server wallet management (EOA owner)
|
|
6
|
+
* - Smart account creation (ERC-4337)
|
|
7
|
+
* - Automatic gas sponsorship via CDP Paymaster on Base
|
|
8
|
+
*/
|
|
9
|
+
import type { CdpCredentials, CreateAgentAccountOptions, AgentAccount } from "./types.js";
|
|
10
|
+
/**
|
|
11
|
+
* Create a gasless smart account for an AI agent.
|
|
12
|
+
*
|
|
13
|
+
* The account is an ERC-4337 smart account on Base, owned by a CDP-managed
|
|
14
|
+
* EOA. All transactions are gas-sponsored by the CDP Paymaster.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { createAgentAccount } from "@a3stack/accounts";
|
|
19
|
+
*
|
|
20
|
+
* const agent = await createAgentAccount({
|
|
21
|
+
* apiKeyId: process.env.CDP_API_KEY_ID!,
|
|
22
|
+
* apiKeySecret: process.env.CDP_API_KEY_SECRET!,
|
|
23
|
+
* walletSecret: process.env.CDP_WALLET_SECRET!,
|
|
24
|
+
* }, { name: "my-agent" });
|
|
25
|
+
*
|
|
26
|
+
* // Register on ERC-8004 with zero gas
|
|
27
|
+
* const result = await agent.register({
|
|
28
|
+
* name: "My Agent",
|
|
29
|
+
* description: "An autonomous AI agent",
|
|
30
|
+
* });
|
|
31
|
+
* console.log(`Registered! Tx: ${result.transactionHash}`);
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function createAgentAccount(credentials: CdpCredentials, options?: CreateAgentAccountOptions): Promise<AgentAccount>;
|
|
35
|
+
//# sourceMappingURL=smart-account.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smart-account.d.ts","sourceRoot":"","sources":["../src/smart-account.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EACV,cAAc,EACd,yBAAyB,EACzB,YAAY,EAKb,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,cAAc,EAC3B,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,YAAY,CAAC,CA6FvB"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CDP Smart Account wrapper for gasless agent operations
|
|
3
|
+
*
|
|
4
|
+
* Uses Coinbase Developer Platform SDK for:
|
|
5
|
+
* - Server wallet management (EOA owner)
|
|
6
|
+
* - Smart account creation (ERC-4337)
|
|
7
|
+
* - Automatic gas sponsorship via CDP Paymaster on Base
|
|
8
|
+
*/
|
|
9
|
+
import { CdpClient } from "@coinbase/cdp-sdk";
|
|
10
|
+
import { encodeFunctionData } from "viem";
|
|
11
|
+
import { REGISTRY_ADDRESS, REGISTRY_ABI, REGISTRATION_TYPE } from "./constants.js";
|
|
12
|
+
/**
|
|
13
|
+
* Create a gasless smart account for an AI agent.
|
|
14
|
+
*
|
|
15
|
+
* The account is an ERC-4337 smart account on Base, owned by a CDP-managed
|
|
16
|
+
* EOA. All transactions are gas-sponsored by the CDP Paymaster.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { createAgentAccount } from "@a3stack/accounts";
|
|
21
|
+
*
|
|
22
|
+
* const agent = await createAgentAccount({
|
|
23
|
+
* apiKeyId: process.env.CDP_API_KEY_ID!,
|
|
24
|
+
* apiKeySecret: process.env.CDP_API_KEY_SECRET!,
|
|
25
|
+
* walletSecret: process.env.CDP_WALLET_SECRET!,
|
|
26
|
+
* }, { name: "my-agent" });
|
|
27
|
+
*
|
|
28
|
+
* // Register on ERC-8004 with zero gas
|
|
29
|
+
* const result = await agent.register({
|
|
30
|
+
* name: "My Agent",
|
|
31
|
+
* description: "An autonomous AI agent",
|
|
32
|
+
* });
|
|
33
|
+
* console.log(`Registered! Tx: ${result.transactionHash}`);
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export async function createAgentAccount(credentials, options = {}) {
|
|
37
|
+
const { apiKeyId, apiKeySecret, walletSecret } = credentials;
|
|
38
|
+
const network = options.testnet ? "base-sepolia" : "base";
|
|
39
|
+
const accountName = options.name ?? "a3stack-agent";
|
|
40
|
+
// Initialize CDP client
|
|
41
|
+
const cdp = new CdpClient({ apiKeyId, apiKeySecret, walletSecret });
|
|
42
|
+
// Create or retrieve the owner EOA
|
|
43
|
+
const owner = await cdp.evm.getOrCreateAccount({
|
|
44
|
+
name: `${accountName}-owner`,
|
|
45
|
+
});
|
|
46
|
+
// Create or retrieve the smart account
|
|
47
|
+
const smartAccount = await cdp.evm.getOrCreateSmartAccount({
|
|
48
|
+
name: accountName,
|
|
49
|
+
owner,
|
|
50
|
+
});
|
|
51
|
+
// Scope to Base network
|
|
52
|
+
const scopedAccount = await smartAccount.useNetwork(network);
|
|
53
|
+
// Build the AgentAccount interface
|
|
54
|
+
const agentAccount = {
|
|
55
|
+
address: smartAccount.address,
|
|
56
|
+
ownerAddress: owner.address,
|
|
57
|
+
network: network,
|
|
58
|
+
async sendUserOperation(calls) {
|
|
59
|
+
const userOp = await scopedAccount.sendUserOperation({
|
|
60
|
+
calls: calls.map((c) => ({
|
|
61
|
+
to: c.to,
|
|
62
|
+
value: c.value ?? 0n,
|
|
63
|
+
data: c.data ?? "0x",
|
|
64
|
+
})),
|
|
65
|
+
});
|
|
66
|
+
const receipt = await scopedAccount.waitForUserOperation(userOp);
|
|
67
|
+
const txHash = receipt.transactionHash ?? String(receipt);
|
|
68
|
+
return {
|
|
69
|
+
userOpHash: userOp.userOpHash ?? String(userOp),
|
|
70
|
+
transactionHash: txHash,
|
|
71
|
+
};
|
|
72
|
+
},
|
|
73
|
+
async register(opts) {
|
|
74
|
+
// Build the agent registration JSON
|
|
75
|
+
const registration = {
|
|
76
|
+
type: REGISTRATION_TYPE,
|
|
77
|
+
name: opts.name,
|
|
78
|
+
description: opts.description,
|
|
79
|
+
...(opts.image ? { image: opts.image } : {}),
|
|
80
|
+
services: opts.services ?? [],
|
|
81
|
+
x402Support: opts.x402Support ?? false,
|
|
82
|
+
active: true,
|
|
83
|
+
registrations: opts.existingRegistrations ?? [],
|
|
84
|
+
};
|
|
85
|
+
const json = JSON.stringify(registration);
|
|
86
|
+
const agentURI = `data:application/json;base64,${Buffer.from(json).toString("base64")}`;
|
|
87
|
+
// Encode the register() call
|
|
88
|
+
const callData = encodeFunctionData({
|
|
89
|
+
abi: REGISTRY_ABI,
|
|
90
|
+
functionName: "register",
|
|
91
|
+
args: [agentURI],
|
|
92
|
+
});
|
|
93
|
+
// Send gasless UserOperation
|
|
94
|
+
const userOp = await scopedAccount.sendUserOperation({
|
|
95
|
+
calls: [{
|
|
96
|
+
to: REGISTRY_ADDRESS,
|
|
97
|
+
value: 0n,
|
|
98
|
+
data: callData,
|
|
99
|
+
}],
|
|
100
|
+
});
|
|
101
|
+
const receipt = await scopedAccount.waitForUserOperation(userOp);
|
|
102
|
+
const txHash = receipt.transactionHash ?? String(receipt);
|
|
103
|
+
return {
|
|
104
|
+
transactionHash: txHash,
|
|
105
|
+
userOpHash: userOp.userOpHash ?? String(userOp),
|
|
106
|
+
smartAccountAddress: smartAccount.address,
|
|
107
|
+
network,
|
|
108
|
+
gasCost: 0,
|
|
109
|
+
sponsored: true,
|
|
110
|
+
};
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
return agentAccount;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=smart-account.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smart-account.js","sourceRoot":"","sources":["../src/smart-account.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for @a3stack/accounts
|
|
3
|
+
*/
|
|
4
|
+
export interface CdpCredentials {
|
|
5
|
+
/** CDP API Key ID */
|
|
6
|
+
apiKeyId: string;
|
|
7
|
+
/** CDP API Key Secret */
|
|
8
|
+
apiKeySecret: string;
|
|
9
|
+
/** CDP Wallet Secret (EC P-256 PKCS8 key, base64-encoded) */
|
|
10
|
+
walletSecret: string;
|
|
11
|
+
}
|
|
12
|
+
export interface CreateAgentAccountOptions {
|
|
13
|
+
/** Human-readable name for the account (used for idempotent getOrCreate) */
|
|
14
|
+
name?: string;
|
|
15
|
+
/** Use testnet (Base Sepolia) instead of mainnet */
|
|
16
|
+
testnet?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface AgentAccount {
|
|
19
|
+
/** Smart account address (ERC-4337) */
|
|
20
|
+
address: `0x${string}`;
|
|
21
|
+
/** Owner EOA address */
|
|
22
|
+
ownerAddress: `0x${string}`;
|
|
23
|
+
/** The network used */
|
|
24
|
+
network: "base" | "base-sepolia";
|
|
25
|
+
/** Send a gasless UserOperation */
|
|
26
|
+
sendUserOperation: (calls: UserOperationCall[]) => Promise<UserOperationResult>;
|
|
27
|
+
/** Register this agent on ERC-8004 with zero gas */
|
|
28
|
+
register: (options: RegisterOptions) => Promise<RegisterResult>;
|
|
29
|
+
}
|
|
30
|
+
export interface UserOperationCall {
|
|
31
|
+
to: `0x${string}`;
|
|
32
|
+
value?: bigint;
|
|
33
|
+
data?: `0x${string}`;
|
|
34
|
+
}
|
|
35
|
+
export interface UserOperationResult {
|
|
36
|
+
userOpHash: string;
|
|
37
|
+
transactionHash: string;
|
|
38
|
+
}
|
|
39
|
+
export interface RegisterOptions {
|
|
40
|
+
/** Agent name */
|
|
41
|
+
name: string;
|
|
42
|
+
/** Agent description */
|
|
43
|
+
description: string;
|
|
44
|
+
/** Agent image URL (optional) */
|
|
45
|
+
image?: string;
|
|
46
|
+
/** Service endpoints */
|
|
47
|
+
services?: Array<{
|
|
48
|
+
type: string;
|
|
49
|
+
url: string;
|
|
50
|
+
}>;
|
|
51
|
+
/** Whether agent supports x402 payments */
|
|
52
|
+
x402Support?: boolean;
|
|
53
|
+
/** Existing registrations from other chains */
|
|
54
|
+
existingRegistrations?: Array<{
|
|
55
|
+
agentId: number;
|
|
56
|
+
agentRegistry: string;
|
|
57
|
+
}>;
|
|
58
|
+
}
|
|
59
|
+
export interface RegisterResult {
|
|
60
|
+
/** Transaction hash on Base */
|
|
61
|
+
transactionHash: string;
|
|
62
|
+
/** UserOperation hash */
|
|
63
|
+
userOpHash: string;
|
|
64
|
+
/** Smart account address */
|
|
65
|
+
smartAccountAddress: `0x${string}`;
|
|
66
|
+
/** Network used */
|
|
67
|
+
network: string;
|
|
68
|
+
/** Gas cost to user (always 0 with Paymaster) */
|
|
69
|
+
gasCost: number;
|
|
70
|
+
/** Whether gas was sponsored */
|
|
71
|
+
sponsored: boolean;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,cAAc;IAC7B,qBAAqB;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,6DAA6D;IAC7D,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,yBAAyB;IACxC,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,uCAAuC;IACvC,OAAO,EAAE,KAAK,MAAM,EAAE,CAAC;IACvB,wBAAwB;IACxB,YAAY,EAAE,KAAK,MAAM,EAAE,CAAC;IAC5B,uBAAuB;IACvB,OAAO,EAAE,MAAM,GAAG,cAAc,CAAC;IACjC,mCAAmC;IACnC,iBAAiB,EAAE,CAAC,KAAK,EAAE,iBAAiB,EAAE,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAChF,oDAAoD;IACpD,QAAQ,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;CACjE;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,KAAK,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,wBAAwB;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wBAAwB;IACxB,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,2CAA2C;IAC3C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+CAA+C;IAC/C,qBAAqB,CAAC,EAAE,KAAK,CAAC;QAC5B,OAAO,EAAE,MAAM,CAAC;QAChB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,cAAc;IAC7B,+BAA+B;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,yBAAyB;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,mBAAmB,EAAE,KAAK,MAAM,EAAE,CAAC;IACnC,mBAAmB;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,gCAAgC;IAChC,SAAS,EAAE,OAAO,CAAC;CACpB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@a3stack/accounts",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Gasless smart accounts for ERC-8004 agent registration via CDP Paymaster",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"typecheck": "tsc --noEmit",
|
|
17
|
+
"dev": "tsc --watch"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@coinbase/cdp-sdk": "^1.44.1",
|
|
21
|
+
"viem": "^2.46.2"
|
|
22
|
+
},
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"erc-8004",
|
|
28
|
+
"agent",
|
|
29
|
+
"identity",
|
|
30
|
+
"gasless",
|
|
31
|
+
"smart-account",
|
|
32
|
+
"cdp",
|
|
33
|
+
"paymaster",
|
|
34
|
+
"base"
|
|
35
|
+
],
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/arcabotai/a3stack",
|
|
40
|
+
"directory": "packages/accounts"
|
|
41
|
+
}
|
|
42
|
+
}
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constants for @a3stack/accounts
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/** ERC-8004 Identity Registry — same address on all chains */
|
|
6
|
+
export const REGISTRY_ADDRESS = "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432" as const;
|
|
7
|
+
|
|
8
|
+
/** ERC-8004 registration type URI */
|
|
9
|
+
export const REGISTRATION_TYPE = "https://eips.ethereum.org/EIPS/eip-8004#registration-v1";
|
|
10
|
+
|
|
11
|
+
/** Zero address */
|
|
12
|
+
export const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" as const;
|
|
13
|
+
|
|
14
|
+
/** Minimal ABI for ERC-8004 register + Transfer event */
|
|
15
|
+
export const REGISTRY_ABI = [
|
|
16
|
+
{
|
|
17
|
+
name: "register",
|
|
18
|
+
type: "function",
|
|
19
|
+
stateMutability: "nonpayable",
|
|
20
|
+
inputs: [{ name: "agentURI", type: "string" }],
|
|
21
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: "setAgentURI",
|
|
25
|
+
type: "function",
|
|
26
|
+
stateMutability: "nonpayable",
|
|
27
|
+
inputs: [
|
|
28
|
+
{ name: "agentId", type: "uint256" },
|
|
29
|
+
{ name: "newURI", type: "string" },
|
|
30
|
+
],
|
|
31
|
+
outputs: [],
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: "balanceOf",
|
|
35
|
+
type: "function",
|
|
36
|
+
stateMutability: "view",
|
|
37
|
+
inputs: [{ name: "owner", type: "address" }],
|
|
38
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: "Transfer",
|
|
42
|
+
type: "event",
|
|
43
|
+
inputs: [
|
|
44
|
+
{ name: "from", type: "address", indexed: true },
|
|
45
|
+
{ name: "to", type: "address", indexed: true },
|
|
46
|
+
{ name: "tokenId", type: "uint256", indexed: true },
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
] as const;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convenience function for one-shot gasless registration.
|
|
3
|
+
*
|
|
4
|
+
* For more control, use createAgentAccount() directly.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createAgentAccount } from "./smart-account.js";
|
|
8
|
+
import type { CdpCredentials, RegisterOptions, RegisterResult } from "./types.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Register an agent on ERC-8004 with zero gas cost (one-shot).
|
|
12
|
+
*
|
|
13
|
+
* Creates a smart account and registers in a single call.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { gaslessRegister } from "@a3stack/accounts";
|
|
18
|
+
*
|
|
19
|
+
* const result = await gaslessRegister(
|
|
20
|
+
* {
|
|
21
|
+
* apiKeyId: process.env.CDP_API_KEY_ID!,
|
|
22
|
+
* apiKeySecret: process.env.CDP_API_KEY_SECRET!,
|
|
23
|
+
* walletSecret: process.env.CDP_WALLET_SECRET!,
|
|
24
|
+
* },
|
|
25
|
+
* {
|
|
26
|
+
* name: "my-agent",
|
|
27
|
+
* description: "An AI agent that does cool things",
|
|
28
|
+
* services: [{ type: "website", url: "https://myagent.ai" }],
|
|
29
|
+
* }
|
|
30
|
+
* );
|
|
31
|
+
*
|
|
32
|
+
* console.log(`Registered at ${result.smartAccountAddress}`);
|
|
33
|
+
* console.log(`Tx: ${result.transactionHash}`);
|
|
34
|
+
* console.log(`Gas cost: $${result.gasCost}`); // $0
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export async function gaslessRegister(
|
|
38
|
+
credentials: CdpCredentials,
|
|
39
|
+
options: RegisterOptions & { accountName?: string; testnet?: boolean }
|
|
40
|
+
): Promise<RegisterResult> {
|
|
41
|
+
const agent = await createAgentAccount(credentials, {
|
|
42
|
+
name: options.accountName ?? `agent-${options.name.toLowerCase().replace(/\s+/g, "-")}`,
|
|
43
|
+
testnet: options.testnet,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return agent.register(options);
|
|
47
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @a3stack/accounts — Gasless smart accounts for AI agents
|
|
3
|
+
*
|
|
4
|
+
* Create ERC-4337 smart accounts with automatic gas sponsorship
|
|
5
|
+
* via CDP Paymaster. Register agents on ERC-8004 with zero gas cost.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { createAgentAccount } from "@a3stack/accounts";
|
|
10
|
+
*
|
|
11
|
+
* const agent = await createAgentAccount({
|
|
12
|
+
* apiKeyId: process.env.CDP_API_KEY_ID!,
|
|
13
|
+
* apiKeySecret: process.env.CDP_API_KEY_SECRET!,
|
|
14
|
+
* walletSecret: process.env.CDP_WALLET_SECRET!,
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* // Register on-chain with zero gas
|
|
18
|
+
* const result = await agent.register({
|
|
19
|
+
* name: "My Agent",
|
|
20
|
+
* description: "Does cool stuff",
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export { createAgentAccount } from "./smart-account.js";
|
|
26
|
+
export { gaslessRegister } from "./gasless-register.js";
|
|
27
|
+
export { REGISTRY_ADDRESS, REGISTRY_ABI, REGISTRATION_TYPE } from "./constants.js";
|
|
28
|
+
export type {
|
|
29
|
+
CdpCredentials,
|
|
30
|
+
CreateAgentAccountOptions,
|
|
31
|
+
AgentAccount,
|
|
32
|
+
RegisterOptions,
|
|
33
|
+
RegisterResult,
|
|
34
|
+
UserOperationCall,
|
|
35
|
+
UserOperationResult,
|
|
36
|
+
} from "./types.js";
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CDP Smart Account wrapper for gasless agent operations
|
|
3
|
+
*
|
|
4
|
+
* Uses Coinbase Developer Platform SDK for:
|
|
5
|
+
* - Server wallet management (EOA owner)
|
|
6
|
+
* - Smart account creation (ERC-4337)
|
|
7
|
+
* - Automatic gas sponsorship via CDP Paymaster on Base
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { CdpClient } from "@coinbase/cdp-sdk";
|
|
11
|
+
import { encodeFunctionData } from "viem";
|
|
12
|
+
import { REGISTRY_ADDRESS, REGISTRY_ABI, REGISTRATION_TYPE } from "./constants.js";
|
|
13
|
+
import type {
|
|
14
|
+
CdpCredentials,
|
|
15
|
+
CreateAgentAccountOptions,
|
|
16
|
+
AgentAccount,
|
|
17
|
+
RegisterOptions,
|
|
18
|
+
RegisterResult,
|
|
19
|
+
UserOperationCall,
|
|
20
|
+
UserOperationResult,
|
|
21
|
+
} from "./types.js";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Create a gasless smart account for an AI agent.
|
|
25
|
+
*
|
|
26
|
+
* The account is an ERC-4337 smart account on Base, owned by a CDP-managed
|
|
27
|
+
* EOA. All transactions are gas-sponsored by the CDP Paymaster.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* import { createAgentAccount } from "@a3stack/accounts";
|
|
32
|
+
*
|
|
33
|
+
* const agent = await createAgentAccount({
|
|
34
|
+
* apiKeyId: process.env.CDP_API_KEY_ID!,
|
|
35
|
+
* apiKeySecret: process.env.CDP_API_KEY_SECRET!,
|
|
36
|
+
* walletSecret: process.env.CDP_WALLET_SECRET!,
|
|
37
|
+
* }, { name: "my-agent" });
|
|
38
|
+
*
|
|
39
|
+
* // Register on ERC-8004 with zero gas
|
|
40
|
+
* const result = await agent.register({
|
|
41
|
+
* name: "My Agent",
|
|
42
|
+
* description: "An autonomous AI agent",
|
|
43
|
+
* });
|
|
44
|
+
* console.log(`Registered! Tx: ${result.transactionHash}`);
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export async function createAgentAccount(
|
|
48
|
+
credentials: CdpCredentials,
|
|
49
|
+
options: CreateAgentAccountOptions = {}
|
|
50
|
+
): Promise<AgentAccount> {
|
|
51
|
+
const { apiKeyId, apiKeySecret, walletSecret } = credentials;
|
|
52
|
+
const network = options.testnet ? "base-sepolia" : "base";
|
|
53
|
+
const accountName = options.name ?? "a3stack-agent";
|
|
54
|
+
|
|
55
|
+
// Initialize CDP client
|
|
56
|
+
const cdp = new CdpClient({ apiKeyId, apiKeySecret, walletSecret });
|
|
57
|
+
|
|
58
|
+
// Create or retrieve the owner EOA
|
|
59
|
+
const owner = await cdp.evm.getOrCreateAccount({
|
|
60
|
+
name: `${accountName}-owner`,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Create or retrieve the smart account
|
|
64
|
+
const smartAccount = await cdp.evm.getOrCreateSmartAccount({
|
|
65
|
+
name: accountName,
|
|
66
|
+
owner,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Scope to Base network
|
|
70
|
+
const scopedAccount = await smartAccount.useNetwork(network);
|
|
71
|
+
|
|
72
|
+
// Build the AgentAccount interface
|
|
73
|
+
const agentAccount: AgentAccount = {
|
|
74
|
+
address: smartAccount.address as `0x${string}`,
|
|
75
|
+
ownerAddress: owner.address as `0x${string}`,
|
|
76
|
+
network: network as "base" | "base-sepolia",
|
|
77
|
+
|
|
78
|
+
async sendUserOperation(calls: UserOperationCall[]): Promise<UserOperationResult> {
|
|
79
|
+
const userOp = await scopedAccount.sendUserOperation({
|
|
80
|
+
calls: calls.map((c) => ({
|
|
81
|
+
to: c.to,
|
|
82
|
+
value: c.value ?? 0n,
|
|
83
|
+
data: c.data ?? "0x",
|
|
84
|
+
})),
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const receipt = await scopedAccount.waitForUserOperation(userOp);
|
|
88
|
+
const txHash = (receipt as any).transactionHash ?? String(receipt);
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
userOpHash: (userOp as any).userOpHash ?? String(userOp),
|
|
92
|
+
transactionHash: txHash,
|
|
93
|
+
};
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
async register(opts: RegisterOptions): Promise<RegisterResult> {
|
|
97
|
+
// Build the agent registration JSON
|
|
98
|
+
const registration = {
|
|
99
|
+
type: REGISTRATION_TYPE,
|
|
100
|
+
name: opts.name,
|
|
101
|
+
description: opts.description,
|
|
102
|
+
...(opts.image ? { image: opts.image } : {}),
|
|
103
|
+
services: opts.services ?? [],
|
|
104
|
+
x402Support: opts.x402Support ?? false,
|
|
105
|
+
active: true,
|
|
106
|
+
registrations: opts.existingRegistrations ?? [],
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const json = JSON.stringify(registration);
|
|
110
|
+
const agentURI = `data:application/json;base64,${Buffer.from(json).toString("base64")}`;
|
|
111
|
+
|
|
112
|
+
// Encode the register() call
|
|
113
|
+
const callData = encodeFunctionData({
|
|
114
|
+
abi: REGISTRY_ABI,
|
|
115
|
+
functionName: "register",
|
|
116
|
+
args: [agentURI],
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// Send gasless UserOperation
|
|
120
|
+
const userOp = await scopedAccount.sendUserOperation({
|
|
121
|
+
calls: [{
|
|
122
|
+
to: REGISTRY_ADDRESS,
|
|
123
|
+
value: 0n,
|
|
124
|
+
data: callData,
|
|
125
|
+
}],
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
const receipt = await scopedAccount.waitForUserOperation(userOp);
|
|
129
|
+
const txHash = (receipt as any).transactionHash ?? String(receipt);
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
transactionHash: txHash,
|
|
133
|
+
userOpHash: (userOp as any).userOpHash ?? String(userOp),
|
|
134
|
+
smartAccountAddress: smartAccount.address as `0x${string}`,
|
|
135
|
+
network,
|
|
136
|
+
gasCost: 0,
|
|
137
|
+
sponsored: true,
|
|
138
|
+
};
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
return agentAccount;
|
|
143
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for @a3stack/accounts
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface CdpCredentials {
|
|
6
|
+
/** CDP API Key ID */
|
|
7
|
+
apiKeyId: string;
|
|
8
|
+
/** CDP API Key Secret */
|
|
9
|
+
apiKeySecret: string;
|
|
10
|
+
/** CDP Wallet Secret (EC P-256 PKCS8 key, base64-encoded) */
|
|
11
|
+
walletSecret: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface CreateAgentAccountOptions {
|
|
15
|
+
/** Human-readable name for the account (used for idempotent getOrCreate) */
|
|
16
|
+
name?: string;
|
|
17
|
+
/** Use testnet (Base Sepolia) instead of mainnet */
|
|
18
|
+
testnet?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface AgentAccount {
|
|
22
|
+
/** Smart account address (ERC-4337) */
|
|
23
|
+
address: `0x${string}`;
|
|
24
|
+
/** Owner EOA address */
|
|
25
|
+
ownerAddress: `0x${string}`;
|
|
26
|
+
/** The network used */
|
|
27
|
+
network: "base" | "base-sepolia";
|
|
28
|
+
/** Send a gasless UserOperation */
|
|
29
|
+
sendUserOperation: (calls: UserOperationCall[]) => Promise<UserOperationResult>;
|
|
30
|
+
/** Register this agent on ERC-8004 with zero gas */
|
|
31
|
+
register: (options: RegisterOptions) => Promise<RegisterResult>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface UserOperationCall {
|
|
35
|
+
to: `0x${string}`;
|
|
36
|
+
value?: bigint;
|
|
37
|
+
data?: `0x${string}`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface UserOperationResult {
|
|
41
|
+
userOpHash: string;
|
|
42
|
+
transactionHash: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface RegisterOptions {
|
|
46
|
+
/** Agent name */
|
|
47
|
+
name: string;
|
|
48
|
+
/** Agent description */
|
|
49
|
+
description: string;
|
|
50
|
+
/** Agent image URL (optional) */
|
|
51
|
+
image?: string;
|
|
52
|
+
/** Service endpoints */
|
|
53
|
+
services?: Array<{ type: string; url: string }>;
|
|
54
|
+
/** Whether agent supports x402 payments */
|
|
55
|
+
x402Support?: boolean;
|
|
56
|
+
/** Existing registrations from other chains */
|
|
57
|
+
existingRegistrations?: Array<{
|
|
58
|
+
agentId: number;
|
|
59
|
+
agentRegistry: string;
|
|
60
|
+
}>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface RegisterResult {
|
|
64
|
+
/** Transaction hash on Base */
|
|
65
|
+
transactionHash: string;
|
|
66
|
+
/** UserOperation hash */
|
|
67
|
+
userOpHash: string;
|
|
68
|
+
/** Smart account address */
|
|
69
|
+
smartAccountAddress: `0x${string}`;
|
|
70
|
+
/** Network used */
|
|
71
|
+
network: string;
|
|
72
|
+
/** Gas cost to user (always 0 with Paymaster) */
|
|
73
|
+
gasCost: number;
|
|
74
|
+
/** Whether gas was sponsored */
|
|
75
|
+
sponsored: boolean;
|
|
76
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Integration test for @a3stack/accounts
|
|
4
|
+
*
|
|
5
|
+
* Tests:
|
|
6
|
+
* 1. Import from compiled dist
|
|
7
|
+
* 2. createAgentAccount() — creates smart account via CDP
|
|
8
|
+
* 3. agent.register() — gasless ERC-8004 registration on Base
|
|
9
|
+
* 4. gaslessRegister() — one-shot convenience function
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* node test/integration.mjs [--live]
|
|
13
|
+
*
|
|
14
|
+
* Without --live: tests imports and account creation only (no on-chain tx)
|
|
15
|
+
* With --live: executes a real gasless registration on Base mainnet
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { execSync } from "child_process";
|
|
19
|
+
|
|
20
|
+
// Import from compiled dist
|
|
21
|
+
const {
|
|
22
|
+
createAgentAccount,
|
|
23
|
+
gaslessRegister,
|
|
24
|
+
REGISTRY_ADDRESS,
|
|
25
|
+
REGISTRY_ABI,
|
|
26
|
+
REGISTRATION_TYPE,
|
|
27
|
+
} = await import("../dist/index.js");
|
|
28
|
+
|
|
29
|
+
const LIVE = process.argv.includes("--live");
|
|
30
|
+
|
|
31
|
+
function keychain(key) {
|
|
32
|
+
try {
|
|
33
|
+
return execSync(`security find-generic-password -s "${key}" -w 2>/dev/null`, {
|
|
34
|
+
encoding: "utf8",
|
|
35
|
+
}).trim();
|
|
36
|
+
} catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function assert(condition, msg) {
|
|
42
|
+
if (!condition) {
|
|
43
|
+
console.error(` ❌ FAIL: ${msg}`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
console.log(` ✅ ${msg}`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function main() {
|
|
50
|
+
console.log("🧪 @a3stack/accounts Integration Tests\n");
|
|
51
|
+
|
|
52
|
+
// --- Test 1: Exports ---
|
|
53
|
+
console.log("1️⃣ Exports");
|
|
54
|
+
assert(typeof createAgentAccount === "function", "createAgentAccount is a function");
|
|
55
|
+
assert(typeof gaslessRegister === "function", "gaslessRegister is a function");
|
|
56
|
+
assert(REGISTRY_ADDRESS === "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432", "REGISTRY_ADDRESS correct");
|
|
57
|
+
assert(Array.isArray(REGISTRY_ABI), "REGISTRY_ABI is an array");
|
|
58
|
+
assert(REGISTRATION_TYPE.includes("eip-8004"), "REGISTRATION_TYPE contains eip-8004");
|
|
59
|
+
|
|
60
|
+
// --- Test 2: Credentials ---
|
|
61
|
+
console.log("\n2️⃣ Credentials");
|
|
62
|
+
const credentials = {
|
|
63
|
+
apiKeyId: process.env.CDP_API_KEY_ID || keychain("cdp-api-key-id"),
|
|
64
|
+
apiKeySecret: process.env.CDP_API_KEY_SECRET || keychain("cdp-api-secret"),
|
|
65
|
+
walletSecret: process.env.CDP_WALLET_SECRET || keychain("cdp-wallet-secret"),
|
|
66
|
+
};
|
|
67
|
+
assert(!!credentials.apiKeyId, "CDP API Key ID loaded");
|
|
68
|
+
assert(!!credentials.apiKeySecret, "CDP API Key Secret loaded");
|
|
69
|
+
assert(!!credentials.walletSecret, "CDP Wallet Secret loaded");
|
|
70
|
+
|
|
71
|
+
// --- Test 3: Account creation ---
|
|
72
|
+
console.log("\n3️⃣ Account Creation");
|
|
73
|
+
const testName = `a3stack-test-${Date.now()}`;
|
|
74
|
+
const agent = await createAgentAccount(credentials, { name: testName });
|
|
75
|
+
|
|
76
|
+
assert(agent.address.startsWith("0x"), `Smart account: ${agent.address}`);
|
|
77
|
+
assert(agent.ownerAddress.startsWith("0x"), `Owner EOA: ${agent.ownerAddress}`);
|
|
78
|
+
assert(agent.network === "base", `Network: ${agent.network}`);
|
|
79
|
+
assert(typeof agent.sendUserOperation === "function", "sendUserOperation is a function");
|
|
80
|
+
assert(typeof agent.register === "function", "register is a function");
|
|
81
|
+
|
|
82
|
+
// --- Test 4: Idempotent retrieval ---
|
|
83
|
+
console.log("\n4️⃣ Idempotent Retrieval");
|
|
84
|
+
const agent2 = await createAgentAccount(credentials, { name: testName });
|
|
85
|
+
assert(agent2.address === agent.address, `Same name returns same address: ${agent2.address}`);
|
|
86
|
+
assert(agent2.ownerAddress === agent.ownerAddress, "Same owner address");
|
|
87
|
+
|
|
88
|
+
if (!LIVE) {
|
|
89
|
+
console.log("\n⏭️ Skipping live registration (run with --live to execute on-chain)");
|
|
90
|
+
console.log("\n✅ All tests passed!");
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// --- Test 5: Live gasless registration ---
|
|
95
|
+
console.log("\n5️⃣ Live Gasless Registration (Base mainnet)");
|
|
96
|
+
console.log(" ⛽ Sending UserOperation (CDP Paymaster sponsors gas)...");
|
|
97
|
+
|
|
98
|
+
const result = await agent.register({
|
|
99
|
+
name: "A3Stack Test Agent (integration)",
|
|
100
|
+
description: "Integration test for @a3stack/accounts package",
|
|
101
|
+
services: [{ type: "website", url: "https://a3stack.arcabot.ai" }],
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
assert(result.transactionHash.length > 0, `Tx hash: ${result.transactionHash}`);
|
|
105
|
+
assert(result.userOpHash.length > 0, `UserOp hash: ${result.userOpHash}`);
|
|
106
|
+
assert(result.smartAccountAddress === agent.address, "Smart account matches");
|
|
107
|
+
assert(result.network === "base", "Network is base");
|
|
108
|
+
assert(result.gasCost === 0, "Gas cost is $0");
|
|
109
|
+
assert(result.sponsored === true, "Gas was sponsored");
|
|
110
|
+
|
|
111
|
+
console.log(`\n🎉 Live registration successful!`);
|
|
112
|
+
console.log(` BaseScan: https://basescan.org/tx/${result.transactionHash}`);
|
|
113
|
+
|
|
114
|
+
console.log("\n✅ All tests passed!");
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
main().catch((err) => {
|
|
118
|
+
console.error("\n❌ Test failed:", err.message || err);
|
|
119
|
+
if (err.cause) console.error(" Cause:", err.cause);
|
|
120
|
+
process.exit(1);
|
|
121
|
+
});
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "Node16",
|
|
5
|
+
"moduleResolution": "node16",
|
|
6
|
+
"lib": ["ES2022"],
|
|
7
|
+
"strict": true,
|
|
8
|
+
"declaration": true,
|
|
9
|
+
"declarationMap": true,
|
|
10
|
+
"sourceMap": true,
|
|
11
|
+
"outDir": "dist",
|
|
12
|
+
"rootDir": "src",
|
|
13
|
+
"esModuleInterop": true,
|
|
14
|
+
"skipLibCheck": true,
|
|
15
|
+
"resolveJsonModule": true,
|
|
16
|
+
"allowImportingTsExtensions": false,
|
|
17
|
+
"noEmitOnError": false
|
|
18
|
+
},
|
|
19
|
+
"include": ["src/**/*"],
|
|
20
|
+
"exclude": ["node_modules", "dist", "**/*.test.ts"]
|
|
21
|
+
}
|