@atxp/polygon 0.8.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 (44) hide show
  1. package/README.md +497 -0
  2. package/dist/cache.d.ts +19 -0
  3. package/dist/cache.d.ts.map +1 -0
  4. package/dist/cache.js +11 -0
  5. package/dist/cache.js.map +1 -0
  6. package/dist/directWalletPaymentMaker.d.ts +35 -0
  7. package/dist/directWalletPaymentMaker.d.ts.map +1 -0
  8. package/dist/directWalletPaymentMaker.js +143 -0
  9. package/dist/directWalletPaymentMaker.js.map +1 -0
  10. package/dist/index.cjs +458 -0
  11. package/dist/index.cjs.map +1 -0
  12. package/dist/index.d.ts +145 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +446 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/polygonBrowserAccount.d.ts +40 -0
  17. package/dist/polygonBrowserAccount.d.ts.map +1 -0
  18. package/dist/polygonBrowserAccount.js +70 -0
  19. package/dist/polygonBrowserAccount.js.map +1 -0
  20. package/dist/polygonServerAccount.d.ts +35 -0
  21. package/dist/polygonServerAccount.d.ts.map +1 -0
  22. package/dist/polygonServerAccount.js +78 -0
  23. package/dist/polygonServerAccount.js.map +1 -0
  24. package/dist/serverPaymentMaker.d.ts +29 -0
  25. package/dist/serverPaymentMaker.d.ts.map +1 -0
  26. package/dist/serverPaymentMaker.js +173 -0
  27. package/dist/serverPaymentMaker.js.map +1 -0
  28. package/dist/smartWalletHelpers.d.ts +18 -0
  29. package/dist/smartWalletHelpers.d.ts.map +1 -0
  30. package/dist/smartWalletHelpers.js +93 -0
  31. package/dist/smartWalletHelpers.js.map +1 -0
  32. package/dist/smartWalletPaymentMaker.d.ts +29 -0
  33. package/dist/smartWalletPaymentMaker.d.ts.map +1 -0
  34. package/dist/smartWalletPaymentMaker.js +172 -0
  35. package/dist/smartWalletPaymentMaker.js.map +1 -0
  36. package/dist/spendPermissionShim.d.ts +19 -0
  37. package/dist/spendPermissionShim.d.ts.map +1 -0
  38. package/dist/spendPermissionShim.js +129 -0
  39. package/dist/spendPermissionShim.js.map +1 -0
  40. package/dist/testHelpers.d.ts +17 -0
  41. package/dist/testHelpers.d.ts.map +1 -0
  42. package/dist/types.d.ts +11 -0
  43. package/dist/types.d.ts.map +1 -0
  44. package/package.json +57 -0
