@azeth/sdk 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.
Files changed (115) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +139 -0
  3. package/dist/account/balance.d.ts +41 -0
  4. package/dist/account/balance.d.ts.map +1 -0
  5. package/dist/account/balance.js +264 -0
  6. package/dist/account/balance.js.map +1 -0
  7. package/dist/account/create.d.ts +27 -0
  8. package/dist/account/create.d.ts.map +1 -0
  9. package/dist/account/create.js +116 -0
  10. package/dist/account/create.js.map +1 -0
  11. package/dist/account/deposit.d.ts +34 -0
  12. package/dist/account/deposit.d.ts.map +1 -0
  13. package/dist/account/deposit.js +88 -0
  14. package/dist/account/deposit.js.map +1 -0
  15. package/dist/account/guardian-approval.d.ts +111 -0
  16. package/dist/account/guardian-approval.d.ts.map +1 -0
  17. package/dist/account/guardian-approval.js +223 -0
  18. package/dist/account/guardian-approval.js.map +1 -0
  19. package/dist/account/guardian.d.ts +27 -0
  20. package/dist/account/guardian.d.ts.map +1 -0
  21. package/dist/account/guardian.js +67 -0
  22. package/dist/account/guardian.js.map +1 -0
  23. package/dist/account/history.d.ts +22 -0
  24. package/dist/account/history.d.ts.map +1 -0
  25. package/dist/account/history.js +144 -0
  26. package/dist/account/history.js.map +1 -0
  27. package/dist/account/transfer.d.ts +28 -0
  28. package/dist/account/transfer.d.ts.map +1 -0
  29. package/dist/account/transfer.js +137 -0
  30. package/dist/account/transfer.js.map +1 -0
  31. package/dist/auth/erc8128.d.ts +14 -0
  32. package/dist/auth/erc8128.d.ts.map +1 -0
  33. package/dist/auth/erc8128.js +92 -0
  34. package/dist/auth/erc8128.js.map +1 -0
  35. package/dist/client.d.ts +394 -0
  36. package/dist/client.d.ts.map +1 -0
  37. package/dist/client.js +970 -0
  38. package/dist/client.js.map +1 -0
  39. package/dist/events/emitter.d.ts +96 -0
  40. package/dist/events/emitter.d.ts.map +1 -0
  41. package/dist/events/emitter.js +90 -0
  42. package/dist/events/emitter.js.map +1 -0
  43. package/dist/index.d.ts +29 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +33 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/messaging/message-router.d.ts +69 -0
  48. package/dist/messaging/message-router.d.ts.map +1 -0
  49. package/dist/messaging/message-router.js +307 -0
  50. package/dist/messaging/message-router.js.map +1 -0
  51. package/dist/messaging/rate-limiter.d.ts +31 -0
  52. package/dist/messaging/rate-limiter.d.ts.map +1 -0
  53. package/dist/messaging/rate-limiter.js +74 -0
  54. package/dist/messaging/rate-limiter.js.map +1 -0
  55. package/dist/messaging/xmtp.d.ts +144 -0
  56. package/dist/messaging/xmtp.d.ts.map +1 -0
  57. package/dist/messaging/xmtp.js +473 -0
  58. package/dist/messaging/xmtp.js.map +1 -0
  59. package/dist/payments/agreements.d.ts +87 -0
  60. package/dist/payments/agreements.d.ts.map +1 -0
  61. package/dist/payments/agreements.js +337 -0
  62. package/dist/payments/agreements.js.map +1 -0
  63. package/dist/payments/budget.d.ts +118 -0
  64. package/dist/payments/budget.d.ts.map +1 -0
  65. package/dist/payments/budget.js +176 -0
  66. package/dist/payments/budget.js.map +1 -0
  67. package/dist/payments/smart-fetch.d.ts +65 -0
  68. package/dist/payments/smart-fetch.d.ts.map +1 -0
  69. package/dist/payments/smart-fetch.js +115 -0
  70. package/dist/payments/smart-fetch.js.map +1 -0
  71. package/dist/payments/x402.d.ts +89 -0
  72. package/dist/payments/x402.d.ts.map +1 -0
  73. package/dist/payments/x402.js +620 -0
  74. package/dist/payments/x402.js.map +1 -0
  75. package/dist/registry/discover.d.ts +43 -0
  76. package/dist/registry/discover.d.ts.map +1 -0
  77. package/dist/registry/discover.js +272 -0
  78. package/dist/registry/discover.js.map +1 -0
  79. package/dist/registry/register.d.ts +44 -0
  80. package/dist/registry/register.d.ts.map +1 -0
  81. package/dist/registry/register.js +126 -0
  82. package/dist/registry/register.js.map +1 -0
  83. package/dist/reputation/opinion.d.ts +52 -0
  84. package/dist/reputation/opinion.d.ts.map +1 -0
  85. package/dist/reputation/opinion.js +198 -0
  86. package/dist/reputation/opinion.js.map +1 -0
  87. package/dist/utils/addresses.d.ts +6 -0
  88. package/dist/utils/addresses.d.ts.map +1 -0
  89. package/dist/utils/addresses.js +53 -0
  90. package/dist/utils/addresses.js.map +1 -0
  91. package/dist/utils/errors.d.ts +23 -0
  92. package/dist/utils/errors.d.ts.map +1 -0
  93. package/dist/utils/errors.js +188 -0
  94. package/dist/utils/errors.js.map +1 -0
  95. package/dist/utils/execution.d.ts +20 -0
  96. package/dist/utils/execution.d.ts.map +1 -0
  97. package/dist/utils/execution.js +28 -0
  98. package/dist/utils/execution.js.map +1 -0
  99. package/dist/utils/paymaster.d.ts +35 -0
  100. package/dist/utils/paymaster.d.ts.map +1 -0
  101. package/dist/utils/paymaster.js +115 -0
  102. package/dist/utils/paymaster.js.map +1 -0
  103. package/dist/utils/retry.d.ts +19 -0
  104. package/dist/utils/retry.d.ts.map +1 -0
  105. package/dist/utils/retry.js +68 -0
  106. package/dist/utils/retry.js.map +1 -0
  107. package/dist/utils/userop.d.ts +55 -0
  108. package/dist/utils/userop.d.ts.map +1 -0
  109. package/dist/utils/userop.js +201 -0
  110. package/dist/utils/userop.js.map +1 -0
  111. package/dist/utils/validation.d.ts +8 -0
  112. package/dist/utils/validation.d.ts.map +1 -0
  113. package/dist/utils/validation.js +35 -0
  114. package/dist/utils/validation.js.map +1 -0
  115. package/package.json +63 -0
@@ -0,0 +1,115 @@
1
+ import { http } from 'viem';
2
+ import { entryPoint07Address } from 'viem/account-abstraction';
3
+ import { createPimlicoClient } from 'permissionless/clients/pimlico';
4
+ /** In-memory daily sponsorship counter.
5
+ * Resets at midnight UTC by tracking the current date string. */
6
+ class SponsorshipCounter {
7
+ counts = new Map();
8
+ currentDay = '';
9
+ /** Increment and return the new count for the given account.
10
+ * Returns 0-based pre-increment count (i.e., the count BEFORE this call). */
11
+ incrementAndGet(account) {
12
+ const today = new Date().toISOString().slice(0, 10);
13
+ if (today !== this.currentDay) {
14
+ this.counts.clear();
15
+ this.currentDay = today;
16
+ }
17
+ const key = account.toLowerCase();
18
+ const current = this.counts.get(key) ?? 0;
19
+ this.counts.set(key, current + 1);
20
+ return current;
21
+ }
22
+ }
23
+ const dailyCounter = new SponsorshipCounter();
24
+ /** Estimate total gas cost in wei from UserOp gas fields.
25
+ * Uses maxFeePerGas * (callGasLimit + verificationGasLimit + preVerificationGas)
26
+ * as a conservative upper bound. Returns 0n if fields are missing. */
27
+ function estimateGasCostWei(params) {
28
+ const maxFeePerGas = params['maxFeePerGas'];
29
+ const callGasLimit = params['callGasLimit'];
30
+ const verificationGasLimit = params['verificationGasLimit'];
31
+ const preVerificationGas = params['preVerificationGas'];
32
+ if (!maxFeePerGas)
33
+ return 0n;
34
+ const totalGas = (callGasLimit ?? 0n) + (verificationGasLimit ?? 0n) + (preVerificationGas ?? 0n);
35
+ return maxFeePerGas * totalGas;
36
+ }
37
+ /** Check if the policy allows sponsoring this UserOp.
38
+ * Returns a reason string if denied, undefined if allowed. */
39
+ export function checkPolicy(policy, params) {
40
+ if (!policy)
41
+ return undefined;
42
+ const sender = params['sender'];
43
+ // Check allowedAccounts
44
+ if (policy.allowedAccounts && policy.allowedAccounts.length > 0 && sender) {
45
+ const allowed = policy.allowedAccounts.some((a) => a.toLowerCase() === sender.toLowerCase());
46
+ if (!allowed) {
47
+ return `Account ${sender} not in paymaster allowedAccounts`;
48
+ }
49
+ }
50
+ // Check daily limit
51
+ if (policy.maxSponsoredPerDay && policy.maxSponsoredPerDay > 0 && sender) {
52
+ const countBefore = dailyCounter.incrementAndGet(sender);
53
+ if (countBefore >= policy.maxSponsoredPerDay) {
54
+ return `Account ${sender} exceeded daily sponsorship limit (${policy.maxSponsoredPerDay})`;
55
+ }
56
+ }
57
+ // Check max gas cost
58
+ if (policy.maxGasCostWei && policy.maxGasCostWei > 0n) {
59
+ const cost = estimateGasCostWei(params);
60
+ if (cost > 0n && cost > policy.maxGasCostWei) {
61
+ return `Estimated gas cost ${cost} wei exceeds maxGasCostWei ${policy.maxGasCostWei}`;
62
+ }
63
+ }
64
+ return undefined;
65
+ }
66
+ /** Create a paymaster middleware that wraps a PimlicoClient with graceful fallback
67
+ * and optional policy enforcement.
68
+ *
69
+ * When the paymaster is unreachable or rejects the UserOp, the middleware returns
70
+ * empty paymaster data so the UserOp falls back to self-paid gas.
71
+ *
72
+ * @param paymasterUrl - URL for the paymaster RPC endpoint
73
+ * @param policy - Optional sponsorship policy for client-side filtering
74
+ * @returns PaymasterMiddleware compatible with permissionless's createSmartAccountClient
75
+ */
76
+ export function createPaymasterMiddleware(paymasterUrl, policy) {
77
+ const pimlicoClient = createPimlicoClient({
78
+ transport: http(paymasterUrl),
79
+ entryPoint: { address: entryPoint07Address, version: '0.7' },
80
+ });
81
+ return {
82
+ getPaymasterData: async (params) => {
83
+ // Policy check before calling the paymaster
84
+ const policyDenial = checkPolicy(policy, params);
85
+ if (policyDenial) {
86
+ console.warn(`[azeth] Paymaster policy denied: ${policyDenial}. Falling back to self-paid gas.`);
87
+ return {};
88
+ }
89
+ try {
90
+ return await pimlicoClient.getPaymasterData(params);
91
+ }
92
+ catch (err) {
93
+ const message = err instanceof Error ? err.message : String(err);
94
+ console.warn(`[azeth] Paymaster getPaymasterData failed: ${message}. Falling back to self-paid gas.`);
95
+ return {};
96
+ }
97
+ },
98
+ getPaymasterStubData: async (params) => {
99
+ // Policy check applies to stub data too (same sender, same policy)
100
+ const policyDenial = checkPolicy(policy, params);
101
+ if (policyDenial) {
102
+ return {};
103
+ }
104
+ try {
105
+ return await pimlicoClient.getPaymasterStubData(params);
106
+ }
107
+ catch (err) {
108
+ const message = err instanceof Error ? err.message : String(err);
109
+ console.warn(`[azeth] Paymaster getPaymasterStubData failed: ${message}. Falling back to self-paid gas.`);
110
+ return {};
111
+ }
112
+ },
113
+ };
114
+ }
115
+ //# sourceMappingURL=paymaster.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paymaster.js","sourceRoot":"","sources":["../../src/utils/paymaster.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export interface RetryOptions {
2
+ /** Maximum number of retry attempts (default: 3) */
3
+ maxRetries?: number;
4
+ /** Base delay in ms before first retry (default: 1000) */
5
+ baseDelay?: number;
6
+ /** Maximum delay in ms between retries (default: 10000) */
7
+ maxDelay?: number;
8
+ /** Custom predicate to determine if an error is retryable */
9
+ retryOn?: (error: unknown) => boolean;
10
+ }
11
+ /** Execute a function with exponential backoff retry logic.
12
+ *
13
+ * Retries on network errors and 5xx-like failures by default.
14
+ * Uses exponential backoff with jitter to avoid thundering herd.
15
+ *
16
+ * @throws The last error encountered after all retries are exhausted
17
+ */
18
+ export declare function withRetry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T>;
19
+ //# sourceMappingURL=retry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/utils/retry.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC3B,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;CACvC;AAsCD;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAC/B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,CAAC,CAAC,CA6BZ"}
@@ -0,0 +1,68 @@
1
+ import { AzethError } from '@azeth/common';
2
+ /** LOW-8 fix: Retryable Node.js error codes (stable across versions, unlike message strings) */
3
+ const RETRYABLE_ERROR_CODES = new Set([
4
+ 'ECONNREFUSED', 'ECONNRESET', 'ETIMEDOUT', 'ENOTFOUND',
5
+ 'EHOSTUNREACH', 'ENETUNREACH', 'EPIPE', 'UND_ERR_CONNECT_TIMEOUT',
6
+ 'UND_ERR_SOCKET', 'UND_ERR_HEADERS_TIMEOUT',
7
+ ]);
8
+ /** Default retry predicate: retries on network errors and 5xx status codes */
9
+ function isRetryableError(error) {
10
+ if (error instanceof AzethError) {
11
+ return error.code === 'NETWORK_ERROR';
12
+ }
13
+ if (error instanceof TypeError && error.message.includes('fetch')) {
14
+ return true;
15
+ }
16
+ if (error instanceof Error) {
17
+ // LOW-8 fix: Prefer stable error codes over fragile string matching.
18
+ // Node.js system errors (and undici) expose a `code` property.
19
+ const errCode = error.code;
20
+ if (errCode && RETRYABLE_ERROR_CODES.has(errCode)) {
21
+ return true;
22
+ }
23
+ // Fallback: string matching for environments without error codes
24
+ const msg = error.message.toLowerCase();
25
+ return msg.includes('network') ||
26
+ msg.includes('econnrefused') ||
27
+ msg.includes('econnreset') ||
28
+ msg.includes('etimedout') ||
29
+ msg.includes('socket hang up') ||
30
+ msg.includes('503') ||
31
+ msg.includes('502') ||
32
+ msg.includes('429');
33
+ }
34
+ return false;
35
+ }
36
+ /** Execute a function with exponential backoff retry logic.
37
+ *
38
+ * Retries on network errors and 5xx-like failures by default.
39
+ * Uses exponential backoff with jitter to avoid thundering herd.
40
+ *
41
+ * @throws The last error encountered after all retries are exhausted
42
+ */
43
+ export async function withRetry(fn, options) {
44
+ const maxRetries = options?.maxRetries ?? 3;
45
+ const baseDelay = options?.baseDelay ?? 1000;
46
+ const maxDelay = options?.maxDelay ?? 10000;
47
+ const retryOn = options?.retryOn ?? isRetryableError;
48
+ let lastError;
49
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
50
+ try {
51
+ return await fn();
52
+ }
53
+ catch (err) {
54
+ lastError = err;
55
+ if (attempt >= maxRetries || !retryOn(err)) {
56
+ throw err;
57
+ }
58
+ // Exponential backoff with jitter
59
+ const exponentialDelay = baseDelay * Math.pow(2, attempt);
60
+ const jitter = Math.random() * baseDelay;
61
+ const delay = Math.min(exponentialDelay + jitter, maxDelay);
62
+ await new Promise(resolve => setTimeout(resolve, delay));
63
+ }
64
+ }
65
+ // Unreachable but satisfies TypeScript
66
+ throw lastError;
67
+ }
68
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/utils/retry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ import { type PublicClient, type WalletClient, type Chain, type Transport, type Account } from 'viem';
2
+ import { type SmartAccount } from 'viem/account-abstraction';
3
+ import { type SmartAccountClient as PermissionlessSmartAccountClient } from 'permissionless';
4
+ import { type PaymasterPolicy } from './paymaster.js';
5
+ /** SmartAccountClient type with concrete SmartAccount (not `SmartAccount | undefined`).
6
+ * This ensures sendTransaction() doesn't require explicit `account` parameter. */
7
+ export type AzethSmartAccountClient = PermissionlessSmartAccountClient<Transport, Chain, SmartAccount>;
8
+ export interface SmartAccountClientConfig {
9
+ publicClient: PublicClient<Transport, Chain>;
10
+ walletClient: WalletClient<Transport, Chain, Account>;
11
+ smartAccountAddress: `0x${string}`;
12
+ bundlerUrl?: string;
13
+ paymasterUrl?: string;
14
+ /** Client-side sponsorship policy for paymaster gas sponsorship.
15
+ * Only applies when paymasterUrl is configured. */
16
+ paymasterPolicy?: PaymasterPolicy;
17
+ /** Optional guardian co-signing key. When set, every UserOperation gets a
18
+ * 130-byte dual signature (owner 65 bytes + guardian 65 bytes), enabling
19
+ * operations that exceed standard spending limits. */
20
+ guardianKey?: `0x${string}`;
21
+ /** Azeth server URL. Used as bundler fallback on testnet — the server
22
+ * proxies bundler requests using its own PIMLICO_API_KEY so developers
23
+ * don't need their own key for getting started. */
24
+ serverUrl?: string;
25
+ }
26
+ /**
27
+ * Create a viem SmartAccount implementation for an existing deployed AzethAccount.
28
+ *
29
+ * This wraps a deployed AzethAccount v12 smart account as a viem SmartAccount
30
+ * that can be used with permissionless's createSmartAccountClient to submit
31
+ * UserOperations through ERC-4337 EntryPoint v0.7.
32
+ *
33
+ * The signing flow matches GuardianModule expectations:
34
+ * - Computes getUserOperationHash (ERC-4337 standard)
35
+ * - Signs with walletClient.signMessage({ message: { raw: hash } })
36
+ * - This produces sign(keccak256("\x19Ethereum Signed Message:\n32" + userOpHash))
37
+ * - GuardianModule._splitSignature expects ECDSA owner sig as first 65 bytes
38
+ */
39
+ export declare function createAzethSmartAccount(publicClient: PublicClient<Transport, Chain>, walletClient: WalletClient<Transport, Chain, Account>, smartAccountAddress: `0x${string}`, guardianKey?: `0x${string}`): Promise<SmartAccount>;
40
+ /**
41
+ * Create a permissionless SmartAccountClient for an AzethAccount.
42
+ *
43
+ * The SmartAccountClient handles the full ERC-4337 flow:
44
+ * 1. Encodes calls via account.encodeCalls()
45
+ * 2. Gets nonce from EntryPoint
46
+ * 3. Estimates gas via bundler
47
+ * 4. Signs UserOp via account.signUserOperation()
48
+ * 5. Submits to bundler via eth_sendUserOperation
49
+ * 6. Waits for receipt and returns transaction hash
50
+ *
51
+ * @param config - Configuration with clients, smart account address, and bundler URL
52
+ * @returns A SmartAccountClient that can be used for sendTransaction/writeContract
53
+ */
54
+ export declare function createAzethSmartAccountClient(config: SmartAccountClientConfig): Promise<AzethSmartAccountClient>;
55
+ //# sourceMappingURL=userop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"userop.d.ts","sourceRoot":"","sources":["../../src/utils/userop.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,KAAK,EACV,KAAK,SAAS,EACd,KAAK,OAAO,EAKb,MAAM,MAAM,CAAC;AAEd,OAAO,EAEL,KAAK,YAAY,EAIlB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAA4B,KAAK,kBAAkB,IAAI,gCAAgC,EAAE,MAAM,gBAAgB,CAAC;AAIvH,OAAO,EAA6B,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjF;mFACmF;AACnF,MAAM,MAAM,uBAAuB,GAAG,gCAAgC,CAAC,SAAS,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;AAEvG,MAAM,WAAW,wBAAwB;IACvC,YAAY,EAAE,YAAY,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC7C,YAAY,EAAE,YAAY,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IACtD,mBAAmB,EAAE,KAAK,MAAM,EAAE,CAAC;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;wDACoD;IACpD,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC;;2DAEuD;IACvD,WAAW,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;IAC5B;;wDAEoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,uBAAuB,CAC3C,YAAY,EAAE,YAAY,CAAC,SAAS,EAAE,KAAK,CAAC,EAC5C,YAAY,EAAE,YAAY,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,EACrD,mBAAmB,EAAE,KAAK,MAAM,EAAE,EAClC,WAAW,CAAC,EAAE,KAAK,MAAM,EAAE,GAC1B,OAAO,CAAC,YAAY,CAAC,CAgIvB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,6BAA6B,CACjD,MAAM,EAAE,wBAAwB,GAC/B,OAAO,CAAC,uBAAuB,CAAC,CAyElC"}
@@ -0,0 +1,201 @@
1
+ import { encodeFunctionData, http, createNonceManager, } from 'viem';
2
+ import { privateKeyToAccount } from 'viem/accounts';
3
+ import { toSmartAccount, entryPoint07Abi, entryPoint07Address, getUserOperationHash, } from 'viem/account-abstraction';
4
+ import { createSmartAccountClient } from 'permissionless';
5
+ import { AzethAccountAbi } from '@azeth/common/abis';
6
+ import { AzethError, SUPPORTED_CHAINS, getBundlerUrl, getPaymasterUrl, getServerBundlerUrl } from '@azeth/common';
7
+ import { encodeSimpleSingle, encodeSimpleBatch, encodeSingleExecution, encodeBatchExecution } from './execution.js';
8
+ import { createPaymasterMiddleware } from './paymaster.js';
9
+ /**
10
+ * Create a viem SmartAccount implementation for an existing deployed AzethAccount.
11
+ *
12
+ * This wraps a deployed AzethAccount v12 smart account as a viem SmartAccount
13
+ * that can be used with permissionless's createSmartAccountClient to submit
14
+ * UserOperations through ERC-4337 EntryPoint v0.7.
15
+ *
16
+ * The signing flow matches GuardianModule expectations:
17
+ * - Computes getUserOperationHash (ERC-4337 standard)
18
+ * - Signs with walletClient.signMessage({ message: { raw: hash } })
19
+ * - This produces sign(keccak256("\x19Ethereum Signed Message:\n32" + userOpHash))
20
+ * - GuardianModule._splitSignature expects ECDSA owner sig as first 65 bytes
21
+ */
22
+ export async function createAzethSmartAccount(publicClient, walletClient, smartAccountAddress, guardianKey) {
23
+ const chainId = publicClient.chain?.id;
24
+ if (!chainId) {
25
+ throw new AzethError('Public client must have a chain configured', 'NETWORK_ERROR');
26
+ }
27
+ return toSmartAccount({
28
+ client: publicClient,
29
+ entryPoint: {
30
+ abi: entryPoint07Abi,
31
+ address: entryPoint07Address,
32
+ version: '0.7',
33
+ },
34
+ // Override viem's default time-based nonce key manager.
35
+ // viem defaults to Date.now() as the nonce key, which produces 192-bit
36
+ // timestamp keys (e.g., key=1771722560333). Our EntryPoint nonces live
37
+ // at key=0, so the SDK would sign a UserOp with nonce=(timestamp<<64|seq)
38
+ // while the bundler/EntryPoint expects nonce=(0<<64|seq) — causing AA24.
39
+ nonceKeyManager: createNonceManager({
40
+ source: {
41
+ get() { return 0; },
42
+ set() { },
43
+ },
44
+ }),
45
+ // Return the existing deployed account address
46
+ getAddress: async () => smartAccountAddress,
47
+ // Our account is already deployed — no factory needed
48
+ getFactoryArgs: async () => ({
49
+ factory: undefined,
50
+ factoryData: undefined,
51
+ }),
52
+ // Encode calls into AzethAccount.execute() callData
53
+ encodeCalls: async (calls) => {
54
+ if (calls.length === 0) {
55
+ throw new AzethError('At least one call is required', 'INVALID_INPUT');
56
+ }
57
+ if (calls.length === 1) {
58
+ const call = calls[0];
59
+ return encodeFunctionData({
60
+ abi: AzethAccountAbi,
61
+ functionName: 'execute',
62
+ args: [
63
+ encodeSimpleSingle(),
64
+ encodeSingleExecution(call.to, call.value ?? 0n, (call.data ?? '0x')),
65
+ ],
66
+ });
67
+ }
68
+ // Batch execution: encode multiple calls into a single UserOp
69
+ return encodeFunctionData({
70
+ abi: AzethAccountAbi,
71
+ functionName: 'execute',
72
+ args: [
73
+ encodeSimpleBatch(),
74
+ encodeBatchExecution(calls.map(c => ({
75
+ target: c.to,
76
+ value: c.value ?? 0n,
77
+ data: (c.data ?? '0x'),
78
+ }))),
79
+ ],
80
+ });
81
+ },
82
+ // Sign a personal message (EIP-191) via the owner EOA
83
+ signMessage: async ({ message }) => {
84
+ return walletClient.signMessage({ message });
85
+ },
86
+ // Sign a UserOperation: compute the ERC-4337 userOpHash and sign it
87
+ signUserOperation: async (userOperation) => {
88
+ const userOpForHash = {
89
+ ...userOperation,
90
+ sender: userOperation.sender ?? smartAccountAddress,
91
+ };
92
+ const hash = getUserOperationHash({
93
+ chainId,
94
+ entryPointAddress: entryPoint07Address,
95
+ entryPointVersion: '0.7',
96
+ userOperation: userOpForHash,
97
+ });
98
+ // Sign with EIP-191 personal sign: this produces
99
+ // sign(keccak256("\x19Ethereum Signed Message:\n32" + hash))
100
+ // which matches GuardianModule's ecrecover(hash.toEthSignedMessageHash(), v, r, s)
101
+ const ownerSig = await walletClient.signMessage({ message: { raw: hash } });
102
+ // Guardian co-signature: append 65-byte guardian sig to produce 130-byte dual signature
103
+ if (guardianKey) {
104
+ const guardianAccount = privateKeyToAccount(guardianKey);
105
+ const guardianSig = await guardianAccount.signMessage({ message: { raw: hash } });
106
+ // Concatenate: ownerSig (0x + 128 hex chars) + guardianSig (128 hex chars, no 0x prefix)
107
+ return (ownerSig + guardianSig.slice(2));
108
+ }
109
+ return ownerSig;
110
+ },
111
+ // Sign typed data via the owner EOA
112
+ signTypedData: async (typedData) => {
113
+ return walletClient.signTypedData(typedData);
114
+ },
115
+ // 65-byte dummy signature for gas estimation.
116
+ // Must be a valid ECDSA signature (r=1, s=1, v=27) so tryRecover succeeds
117
+ // and the full validateUserOp code path executes (guardrails, oracle, etc.).
118
+ // An all-0xFF stub triggers ECDSAInvalidSignatureS, taking a short path that
119
+ // causes the bundler to underestimate verificationGasLimit (AA26).
120
+ getStubSignature: async () => {
121
+ const stub65 = ('0x' + '00'.repeat(31) + '01' + '00'.repeat(31) + '01' + '1b');
122
+ if (guardianKey) {
123
+ // 130-byte stub: two valid ECDSA dummy signatures for owner + guardian
124
+ return (stub65 + stub65.slice(2));
125
+ }
126
+ return stub65;
127
+ },
128
+ });
129
+ }
130
+ /**
131
+ * Create a permissionless SmartAccountClient for an AzethAccount.
132
+ *
133
+ * The SmartAccountClient handles the full ERC-4337 flow:
134
+ * 1. Encodes calls via account.encodeCalls()
135
+ * 2. Gets nonce from EntryPoint
136
+ * 3. Estimates gas via bundler
137
+ * 4. Signs UserOp via account.signUserOperation()
138
+ * 5. Submits to bundler via eth_sendUserOperation
139
+ * 6. Waits for receipt and returns transaction hash
140
+ *
141
+ * @param config - Configuration with clients, smart account address, and bundler URL
142
+ * @returns A SmartAccountClient that can be used for sendTransaction/writeContract
143
+ */
144
+ export async function createAzethSmartAccountClient(config) {
145
+ const { publicClient, walletClient, smartAccountAddress, bundlerUrl, paymasterPolicy } = config;
146
+ const chainId = publicClient.chain?.id;
147
+ if (!chainId) {
148
+ throw new AzethError('Public client must have a chain configured', 'NETWORK_ERROR');
149
+ }
150
+ // Resolve chain name from chain ID for URL resolution
151
+ const chainName = Object.entries(SUPPORTED_CHAINS)
152
+ .find(([, c]) => c.id === chainId)?.[0];
153
+ // Resolve bundler URL: explicit config > env var > chain base URL + API key > error
154
+ let resolvedBundlerUrl = bundlerUrl;
155
+ if (!resolvedBundlerUrl) {
156
+ if (chainName) {
157
+ const apiKey = typeof globalThis.process !== 'undefined'
158
+ ? globalThis.process.env?.['PIMLICO_API_KEY']
159
+ : undefined;
160
+ resolvedBundlerUrl = getBundlerUrl(chainName, apiKey);
161
+ }
162
+ }
163
+ // Fallback: use Azeth server bundler proxy (testnet gas sponsorship)
164
+ if (!resolvedBundlerUrl && config.serverUrl) {
165
+ resolvedBundlerUrl = getServerBundlerUrl(config.serverUrl);
166
+ }
167
+ if (!resolvedBundlerUrl) {
168
+ throw new AzethError('bundlerUrl is required for UserOperation submission. ' +
169
+ 'Set PIMLICO_API_KEY or AZETH_BUNDLER_URL env var, or pass bundlerUrl in AzethKitConfig. ' +
170
+ 'Get a free key at https://dashboard.pimlico.io or https://portal.cdp.coinbase.com.', 'INVALID_INPUT', { chainId });
171
+ }
172
+ // Resolve paymaster URL: explicit config > env var > chain default (same as bundler for Pimlico)
173
+ let resolvedPaymasterUrl = config.paymasterUrl;
174
+ if (!resolvedPaymasterUrl) {
175
+ resolvedPaymasterUrl = typeof globalThis.process !== 'undefined'
176
+ ? globalThis.process.env?.['AZETH_PAYMASTER_URL']
177
+ : undefined;
178
+ if (!resolvedPaymasterUrl && chainName) {
179
+ const apiKey = typeof globalThis.process !== 'undefined'
180
+ ? globalThis.process.env?.['PIMLICO_API_KEY']
181
+ : undefined;
182
+ resolvedPaymasterUrl = getPaymasterUrl(chainName, apiKey);
183
+ }
184
+ }
185
+ const smartAccount = await createAzethSmartAccount(publicClient, walletClient, smartAccountAddress, config.guardianKey);
186
+ // Build SmartAccountClient config with optional paymaster
187
+ const clientConfig = {
188
+ account: smartAccount,
189
+ chain: publicClient.chain,
190
+ bundlerTransport: http(resolvedBundlerUrl),
191
+ client: publicClient,
192
+ };
193
+ // Wire paymaster middleware when URL is available.
194
+ // The middleware handles graceful fallback: if the paymaster rejects or is
195
+ // unreachable, the UserOp falls back to self-paid gas (no crash).
196
+ if (resolvedPaymasterUrl) {
197
+ clientConfig.paymaster = createPaymasterMiddleware(resolvedPaymasterUrl, paymasterPolicy);
198
+ }
199
+ return createSmartAccountClient(clientConfig);
200
+ }
201
+ //# sourceMappingURL=userop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"userop.js","sourceRoot":"","sources":["../../src/utils/userop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /** Validate that a string is a valid Ethereum address (0x + 40 hex chars).
2
+ * L-12 fix (Audit #8): Also rejects the zero address to prevent accidental fund burns. */
3
+ export declare function validateAddress(address: string, fieldName: string): void;
4
+ /** Validate that a URL is well-formed HTTP(S). Optionally require HTTPS. */
5
+ export declare function validateUrl(url: string, fieldName: string, requireHttps?: boolean): void;
6
+ /** Validate that a bigint amount is positive */
7
+ export declare function validatePositiveAmount(amount: bigint, fieldName: string): void;
8
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAEA;2FAC2F;AAC3F,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAexE;AAED,4EAA4E;AAC5E,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,UAAQ,GAAG,IAAI,CAatF;AAED,gDAAgD;AAChD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAQ9E"}
@@ -0,0 +1,35 @@
1
+ import { AzethError } from '@azeth/common';
2
+ /** Validate that a string is a valid Ethereum address (0x + 40 hex chars).
3
+ * L-12 fix (Audit #8): Also rejects the zero address to prevent accidental fund burns. */
4
+ export function validateAddress(address, fieldName) {
5
+ if (!/^0x[a-fA-F0-9]{40}$/.test(address)) {
6
+ throw new AzethError('Invalid Ethereum address format', 'INVALID_INPUT', { field: fieldName });
7
+ }
8
+ if (address === '0x0000000000000000000000000000000000000000') {
9
+ throw new AzethError('Cannot use the zero address', 'INVALID_INPUT', { field: fieldName });
10
+ }
11
+ }
12
+ /** Validate that a URL is well-formed HTTP(S). Optionally require HTTPS. */
13
+ export function validateUrl(url, fieldName, requireHttps = false) {
14
+ try {
15
+ const parsed = new URL(url);
16
+ if (requireHttps && parsed.protocol !== 'https:') {
17
+ throw new AzethError('URL must use HTTPS', 'INVALID_INPUT', { field: fieldName });
18
+ }
19
+ if (!['http:', 'https:'].includes(parsed.protocol)) {
20
+ throw new AzethError('URL must use HTTP or HTTPS', 'INVALID_INPUT', { field: fieldName });
21
+ }
22
+ }
23
+ catch (e) {
24
+ if (e instanceof AzethError)
25
+ throw e;
26
+ throw new AzethError('Invalid URL format', 'INVALID_INPUT', { field: fieldName });
27
+ }
28
+ }
29
+ /** Validate that a bigint amount is positive */
30
+ export function validatePositiveAmount(amount, fieldName) {
31
+ if (amount <= 0n) {
32
+ throw new AzethError(`Invalid ${fieldName}: must be greater than 0`, 'INVALID_INPUT', { field: fieldName, value: amount.toString() });
33
+ }
34
+ }
35
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C;2FAC2F;AAC3F,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,SAAiB;IAChE,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,UAAU,CAClB,iCAAiC,EACjC,eAAe,EACf,EAAE,KAAK,EAAE,SAAS,EAAE,CACrB,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,KAAK,4CAA4C,EAAE,CAAC;QAC7D,MAAM,IAAI,UAAU,CAClB,6BAA6B,EAC7B,eAAe,EACf,EAAE,KAAK,EAAE,SAAS,EAAE,CACrB,CAAC;IACJ,CAAC;AACH,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,SAAiB,EAAE,YAAY,GAAG,KAAK;IAC9E,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,YAAY,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACjD,MAAM,IAAI,UAAU,CAAC,oBAAoB,EAAE,eAAe,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QACpF,CAAC;QACD,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,UAAU,CAAC,4BAA4B,EAAE,eAAe,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,YAAY,UAAU;YAAE,MAAM,CAAC,CAAC;QACrC,MAAM,IAAI,UAAU,CAAC,oBAAoB,EAAE,eAAe,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IACpF,CAAC;AACH,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,sBAAsB,CAAC,MAAc,EAAE,SAAiB;IACtE,IAAI,MAAM,IAAI,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,UAAU,CAClB,WAAW,SAAS,0BAA0B,EAC9C,eAAe,EACf,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,EAAE,CAC/C,CAAC;IACJ,CAAC;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@azeth/sdk",
3
+ "version": "0.2.0",
4
+ "type": "module",
5
+ "description": "TypeScript SDK for the Azeth trust infrastructure — smart accounts, x402 payments, reputation, and service discovery",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/azeth-protocol/sdk.git"
10
+ },
11
+ "homepage": "https://azeth.ai",
12
+ "keywords": [
13
+ "azeth",
14
+ "sdk",
15
+ "machine-economy",
16
+ "trust-registry",
17
+ "erc-4337",
18
+ "smart-accounts",
19
+ "x402",
20
+ "payments",
21
+ "reputation",
22
+ "xmtp"
23
+ ],
24
+ "main": "dist/index.js",
25
+ "types": "dist/index.d.ts",
26
+ "files": [
27
+ "dist/",
28
+ "README.md",
29
+ "LICENSE"
30
+ ],
31
+ "dependencies": {
32
+ "@azeth/common": "^0.2.0",
33
+ "@x402/core": "^2.4.0",
34
+ "@x402/extensions": "^2.4.0",
35
+ "@xmtp/agent-sdk": "^2.2.0",
36
+ "permissionless": "^0.3.4",
37
+ "viem": "^2.21.0"
38
+ },
39
+ "devDependencies": {
40
+ "@stryker-mutator/core": "^8.6.0",
41
+ "@stryker-mutator/vitest-runner": "^8.6.0",
42
+ "@types/node": "^22.0.0",
43
+ "typescript": "^5.7.0",
44
+ "vitest": "^2.1.0",
45
+ "@changesets/cli": "^2.27.0"
46
+ },
47
+ "publishConfig": {
48
+ "access": "public"
49
+ },
50
+ "engines": {
51
+ "node": ">=20.0.0"
52
+ },
53
+ "scripts": {
54
+ "build": "tsc --project tsconfig.json",
55
+ "dev": "tsc --watch",
56
+ "test": "vitest run",
57
+ "test:watch": "vitest",
58
+ "typecheck": "tsc --noEmit",
59
+ "clean": "rm -rf dist",
60
+ "test:mutation": "npx stryker run",
61
+ "release": "pnpm build && changeset publish"
62
+ }
63
+ }