@@ -0,0 +1,172 @@
1
+ import { getPolygonUSDCAddress } from '@atxp/client';
2
+ import { polygon } from 'viem/chains';
3
+ import { ConsoleLogger, constructEIP1271Message, createEIP1271AuthData, createEIP1271JWT } from '@atxp/common';
4
+ import { encodeFunctionData, parseEther } from 'viem';
5
+ import { prepareSpendCallData } from './spendPermissionShim.js';
6
+
7
+ const USDC_DECIMALS = 6;
8
+ // Minimal ERC20 ABI for transfer function
9
+ const ERC20_ABI = [
10
+ {
11
+ inputs: [
12
+ { name: 'to', type: 'address' },
13
+ { name: 'amount', type: 'uint256' }
14
+ ],
15
+ name: 'transfer',
16
+ outputs: [{ name: '', type: 'bool' }],
17
+ stateMutability: 'nonpayable',
18
+ type: 'function'
19
+ }
20
+ ];
21
+ async function waitForTransactionConfirmations(smartWallet, txHash, confirmations, logger) {
22
+ try {
23
+ const publicClient = smartWallet.client.account?.client;
24
+ if (publicClient && 'waitForTransactionReceipt' in publicClient) {
25
+ logger.info(`Waiting for ${confirmations} confirmations...`);
26
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
27
+ await publicClient.waitForTransactionReceipt({
28
+ hash: txHash,
29
+ confirmations: confirmations
30
+ });
31
+ logger.info(`Transaction confirmed with ${confirmations} confirmations`);
32
+ }
33
+ else {
34
+ logger.warn('Unable to wait for confirmations: client does not support waitForTransactionReceipt');
35
+ }
36
+ }
37
+ catch (error) {
38
+ logger.warn(`Could not wait for additional confirmations: ${error}`);
39
+ // Continue anyway - the transaction is already mined
40
+ }
41
+ }
42
+ /**
43
+ * Browser-based payment maker using ephemeral smart wallets with account abstraction.
44
+ * Uses Coinbase CDP for gasless transactions and spend permissions.
45
+ */
46
+ class SmartWalletPaymentMaker {
47
+ constructor(spendPermission, smartWallet, logger, chainId = polygon.id) {
48
+ if (!spendPermission) {
49
+ throw new Error('Spend permission is required');
50
+ }
51
+ if (!smartWallet) {
52
+ throw new Error('Smart wallet is required');
53
+ }
54
+ this.logger = logger ?? new ConsoleLogger();
55
+ this.spendPermission = spendPermission;
56
+ this.smartWallet = smartWallet;
57
+ this.chainId = chainId;
58
+ this.usdcAddress = getPolygonUSDCAddress(chainId);
59
+ }
60
+ getSourceAddress(_params) {
61
+ return this.smartWallet.account.address;
62
+ }
63
+ async generateJWT({ paymentRequestId, codeChallenge, accountId }) {
64
+ // Generate EIP-1271 auth data for smart wallet authentication
65
+ const timestamp = Math.floor(Date.now() / 1000);
66
+ const message = constructEIP1271Message({
67
+ walletAddress: this.smartWallet.account.address,
68
+ timestamp,
69
+ codeChallenge,
70
+ paymentRequestId,
71
+ ...(accountId ? { accountId } : {}),
72
+ });
73
+ // Sign the message - this will return an ABI-encoded signature from the smart wallet
74
+ const signature = await this.smartWallet.account.signMessage({
75
+ message: message
76
+ });
77
+ const authData = createEIP1271AuthData({
78
+ walletAddress: this.smartWallet.account.address,
79
+ message,
80
+ signature,
81
+ timestamp,
82
+ codeChallenge,
83
+ paymentRequestId,
84
+ ...(accountId ? { accountId } : {}),
85
+ });
86
+ const jwtToken = createEIP1271JWT(authData);
87
+ this.logger.info(`codeChallenge: ${codeChallenge}`);
88
+ this.logger.info(`paymentRequestId: ${paymentRequestId}`);
89
+ this.logger.info(`walletAddress: ${this.smartWallet.account.address}`);
90
+ this.logger.info(`Generated EIP-1271 JWT: ${jwtToken}`);
91
+ return jwtToken;
92
+ }
93
+ async makePayment(destinations, memo, _paymentRequestId) {
94
+ // Filter to polygon chain destinations
95
+ const polygonDestinations = destinations.filter(d => d.chain === 'polygon');
96
+ if (polygonDestinations.length === 0) {
97
+ this.logger.debug('PolygonPaymentMaker: No polygon destinations found, cannot handle payment');
98
+ return null; // Cannot handle these destinations
99
+ }
100
+ // Pick first polygon destination
101
+ const dest = polygonDestinations[0];
102
+ const amount = dest.amount;
103
+ const currency = dest.currency;
104
+ const receiver = dest.address;
105
+ if (currency !== 'USDC') {
106
+ throw new Error('Only usdc currency is supported; received ' + currency);
107
+ }
108
+ this.logger.info(`Making spendPermission payment of ${amount} ${currency} to ${receiver} on Polygon with memo: ${memo}`);
109
+ // Convert amount to USDC units (6 decimals) as BigInt for spendPermission
110
+ const amountInUSDCUnits = BigInt(amount.multipliedBy(10 ** USDC_DECIMALS).toFixed(0));
111
+ const spendCalls = await prepareSpendCallData({ permission: this.spendPermission, amount: amountInUSDCUnits });
112
+ // Add a second call to transfer USDC from the smart wallet to the receiver
113
+ let transferCallData = encodeFunctionData({
114
+ abi: ERC20_ABI,
115
+ functionName: "transfer",
116
+ args: [receiver, amountInUSDCUnits],
117
+ });
118
+ // Append memo to transfer call data if present
119
+ // This works because the EVM ignores extra calldata beyond what a function expects.
120
+ // The ERC20 transfer() function only reads the first 68 bytes (4-byte selector + 32-byte address + 32-byte amount).
121
+ // Any additional data appended after those 68 bytes is safely ignored by the USDC contract
122
+ // but remains accessible in the transaction data for payment verification.
123
+ // This is a well-established pattern used by OpenSea, Uniswap, and other major protocols.
124
+ if (memo && memo.trim()) {
125
+ const memoHex = Buffer.from(memo.trim(), 'utf8').toString('hex');
126
+ transferCallData = (transferCallData + memoHex);
127
+ this.logger.info(`Added memo "${memo.trim()}" to transfer call`);
128
+ }
129
+ const transferCall = {
130
+ to: this.usdcAddress,
131
+ data: transferCallData,
132
+ value: '0x0'
133
+ };
134
+ // Combine spend permission calls with the transfer call
135
+ const allCalls = [...spendCalls, transferCall];
136
+ this.logger.info(`Executing ${allCalls.length} calls (${spendCalls.length} spend permission + 1 transfer)`);
137
+ const hash = await this.smartWallet.client.sendUserOperation({
138
+ account: this.smartWallet.account,
139
+ calls: allCalls.map(call => {
140
+ return {
141
+ to: call.to,
142
+ data: call.data,
143
+ value: BigInt(call.value || '0x0')
144
+ };
145
+ }),
146
+ maxPriorityFeePerGas: parseEther('0.000000001')
147
+ });
148
+ const receipt = await this.smartWallet.client.waitForUserOperationReceipt({ hash });
149
+ if (!receipt) {
150
+ throw new Error('User operation failed');
151
+ }
152
+ // The receipt contains the actual transaction hash that was mined on chain
153
+ const txHash = receipt.receipt.transactionHash;
154
+ if (!txHash) {
155
+ throw new Error('User operation was executed but no transaction hash was returned. This should not happen.');
156
+ }
157
+ this.logger.info(`Spend permission executed successfully. UserOp: ${receipt.userOpHash}, TxHash: ${txHash}`);
158
+ // Wait for additional confirmations to ensure the transaction is well-propagated
159
+ // This helps avoid the "Transaction receipt could not be found" error
160
+ await waitForTransactionConfirmations(this.smartWallet, txHash, 2, this.logger);
161
+ // Return payment result with chain and currency
162
+ return {
163
+ transactionId: txHash,
164
+ transactionSubId: receipt.userOpHash,
165
+ chain: 'polygon',
166
+ currency: 'USDC'
167
+ };
168
+ }
169
+ }
170
+
171
+ export { SmartWalletPaymentMaker };
172
+ //# sourceMappingURL=smartWalletPaymentMaker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smartWalletPaymentMaker.js","sources":["../src/smartWalletPaymentMaker.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { Eip1193Provider, SpendPermission } from "./types.js";
2
+ export declare function requestSpendPermission(params: {
3
+ account: string;
4
+ spender: string;
5
+ token: string;
6
+ chainId: number;
7
+ allowance: bigint;
8
+ periodInDays: number;
9
+ provider: Eip1193Provider;
10
+ }): Promise<SpendPermission>;
11
+ export declare function prepareSpendCallData(params: {
12
+ permission: SpendPermission;
13
+ amount: bigint;
14
+ }): Promise<{
15
+ to: string;
16
+ data: string;
17
+ value: bigint;
18
+ }[]>;
19
+ //# sourceMappingURL=spendPermissionShim.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spendPermissionShim.d.ts","sourceRoot":"","sources":["../src/spendPermissionShim.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAqF9D,wBAAsB,sBAAsB,CAAC,MAAM,EAAE;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,eAAe,CAAC;CAC3B,GAAG,OAAO,CAAC,eAAe,CAAC,CAkC3B;AAED,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IACjD,UAAU,EAAE,eAAe,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAczD"}
@@ -0,0 +1,129 @@
1
+ import { createWalletClient, custom, encodeFunctionData } from 'viem';
2
+ import { polygon } from 'viem/chains';
3
+
4
+ /*
5
+ This shim uses ERC20 approvals for spend permissions on Polygon.
6
+
7
+ The upside is that it will work with any Polygon wallet/connector (MetaMask, WalletConnect, etc.).
8
+
9
+ The downside is that it's a worse user experience (the user might not be familiar with ERC20 approvals,
10
+ and their wallet might not explain it to them), and worse security (rather than a bounded recurring limit,
11
+ the user needs to grant a single fixed amount up-front—renewing that amount requires a new approval).
12
+ */
13
+ // TODO: this version of the shim will only work for the initial approval. we need logic that can conditionally
14
+ // require new approvals when the old one runs out. (this will require changing the API for this module, or at
15
+ // least introducting a new function)
16
+ // Minimal ERC20 ABI for approve and transferFrom functions
17
+ const ERC20_ABI = [
18
+ {
19
+ "constant": false,
20
+ "inputs": [
21
+ {
22
+ "name": "_spender",
23
+ "type": "address"
24
+ },
25
+ {
26
+ "name": "_value",
27
+ "type": "uint256"
28
+ }
29
+ ],
30
+ "name": "approve",
31
+ "outputs": [
32
+ {
33
+ "name": "",
34
+ "type": "bool"
35
+ }
36
+ ],
37
+ "payable": false,
38
+ "stateMutability": "nonpayable",
39
+ "type": "function"
40
+ },
41
+ {
42
+ "constant": false,
43
+ "inputs": [
44
+ {
45
+ "name": "_from",
46
+ "type": "address"
47
+ },
48
+ {
49
+ "name": "_to",
50
+ "type": "address"
51
+ },
52
+ {
53
+ "name": "_value",
54
+ "type": "uint256"
55
+ }
56
+ ],
57
+ "name": "transferFrom",
58
+ "outputs": [
59
+ {
60
+ "name": "",
61
+ "type": "bool"
62
+ }
63
+ ],
64
+ "payable": false,
65
+ "stateMutability": "nonpayable",
66
+ "type": "function"
67
+ }
68
+ ];
69
+ /**
70
+ * Get Polygon chain configuration by chain ID
71
+ */
72
+ function getPolygonChainConfig(chainId) {
73
+ switch (chainId) {
74
+ case 137: // Polygon mainnet
75
+ return polygon;
76
+ default:
77
+ throw new Error(`Unsupported Polygon Chain ID: ${chainId}. Supported chains: 137 (mainnet)`);
78
+ }
79
+ }
80
+ async function requestSpendPermission(params) {
81
+ // Validate chain ID and get chain config
82
+ const chainConfig = getPolygonChainConfig(params.chainId);
83
+ const client = createWalletClient({
84
+ chain: chainConfig,
85
+ transport: custom(params.provider)
86
+ });
87
+ // Use the client
88
+ const hash = await client.sendTransaction({
89
+ account: params.account,
90
+ to: params.token,
91
+ data: encodeFunctionData({
92
+ abi: ERC20_ABI,
93
+ functionName: "approve",
94
+ args: [params.spender, params.allowance]
95
+ })
96
+ });
97
+ return {
98
+ permission: {
99
+ account: params.account,
100
+ spender: params.spender,
101
+ token: params.token,
102
+ allowance: params.allowance.toString(),
103
+ period: params.periodInDays * 24 * 60 * 60,
104
+ start: Math.floor(Date.now() / 1000),
105
+ end: Math.floor(Date.now() / 1000) + params.periodInDays * 24 * 60 * 60,
106
+ salt: '0x0',
107
+ extraData: '0x0'
108
+ },
109
+ signature: hash
110
+ };
111
+ }
112
+ async function prepareSpendCallData(params) {
113
+ // this introduces an extra layer of indirection: user wallet -> ephemeral wallet -> receiver
114
+ // but the reason for this is that we can't sign JWTs from the user wallet directly
115
+ return [
116
+ {
117
+ to: params.permission.permission.token,
118
+ data: encodeFunctionData({
119
+ abi: ERC20_ABI,
120
+ functionName: 'transferFrom',
121
+ args: [params.permission.permission.account, params.permission.permission.spender, params.amount]
122
+ }),
123
+ value: BigInt(0)
124
+ }
125
+ ];
126
+ }
127
+
128
+ export { prepareSpendCallData, requestSpendPermission };
129
+ //# sourceMappingURL=spendPermissionShim.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spendPermissionShim.js","sources":["../src/spendPermissionShim.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { Mock } from 'vitest';
2
+ import type { Eip1193Provider } from './types.js';
3
+ import type { Hex } from 'viem';
4
+ export type MockEip1193Provider = Eip1193Provider & {
5
+ request: Mock;
6
+ };
7
+ export declare const TEST_WALLET_ADDRESS: Hex;
8
+ export declare const TEST_RECEIVER_ADDRESS: Hex;
9
+ export declare const TEST_PRIVATE_KEY: Hex;
10
+ export declare function mockLogger(): {
11
+ info: Mock<(...args: any[]) => any>;
12
+ warn: Mock<(...args: any[]) => any>;
13
+ error: Mock<(...args: any[]) => any>;
14
+ debug: Mock<(...args: any[]) => any>;
15
+ };
16
+ export declare function mockProvider(overrides?: Partial<MockEip1193Provider>): MockEip1193Provider;
17
+ //# sourceMappingURL=testHelpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testHelpers.d.ts","sourceRoot":"","sources":["../src/testHelpers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAGhC,MAAM,MAAM,mBAAmB,GAAG,eAAe,GAAG;IAClD,OAAO,EAAE,IAAI,CAAC;CACf,CAAC;AAGF,eAAO,MAAM,mBAAmB,EAAmD,GAAG,CAAC;AACvF,eAAO,MAAM,qBAAqB,EAAmD,GAAG,CAAC;AACzF,eAAO,MAAM,gBAAgB,EAA2E,GAAG,CAAC;AAG5G,wBAAgB,UAAU;;;;;EAOzB;AAGD,wBAAgB,YAAY,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,GAAG,mBAAmB,CAK1F"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * EIP-1193 compliant Ethereum provider interface
3
+ * Used for browser wallet integrations
4
+ */
5
+ export type Eip1193Provider = {
6
+ request: (params: {
7
+ method: string;
8
+ params?: unknown[];
9
+ }) => Promise<unknown>;
10
+ };
11
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,CAAC,MAAM,EAAE;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;KACpB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACxB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@atxp/polygon",
3
+ "version": "0.8.0",
4
+ "description": "ATXP for Polygon",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/atxp-dev/sdk.git",
9
+ "directory": "packages/atxp-polygon"
10
+ },
11
+ "type": "module",
12
+ "sideEffects": false,
13
+ "main": "./dist/index.cjs",
14
+ "module": "./dist/index.js",
15
+ "types": "./dist/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "import": "./dist/index.js",
20
+ "require": "./dist/index.cjs"
21
+ }
22
+ },
23
+ "files": [
24
+ "dist"
25
+ ],
26
+ "scripts": {
27
+ "build": "rollup -c",
28
+ "typecheck": "tsc --noEmit",
29
+ "lint": "eslint . --ext .ts",
30
+ "lint:fix": "eslint . --ext .ts --fix",
31
+ "test": "vitest run",
32
+ "prepack": "npm run build && npm run typecheck",
33
+ "pack:dry": "npm pack --dry-run"
34
+ },
35
+ "dependencies": {
36
+ "@atxp/client": "0.8.0",
37
+ "@atxp/common": "0.8.0",
38
+ "bignumber.js": "^9.3.0"
39
+ },
40
+ "peerDependencies": {
41
+ "viem": "^2.34.0"
42
+ },
43
+ "devDependencies": {
44
+ "@types/node": "^22.13.0",
45
+ "@types/supertest": "^6.0.3",
46
+ "@typescript-eslint/eslint-plugin": "^8.38.0",
47
+ "@typescript-eslint/parser": "^8.38.0",
48
+ "eslint": "^9.32.0",
49
+ "fetch-mock": "^12.5.2",
50
+ "happy-dom": "^15.11.6",
51
+ "jsdom": "^25.0.1",
52
+ "supertest": "^7.1.4",
53
+ "typescript": "^5.7.3",
54
+ "viem": "^2.34.0",
55
+ "vitest": "^3.0.9"
56
+ }
57
+ }