@atxp/base 0.2.14
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/baseAppAccount.d.ts +26 -0
- package/dist/baseAppAccount.d.ts.map +1 -0
- package/dist/baseAppAccount.js +107 -0
- package/dist/baseAppAccount.js.map +1 -0
- package/dist/baseAppPaymentMaker.d.ts +16 -0
- package/dist/baseAppPaymentMaker.d.ts.map +1 -0
- package/dist/baseAppPaymentMaker.js +154 -0
- package/dist/baseAppPaymentMaker.js.map +1 -0
- package/dist/baseAppPaymentMaker.test.d.ts +2 -0
- package/dist/baseAppPaymentMaker.test.d.ts.map +1 -0
- package/dist/baseAppPaymentMaker.test.js +95 -0
- package/dist/baseAppPaymentMaker.test.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/smartWalletHelpers.d.ts +13 -0
- package/dist/smartWalletHelpers.d.ts.map +1 -0
- package/dist/smartWalletHelpers.js +41 -0
- package/dist/smartWalletHelpers.js.map +1 -0
- package/dist/storage.d.ts +50 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +61 -0
- package/dist/storage.js.map +1 -0
- package/dist/types.d.ts +35 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Account, PaymentMaker } from '@atxp/client';
|
|
2
|
+
import { SpendPermission } from './types.js';
|
|
3
|
+
import { IStorage } from './storage.js';
|
|
4
|
+
import { type EphemeralSmartWallet } from './smartWalletHelpers.js';
|
|
5
|
+
import { Logger } from '@atxp/common';
|
|
6
|
+
export declare class BaseAppAccount implements Account {
|
|
7
|
+
accountId: string;
|
|
8
|
+
paymentMakers: {
|
|
9
|
+
[key: string]: PaymentMaker;
|
|
10
|
+
};
|
|
11
|
+
private static toStorageKey;
|
|
12
|
+
static initialize(config: {
|
|
13
|
+
walletAddress: string;
|
|
14
|
+
apiKey: string;
|
|
15
|
+
appName: string;
|
|
16
|
+
allowance?: bigint;
|
|
17
|
+
periodInDays?: number;
|
|
18
|
+
storage?: IStorage<string>;
|
|
19
|
+
logger?: Logger;
|
|
20
|
+
}): Promise<BaseAppAccount>;
|
|
21
|
+
private static loadSavedWalletAndPermission;
|
|
22
|
+
private static deploySmartWallet;
|
|
23
|
+
constructor(spendPermission: SpendPermission, ephemeralSmartWallet: EphemeralSmartWallet, logger?: Logger);
|
|
24
|
+
static clearAllStoredData(userWalletAddress: string, storage?: IStorage<string>): void;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=baseAppAccount.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseAppAccount.d.ts","sourceRoot":"","sources":["../src/baseAppAccount.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAM1D,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAA0D,MAAM,cAAc,CAAC;AAChG,OAAO,EAA0B,KAAK,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC5F,OAAO,EAAiB,MAAM,EAAE,MAAM,cAAc,CAAC;AAQrD,qBAAa,cAAe,YAAW,OAAO;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAAA;KAAE,CAAC;IAE/C,OAAO,CAAC,MAAM,CAAC,YAAY;WAId,UAAU,CAAC,MAAM,EAAE;QAC5B,aAAa,EAAE,MAAM,CAAC;QACtB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC3B,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,GACA,OAAO,CAAC,cAAc,CAAC;IAsD1B,OAAO,CAAC,MAAM,CAAC,4BAA4B;mBAkBtB,iBAAiB;gBAsBpC,eAAe,EAAE,eAAe,EAChC,oBAAoB,EAAE,oBAAoB,EAC1C,MAAM,CAAC,EAAE,MAAM;IAajB,MAAM,CAAC,kBAAkB,CAAC,iBAAiB,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI;CAQvF"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { USDC_CONTRACT_ADDRESS_BASE } from '@atxp/client';
|
|
2
|
+
import { BaseAppPaymentMaker } from './baseAppPaymentMaker.js';
|
|
3
|
+
import { generatePrivateKey } from 'viem/accounts';
|
|
4
|
+
import { base } from 'viem/chains';
|
|
5
|
+
import { BrowserStorage, IntermediaryStorage } from './storage.js';
|
|
6
|
+
import { toEphemeralSmartWallet } from './smartWalletHelpers.js';
|
|
7
|
+
import { ConsoleLogger } from '@atxp/common';
|
|
8
|
+
import { createBaseAccountSDK } from "@base-org/account";
|
|
9
|
+
import { requestSpendPermission } from "@base-org/account/spend-permission";
|
|
10
|
+
const DEFAULT_ALLOWANCE = 10n;
|
|
11
|
+
const DEFAULT_PERIOD_IN_DAYS = 7;
|
|
12
|
+
const PAYMASTER_URL = 'https://api.developer.coinbase.com/rpc/v1/base/snPdXqIzOGhRkGNJvEHM5bl9Hm3yRO3m';
|
|
13
|
+
export class BaseAppAccount {
|
|
14
|
+
static toStorageKey(userWalletAddress) {
|
|
15
|
+
return `atxp-base-permission-${userWalletAddress}`;
|
|
16
|
+
}
|
|
17
|
+
static async initialize(config) {
|
|
18
|
+
const logger = config.logger || new ConsoleLogger();
|
|
19
|
+
// Validate smart wallet configuration
|
|
20
|
+
if (!config.apiKey) {
|
|
21
|
+
throw new Error('Smart wallet API key is required. ' +
|
|
22
|
+
'Get your API key from https://portal.cdp.coinbase.com/');
|
|
23
|
+
}
|
|
24
|
+
// Initialize storage
|
|
25
|
+
const baseStorage = config?.storage || new BrowserStorage();
|
|
26
|
+
const storage = new IntermediaryStorage(baseStorage);
|
|
27
|
+
const storageKey = this.toStorageKey(config.walletAddress);
|
|
28
|
+
// Try to load existing permission
|
|
29
|
+
const existingData = this.loadSavedWalletAndPermission(storage, storageKey);
|
|
30
|
+
if (existingData) {
|
|
31
|
+
const ephemeralSmartWallet = await toEphemeralSmartWallet(existingData.privateKey, config.apiKey);
|
|
32
|
+
return new BaseAppAccount(existingData.permission, ephemeralSmartWallet, logger);
|
|
33
|
+
}
|
|
34
|
+
const sdk = createBaseAccountSDK({
|
|
35
|
+
appName: config?.appName,
|
|
36
|
+
appChainIds: [base.id],
|
|
37
|
+
paymasterUrls: {
|
|
38
|
+
[base.id]: PAYMASTER_URL
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
const provider = sdk.getProvider();
|
|
42
|
+
await provider.request({ method: 'wallet_connect' });
|
|
43
|
+
const privateKey = generatePrivateKey();
|
|
44
|
+
const smartWallet = await toEphemeralSmartWallet(privateKey, config.apiKey);
|
|
45
|
+
logger.info(`Generated ephemeral wallet: ${smartWallet.address}`);
|
|
46
|
+
await this.deploySmartWallet(smartWallet);
|
|
47
|
+
logger.info(`Deployed smart wallet: ${smartWallet.address}`);
|
|
48
|
+
const permission = await requestSpendPermission({
|
|
49
|
+
account: config.walletAddress,
|
|
50
|
+
spender: smartWallet.address,
|
|
51
|
+
token: USDC_CONTRACT_ADDRESS_BASE,
|
|
52
|
+
chainId: base.id,
|
|
53
|
+
allowance: config?.allowance ?? DEFAULT_ALLOWANCE,
|
|
54
|
+
periodInDays: config?.periodInDays ?? DEFAULT_PERIOD_IN_DAYS,
|
|
55
|
+
provider,
|
|
56
|
+
});
|
|
57
|
+
// Save wallet and permission
|
|
58
|
+
storage.set(storageKey, { privateKey, permission });
|
|
59
|
+
return new BaseAppAccount(permission, smartWallet, logger);
|
|
60
|
+
}
|
|
61
|
+
static loadSavedWalletAndPermission(permissionStorage, storageKey) {
|
|
62
|
+
const storedData = permissionStorage.get(storageKey);
|
|
63
|
+
if (!storedData)
|
|
64
|
+
return null;
|
|
65
|
+
// Check if permission is not expired
|
|
66
|
+
const now = Math.floor(Date.now() / 1000);
|
|
67
|
+
const permissionEnd = parseInt(storedData.permission.permission.end.toString());
|
|
68
|
+
if (permissionEnd <= now) {
|
|
69
|
+
permissionStorage.delete(storageKey);
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
return storedData;
|
|
73
|
+
}
|
|
74
|
+
static async deploySmartWallet(smartWallet) {
|
|
75
|
+
const deployTx = await smartWallet.client.sendUserOperation({
|
|
76
|
+
calls: [{
|
|
77
|
+
to: smartWallet.address,
|
|
78
|
+
value: 0n,
|
|
79
|
+
data: '0x'
|
|
80
|
+
}],
|
|
81
|
+
paymaster: true
|
|
82
|
+
});
|
|
83
|
+
const receipt = await smartWallet.client.waitForUserOperationReceipt({
|
|
84
|
+
hash: deployTx
|
|
85
|
+
});
|
|
86
|
+
if (!receipt.success) {
|
|
87
|
+
throw new Error(`Smart wallet deployment failed. Receipt: ${JSON.stringify(receipt)}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
constructor(spendPermission, ephemeralSmartWallet, logger) {
|
|
91
|
+
if (!ephemeralSmartWallet) {
|
|
92
|
+
throw new Error('Wallet client is required');
|
|
93
|
+
}
|
|
94
|
+
this.accountId = ephemeralSmartWallet.address;
|
|
95
|
+
this.paymentMakers = {
|
|
96
|
+
'base': new BaseAppPaymentMaker(spendPermission, ephemeralSmartWallet, logger),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
static clearAllStoredData(userWalletAddress, storage) {
|
|
100
|
+
if (typeof window === 'undefined' && !storage) {
|
|
101
|
+
throw new Error('clearAllStoredData requires a storage to be provided outside of browser environments');
|
|
102
|
+
}
|
|
103
|
+
storage = storage || new BrowserStorage();
|
|
104
|
+
storage.delete(this.toStorageKey(userWalletAddress));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=baseAppAccount.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseAppAccount.js","sourceRoot":"","sources":["../src/baseAppAccount.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type PaymentMaker } from '@atxp/client';
|
|
2
|
+
import { Logger, Currency } from '@atxp/common';
|
|
3
|
+
import { SpendPermission } from './types.js';
|
|
4
|
+
import { type EphemeralSmartWallet } from './smartWalletHelpers.js';
|
|
5
|
+
export declare class BaseAppPaymentMaker implements PaymentMaker {
|
|
6
|
+
private logger;
|
|
7
|
+
private spendPermission;
|
|
8
|
+
private smartWallet;
|
|
9
|
+
constructor(spendPermission: SpendPermission, smartWallet: EphemeralSmartWallet, logger?: Logger);
|
|
10
|
+
generateJWT({ paymentRequestId, codeChallenge }: {
|
|
11
|
+
paymentRequestId: string;
|
|
12
|
+
codeChallenge: string;
|
|
13
|
+
}): Promise<string>;
|
|
14
|
+
makePayment(amount: BigNumber, currency: Currency, receiver: string, memo: string): Promise<string>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=baseAppPaymentMaker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseAppPaymentMaker.d.ts","sourceRoot":"","sources":["../src/baseAppPaymentMaker.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAC7E,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAiB,MAAM,cAAc,CAAC;AAE/D,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAsDpE,qBAAa,mBAAoB,YAAW,YAAY;IACtD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,WAAW,CAAuB;gBAGxC,eAAe,EAAE,eAAe,EAChC,WAAW,EAAE,oBAAoB,EACjC,MAAM,CAAC,EAAE,MAAM;IAaX,WAAW,CAAC,EAAC,gBAAgB,EAAE,aAAa,EAAC,EAAE;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAsDlH,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CA2D1G"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { USDC_CONTRACT_ADDRESS_BASE } from '@atxp/client';
|
|
2
|
+
import { ConsoleLogger } from '@atxp/common';
|
|
3
|
+
import { encodeFunctionData } from 'viem';
|
|
4
|
+
import { prepareSpendCallData } from '@base-org/account/spend-permission';
|
|
5
|
+
// Helper function to convert to base64url that works in both Node.js and browsers
|
|
6
|
+
function toBase64Url(data) {
|
|
7
|
+
// Convert string to base64
|
|
8
|
+
const base64 = typeof Buffer !== 'undefined'
|
|
9
|
+
? Buffer.from(data).toString('base64')
|
|
10
|
+
: btoa(data);
|
|
11
|
+
// Convert base64 to base64url
|
|
12
|
+
return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
|
|
13
|
+
}
|
|
14
|
+
const USDC_DECIMALS = 6;
|
|
15
|
+
// Minimal ERC20 ABI for transfer function
|
|
16
|
+
const ERC20_ABI = [
|
|
17
|
+
{
|
|
18
|
+
inputs: [
|
|
19
|
+
{ name: 'to', type: 'address' },
|
|
20
|
+
{ name: 'amount', type: 'uint256' }
|
|
21
|
+
],
|
|
22
|
+
name: 'transfer',
|
|
23
|
+
outputs: [{ name: '', type: 'bool' }],
|
|
24
|
+
stateMutability: 'nonpayable',
|
|
25
|
+
type: 'function'
|
|
26
|
+
}
|
|
27
|
+
];
|
|
28
|
+
async function waitForTransactionConfirmations(smartWallet, txHash, confirmations, logger) {
|
|
29
|
+
try {
|
|
30
|
+
const publicClient = smartWallet.client.account?.client;
|
|
31
|
+
if (publicClient && 'waitForTransactionReceipt' in publicClient) {
|
|
32
|
+
logger.info(`Waiting for ${confirmations} confirmations...`);
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
34
|
+
await publicClient.waitForTransactionReceipt({
|
|
35
|
+
hash: txHash,
|
|
36
|
+
confirmations: confirmations
|
|
37
|
+
});
|
|
38
|
+
logger.info(`Transaction confirmed with ${confirmations} confirmations`);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
logger.warn('Unable to wait for confirmations: client does not support waitForTransactionReceipt');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
logger.warn(`Could not wait for additional confirmations: ${error}`);
|
|
46
|
+
// Continue anyway - the transaction is already mined
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export class BaseAppPaymentMaker {
|
|
50
|
+
constructor(spendPermission, smartWallet, logger) {
|
|
51
|
+
if (!spendPermission) {
|
|
52
|
+
throw new Error('Spend permission is required');
|
|
53
|
+
}
|
|
54
|
+
if (!smartWallet) {
|
|
55
|
+
throw new Error('Smart wallet is required');
|
|
56
|
+
}
|
|
57
|
+
this.logger = logger ?? new ConsoleLogger();
|
|
58
|
+
this.spendPermission = spendPermission;
|
|
59
|
+
this.smartWallet = smartWallet;
|
|
60
|
+
}
|
|
61
|
+
async generateJWT({ paymentRequestId, codeChallenge }) {
|
|
62
|
+
// Generate EIP-1271 auth data for smart wallet authentication
|
|
63
|
+
const timestamp = Math.floor(Date.now() / 1000);
|
|
64
|
+
const nonce = Math.random().toString(36).substring(2, 15); // Generate random nonce
|
|
65
|
+
// Construct the message in the required format
|
|
66
|
+
const messageParts = [
|
|
67
|
+
`PayMCP Authorization Request`,
|
|
68
|
+
``,
|
|
69
|
+
`Wallet: ${this.smartWallet.account.address}`,
|
|
70
|
+
`Timestamp: ${timestamp}`,
|
|
71
|
+
`Nonce: ${nonce}`
|
|
72
|
+
];
|
|
73
|
+
if (codeChallenge) {
|
|
74
|
+
messageParts.push(`Code Challenge: ${codeChallenge}`);
|
|
75
|
+
}
|
|
76
|
+
if (paymentRequestId) {
|
|
77
|
+
messageParts.push(`Payment Request ID: ${paymentRequestId}`);
|
|
78
|
+
}
|
|
79
|
+
messageParts.push('', '', 'Sign this message to prove you control this wallet.');
|
|
80
|
+
const message = messageParts.join('\n');
|
|
81
|
+
// Sign the message - this will return an ABI-encoded signature from the smart wallet
|
|
82
|
+
const signature = await this.smartWallet.account.signMessage({
|
|
83
|
+
message: message
|
|
84
|
+
});
|
|
85
|
+
// Create EIP-1271 auth data
|
|
86
|
+
const authData = {
|
|
87
|
+
type: 'EIP1271_AUTH',
|
|
88
|
+
walletAddress: this.smartWallet.account.address,
|
|
89
|
+
message: message,
|
|
90
|
+
signature: signature,
|
|
91
|
+
timestamp: timestamp,
|
|
92
|
+
nonce: nonce,
|
|
93
|
+
...(codeChallenge && { code_challenge: codeChallenge }),
|
|
94
|
+
...(paymentRequestId && { payment_request_id: paymentRequestId })
|
|
95
|
+
};
|
|
96
|
+
// Encode as base64url
|
|
97
|
+
const encodedAuth = toBase64Url(JSON.stringify(authData));
|
|
98
|
+
this.logger.info(`codeChallenge: ${codeChallenge}`);
|
|
99
|
+
this.logger.info(`paymentRequestId: ${paymentRequestId}`);
|
|
100
|
+
this.logger.info(`walletAddress: ${this.smartWallet.account.address}`);
|
|
101
|
+
this.logger.info(`Generated EIP-1271 auth data: ${encodedAuth}`);
|
|
102
|
+
return encodedAuth;
|
|
103
|
+
}
|
|
104
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
105
|
+
async makePayment(amount, currency, receiver, memo) {
|
|
106
|
+
if (currency !== 'USDC') {
|
|
107
|
+
throw new Error('Only usdc currency is supported; received ' + currency);
|
|
108
|
+
}
|
|
109
|
+
this.logger.info(`Making spendPermission payment of ${amount} ${currency} to ${receiver} on Base`);
|
|
110
|
+
// Convert amount to USDC units (6 decimals) as BigInt for spendPermission
|
|
111
|
+
const amountInUSDCUnits = BigInt(amount.multipliedBy(10 ** USDC_DECIMALS).toFixed(0));
|
|
112
|
+
const spendCalls = await prepareSpendCallData(this.spendPermission, amountInUSDCUnits);
|
|
113
|
+
// Add a second call to transfer USDC from the smart wallet to the receiver
|
|
114
|
+
const transferCall = {
|
|
115
|
+
to: USDC_CONTRACT_ADDRESS_BASE,
|
|
116
|
+
data: encodeFunctionData({
|
|
117
|
+
abi: ERC20_ABI,
|
|
118
|
+
functionName: "transfer",
|
|
119
|
+
args: [receiver, amountInUSDCUnits],
|
|
120
|
+
}),
|
|
121
|
+
value: '0x0'
|
|
122
|
+
};
|
|
123
|
+
// Combine spend permission calls with the transfer call
|
|
124
|
+
const allCalls = [...spendCalls, transferCall];
|
|
125
|
+
this.logger.info(`Executing ${allCalls.length} calls (${spendCalls.length} spend permission + 1 transfer)`);
|
|
126
|
+
const hash = await this.smartWallet.client.sendUserOperation({
|
|
127
|
+
account: this.smartWallet.account,
|
|
128
|
+
calls: allCalls.map(call => {
|
|
129
|
+
return {
|
|
130
|
+
to: call.to,
|
|
131
|
+
data: call.data,
|
|
132
|
+
value: BigInt(call.value || '0x0')
|
|
133
|
+
};
|
|
134
|
+
})
|
|
135
|
+
});
|
|
136
|
+
const receipt = await this.smartWallet.client.waitForUserOperationReceipt({ hash });
|
|
137
|
+
if (!receipt) {
|
|
138
|
+
throw new Error('User operation failed');
|
|
139
|
+
}
|
|
140
|
+
// The receipt contains the actual transaction hash that was mined on chain
|
|
141
|
+
const txHash = receipt.receipt.transactionHash;
|
|
142
|
+
if (!txHash) {
|
|
143
|
+
throw new Error('User operation was executed but no transaction hash was returned. This should not happen.');
|
|
144
|
+
}
|
|
145
|
+
this.logger.info(`Spend permission executed successfully. UserOp: ${receipt.userOpHash}, TxHash: ${txHash}`);
|
|
146
|
+
// Wait for additional confirmations to ensure the transaction is well-propagated
|
|
147
|
+
// This helps avoid the "Transaction receipt could not be found" error
|
|
148
|
+
await waitForTransactionConfirmations(this.smartWallet, txHash, 3, this.logger);
|
|
149
|
+
// Return the actual transaction hash, not the user operation hash
|
|
150
|
+
// The payment verification system needs the on-chain transaction hash
|
|
151
|
+
return txHash;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=baseAppPaymentMaker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseAppPaymentMaker.js","sourceRoot":"","sources":["../src/baseAppPaymentMaker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseAppPaymentMaker.test.d.ts","sourceRoot":"","sources":["../src/baseAppPaymentMaker.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
|
|
3
|
+
import { BaseAppPaymentMaker } from './baseAppPaymentMaker.js';
|
|
4
|
+
describe('basePaymentMaker.generateJWT', () => {
|
|
5
|
+
it('should generate EIP-1271 auth data with default payload', async () => {
|
|
6
|
+
const privateKey = generatePrivateKey();
|
|
7
|
+
const account = privateKeyToAccount(privateKey);
|
|
8
|
+
// Create mock SpendPermission
|
|
9
|
+
const mockSpendPermission = {
|
|
10
|
+
signature: '0xmocksignature',
|
|
11
|
+
permission: {
|
|
12
|
+
account: account.address,
|
|
13
|
+
spender: '0xspender',
|
|
14
|
+
token: '0xtoken',
|
|
15
|
+
allowance: '1000000',
|
|
16
|
+
period: 86400,
|
|
17
|
+
start: Math.floor(Date.now() / 1000),
|
|
18
|
+
end: Math.floor(Date.now() / 1000) + 86400,
|
|
19
|
+
salt: '1',
|
|
20
|
+
extraData: '0x'
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
// Create mock EphemeralSmartWallet
|
|
24
|
+
const mockSmartWallet = {
|
|
25
|
+
address: account.address,
|
|
26
|
+
account: {
|
|
27
|
+
address: account.address,
|
|
28
|
+
signMessage: async (_message) => '0xmocksignature'
|
|
29
|
+
},
|
|
30
|
+
signer: {
|
|
31
|
+
address: account.address,
|
|
32
|
+
signMessage: async (_message) => '0xmocksignature',
|
|
33
|
+
signTypedData: async (_params) => '0xmocksignature',
|
|
34
|
+
signTransaction: async (_tx) => '0xmocksignature',
|
|
35
|
+
getAddress: async () => account.address
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const paymentMaker = new BaseAppPaymentMaker(mockSpendPermission, mockSmartWallet);
|
|
39
|
+
const authData = await paymentMaker.generateJWT({ paymentRequestId: '', codeChallenge: 'testCodeChallenge' });
|
|
40
|
+
// Should return base64-encoded EIP-1271 auth data
|
|
41
|
+
expect(authData).toBeDefined();
|
|
42
|
+
expect(typeof authData).toBe('string');
|
|
43
|
+
// Decode and verify the auth data
|
|
44
|
+
const decoded = JSON.parse(Buffer.from(authData, 'base64').toString('utf-8'));
|
|
45
|
+
expect(decoded.type).toBe('EIP1271_AUTH');
|
|
46
|
+
expect(decoded.walletAddress).toBe(account.address);
|
|
47
|
+
expect(decoded.message).toContain('PayMCP Authorization Request');
|
|
48
|
+
expect(decoded.signature).toBeDefined();
|
|
49
|
+
expect(decoded.timestamp).toBeDefined();
|
|
50
|
+
expect(decoded.nonce).toBeDefined();
|
|
51
|
+
expect(decoded.code_challenge).toBe('testCodeChallenge');
|
|
52
|
+
});
|
|
53
|
+
it('should include payment request id if provided', async () => {
|
|
54
|
+
const privateKey = generatePrivateKey();
|
|
55
|
+
const account = privateKeyToAccount(privateKey);
|
|
56
|
+
// Create mock SpendPermission
|
|
57
|
+
const mockSpendPermission = {
|
|
58
|
+
signature: '0xmocksignature',
|
|
59
|
+
permission: {
|
|
60
|
+
account: account.address,
|
|
61
|
+
spender: '0xspender',
|
|
62
|
+
token: '0xtoken',
|
|
63
|
+
allowance: '1000000',
|
|
64
|
+
period: 86400,
|
|
65
|
+
start: Math.floor(Date.now() / 1000),
|
|
66
|
+
end: Math.floor(Date.now() / 1000) + 86400,
|
|
67
|
+
salt: '1',
|
|
68
|
+
extraData: '0x'
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
// Create mock EphemeralSmartWallet
|
|
72
|
+
const mockSmartWallet = {
|
|
73
|
+
address: account.address,
|
|
74
|
+
account: {
|
|
75
|
+
address: account.address,
|
|
76
|
+
signMessage: async (_message) => '0xmocksignature'
|
|
77
|
+
},
|
|
78
|
+
signer: {
|
|
79
|
+
address: account.address,
|
|
80
|
+
signMessage: async (_message) => '0xmocksignature',
|
|
81
|
+
signTypedData: async (_params) => '0xmocksignature',
|
|
82
|
+
signTransaction: async (_tx) => '0xmocksignature',
|
|
83
|
+
getAddress: async () => account.address
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
const paymentMaker = new BaseAppPaymentMaker(mockSpendPermission, mockSmartWallet);
|
|
87
|
+
const paymentRequestId = 'id1';
|
|
88
|
+
const authData = await paymentMaker.generateJWT({ paymentRequestId, codeChallenge: '' });
|
|
89
|
+
// Decode and verify the auth data includes payment request ID
|
|
90
|
+
const decoded = JSON.parse(Buffer.from(authData, 'base64').toString('utf-8'));
|
|
91
|
+
expect(decoded.payment_request_id).toEqual(paymentRequestId);
|
|
92
|
+
expect(decoded.message).toContain(`Payment Request ID: ${paymentRequestId}`);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
//# sourceMappingURL=baseAppPaymentMaker.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseAppPaymentMaker.test.js","sourceRoot":"","sources":["../src/baseAppPaymentMaker.test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { BaseAppAccount } from './baseAppAccount.js';
|
|
2
|
+
export { BaseAppPaymentMaker } from './baseAppPaymentMaker.js';
|
|
3
|
+
export type { SpendPermission } from './types.js';
|
|
4
|
+
export { type IStorage, type Intermediary as StoredPermissionData, IntermediaryStorage as PermissionStorage, BrowserStorage, MemoryStorage } from './storage.js';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,YAAY,IAAI,oBAAoB,EACzC,mBAAmB,IAAI,iBAAiB,EACxC,cAAc,EACd,aAAa,EACd,MAAM,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,EAGL,mBAAmB,IAAI,iBAAiB,EACxC,cAAc,EACd,aAAa,EACd,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Account, type Address, type Hex } from 'viem';
|
|
2
|
+
import { type BundlerClient, type SmartAccount } from 'viem/account-abstraction';
|
|
3
|
+
export interface EphemeralSmartWallet {
|
|
4
|
+
address: Address;
|
|
5
|
+
client: BundlerClient;
|
|
6
|
+
account: SmartAccount;
|
|
7
|
+
signer: Account;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Creates an ephemeral smart wallet with paymaster support
|
|
11
|
+
*/
|
|
12
|
+
export declare function toEphemeralSmartWallet(privateKey: Hex, apiKey: string): Promise<EphemeralSmartWallet>;
|
|
13
|
+
//# sourceMappingURL=smartWalletHelpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smartWalletHelpers.d.ts","sourceRoot":"","sources":["../src/smartWalletHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,OAAO,EACZ,KAAK,OAAO,EACZ,KAAK,GAAG,EACT,MAAM,MAAM,CAAC;AAGd,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,0BAA0B,CAAC;AAMlC,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,GAAG,EACf,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,oBAAoB,CAAC,CAiC/B"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { http, createPublicClient, } from 'viem';
|
|
2
|
+
import { base } from 'viem/chains';
|
|
3
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
4
|
+
import { toCoinbaseSmartAccount, createBundlerClient } from 'viem/account-abstraction';
|
|
5
|
+
// Coinbase CDP Paymaster and Bundler endpoints
|
|
6
|
+
const COINBASE_BUNDLER_URL = 'https://api.developer.coinbase.com/rpc/v1/base';
|
|
7
|
+
const COINBASE_PAYMASTER_URL = 'https://api.developer.coinbase.com/rpc/v1/base';
|
|
8
|
+
/**
|
|
9
|
+
* Creates an ephemeral smart wallet with paymaster support
|
|
10
|
+
*/
|
|
11
|
+
export async function toEphemeralSmartWallet(privateKey, apiKey) {
|
|
12
|
+
const signer = privateKeyToAccount(privateKey);
|
|
13
|
+
const publicClient = createPublicClient({
|
|
14
|
+
chain: base,
|
|
15
|
+
transport: http(`${COINBASE_BUNDLER_URL}/${apiKey}`)
|
|
16
|
+
});
|
|
17
|
+
// Create the Coinbase smart wallet
|
|
18
|
+
const account = await toCoinbaseSmartAccount({
|
|
19
|
+
client: publicClient,
|
|
20
|
+
owners: [signer],
|
|
21
|
+
version: '1'
|
|
22
|
+
});
|
|
23
|
+
// Create bundler client with paymaster support
|
|
24
|
+
const bundlerClient = createBundlerClient({
|
|
25
|
+
account,
|
|
26
|
+
client: publicClient,
|
|
27
|
+
transport: http(`${COINBASE_BUNDLER_URL}/${apiKey}`),
|
|
28
|
+
chain: base,
|
|
29
|
+
paymaster: true, // Enable paymaster sponsorship
|
|
30
|
+
paymasterContext: {
|
|
31
|
+
transport: http(`${COINBASE_PAYMASTER_URL}/${apiKey}`)
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
return {
|
|
35
|
+
address: account.address,
|
|
36
|
+
client: bundlerClient,
|
|
37
|
+
account,
|
|
38
|
+
signer,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=smartWalletHelpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smartWalletHelpers.js","sourceRoot":"","sources":["../src/smartWalletHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,kBAAkB,GAInB,MAAM,MAAM,CAAC;AACd,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EAGpB,MAAM,0BAA0B,CAAC;AAElC,+CAA+C;AAC/C,MAAM,oBAAoB,GAAG,gDAAgD,CAAC;AAC9E,MAAM,sBAAsB,GAAG,gDAAgD,CAAC;AAShF;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,UAAe,EACf,MAAc;IAEd,MAAM,MAAM,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAE/C,MAAM,YAAY,GAAG,kBAAkB,CAAC;QACtC,KAAK,EAAE,IAAI;QACX,SAAS,EAAE,IAAI,CAAC,GAAG,oBAAoB,IAAI,MAAM,EAAE,CAAC;KACrD,CAAC,CAAC;IAEH,mCAAmC;IACnC,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC;QAC3C,MAAM,EAAE,YAAY;QACpB,MAAM,EAAE,CAAC,MAAM,CAAC;QAChB,OAAO,EAAE,GAAG;KACb,CAAC,CAAC;IAEH,+CAA+C;IAC/C,MAAM,aAAa,GAAG,mBAAmB,CAAC;QACxC,OAAO;QACP,MAAM,EAAE,YAAY;QACpB,SAAS,EAAE,IAAI,CAAC,GAAG,oBAAoB,IAAI,MAAM,EAAE,CAAC;QACpD,KAAK,EAAE,IAAI;QACX,SAAS,EAAE,IAAI,EAAE,+BAA+B;QAChD,gBAAgB,EAAE;YAChB,SAAS,EAAE,IAAI,CAAC,GAAG,sBAAsB,IAAI,MAAM,EAAE,CAAC;SACvD;KACF,CAAC,CAAC;IAEH,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,MAAM,EAAE,aAAa;QACrB,OAAO;QACP,MAAM;KACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { SpendPermission } from './types.js';
|
|
2
|
+
import { Hex } from '@atxp/client';
|
|
3
|
+
/**
|
|
4
|
+
* Stored permission data structure
|
|
5
|
+
*/
|
|
6
|
+
export interface Intermediary {
|
|
7
|
+
/** Ephemeral wallet private key */
|
|
8
|
+
privateKey: Hex;
|
|
9
|
+
/** Spend permission from Base */
|
|
10
|
+
permission: SpendPermission;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Storage interface for abstracting storage mechanisms
|
|
14
|
+
* This allows for easy mocking in tests and potential future
|
|
15
|
+
* support for different storage backends (e.g., React Native AsyncStorage)
|
|
16
|
+
*/
|
|
17
|
+
export interface IStorage<T = string> {
|
|
18
|
+
get(key: string): T | null;
|
|
19
|
+
set(key: string, value: T): void;
|
|
20
|
+
delete(key: string): void;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Type-safe storage wrapper for permission data
|
|
24
|
+
*/
|
|
25
|
+
export declare class IntermediaryStorage {
|
|
26
|
+
private storage;
|
|
27
|
+
constructor(storage: IStorage<string>);
|
|
28
|
+
get(key: string): Intermediary | null;
|
|
29
|
+
set(key: string, data: Intermediary): void;
|
|
30
|
+
delete(key: string): void;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Browser localStorage implementation
|
|
34
|
+
*/
|
|
35
|
+
export declare class BrowserStorage implements IStorage<string> {
|
|
36
|
+
get(key: string): string | null;
|
|
37
|
+
set(key: string, value: string): void;
|
|
38
|
+
delete(key: string): void;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* In-memory storage implementation for testing
|
|
42
|
+
*/
|
|
43
|
+
export declare class MemoryStorage implements IStorage<string> {
|
|
44
|
+
private store;
|
|
45
|
+
get(key: string): string | null;
|
|
46
|
+
set(key: string, value: string): void;
|
|
47
|
+
delete(key: string): void;
|
|
48
|
+
clear(): void;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,mCAAmC;IACnC,UAAU,EAAE,GAAG,CAAC;IAChB,iCAAiC;IACjC,UAAU,EAAE,eAAe,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC,GAAG,MAAM;IAClC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC;IAC3B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IACjC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;GAEG;AACH,qBAAa,mBAAmB;IAClB,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC;IAE7C,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAYrC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI;IAI1C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAG1B;AAED;;GAEG;AACH,qBAAa,cAAe,YAAW,QAAQ,CAAC,MAAM,CAAC;IACrD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAI/B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAIrC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAG1B;AAED;;GAEG;AACH,qBAAa,aAAc,YAAW,QAAQ,CAAC,MAAM,CAAC;IACpD,OAAO,CAAC,KAAK,CAAkC;IAE/C,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAI/B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAIrC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIzB,KAAK,IAAI,IAAI;CAGd"}
|
package/dist/storage.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-safe storage wrapper for permission data
|
|
3
|
+
*/
|
|
4
|
+
export class IntermediaryStorage {
|
|
5
|
+
constructor(storage) {
|
|
6
|
+
this.storage = storage;
|
|
7
|
+
}
|
|
8
|
+
get(key) {
|
|
9
|
+
const data = this.storage.get(key);
|
|
10
|
+
if (!data)
|
|
11
|
+
return null;
|
|
12
|
+
try {
|
|
13
|
+
const parsed = JSON.parse(data);
|
|
14
|
+
return parsed;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
set(key, data) {
|
|
21
|
+
this.storage.set(key, JSON.stringify(data));
|
|
22
|
+
}
|
|
23
|
+
delete(key) {
|
|
24
|
+
this.storage.delete(key);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Browser localStorage implementation
|
|
29
|
+
*/
|
|
30
|
+
export class BrowserStorage {
|
|
31
|
+
get(key) {
|
|
32
|
+
return localStorage.getItem(key);
|
|
33
|
+
}
|
|
34
|
+
set(key, value) {
|
|
35
|
+
localStorage.setItem(key, value);
|
|
36
|
+
}
|
|
37
|
+
delete(key) {
|
|
38
|
+
localStorage.removeItem(key);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* In-memory storage implementation for testing
|
|
43
|
+
*/
|
|
44
|
+
export class MemoryStorage {
|
|
45
|
+
constructor() {
|
|
46
|
+
this.store = new Map();
|
|
47
|
+
}
|
|
48
|
+
get(key) {
|
|
49
|
+
return this.store.get(key) || null;
|
|
50
|
+
}
|
|
51
|
+
set(key, value) {
|
|
52
|
+
this.store.set(key, value);
|
|
53
|
+
}
|
|
54
|
+
delete(key) {
|
|
55
|
+
this.store.delete(key);
|
|
56
|
+
}
|
|
57
|
+
clear() {
|
|
58
|
+
this.store.clear();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAwBA;;GAEG;AACH,MAAM,OAAO,mBAAmB;IAC9B,YAAoB,OAAyB;QAAzB,YAAO,GAAP,OAAO,CAAkB;IAAG,CAAC;IAEjD,GAAG,CAAC,GAAW;QACb,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QAEvB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAChC,OAAO,MAAsB,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,GAAG,CAAC,GAAW,EAAE,IAAkB;QACjC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,CAAC,GAAW;QAChB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,cAAc;IACzB,GAAG,CAAC,GAAW;QACb,OAAO,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,GAAG,CAAC,GAAW,EAAE,KAAa;QAC5B,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACnC,CAAC;IAED,MAAM,CAAC,GAAW;QAChB,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,aAAa;IAA1B;QACU,UAAK,GAAwB,IAAI,GAAG,EAAE,CAAC;IAiBjD,CAAC;IAfC,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;IACrC,CAAC;IAED,GAAG,CAAC,GAAW,EAAE,KAAa;QAC5B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED,MAAM,CAAC,GAAW;QAChB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;CACF"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a spending permission with limits
|
|
3
|
+
*/
|
|
4
|
+
export type SpendPermission = {
|
|
5
|
+
/** UTC timestamp for when the permission was granted */
|
|
6
|
+
createdAt?: number;
|
|
7
|
+
/** Hash of the permission in hex format */
|
|
8
|
+
permissionHash?: string;
|
|
9
|
+
/** Cryptographic signature in hex format */
|
|
10
|
+
signature: string;
|
|
11
|
+
/** Chain ID */
|
|
12
|
+
chainId?: number;
|
|
13
|
+
/** The permission details */
|
|
14
|
+
permission: {
|
|
15
|
+
/** Wallet address of the account */
|
|
16
|
+
account: string;
|
|
17
|
+
/** Address of the contract/entity allowed to spend */
|
|
18
|
+
spender: string;
|
|
19
|
+
/** Address of the token being spent */
|
|
20
|
+
token: string;
|
|
21
|
+
/** Maximum amount allowed as base 10 numeric string */
|
|
22
|
+
allowance: string;
|
|
23
|
+
/** Time period in seconds */
|
|
24
|
+
period: number;
|
|
25
|
+
/** Start time in unix seconds */
|
|
26
|
+
start: number;
|
|
27
|
+
/** Expiration time in unix seconds */
|
|
28
|
+
end: number;
|
|
29
|
+
/** Salt as base 10 numeric string */
|
|
30
|
+
salt: string;
|
|
31
|
+
/** Additional data in hex format */
|
|
32
|
+
extraData: string;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6BAA6B;IAC7B,UAAU,EAAE;QACV,oCAAoC;QACpC,OAAO,EAAE,MAAM,CAAC;QAChB,sDAAsD;QACtD,OAAO,EAAE,MAAM,CAAC;QAChB,uCAAuC;QACvC,KAAK,EAAE,MAAM,CAAC;QACd,uDAAuD;QACvD,SAAS,EAAE,MAAM,CAAC;QAClB,6BAA6B;QAC7B,MAAM,EAAE,MAAM,CAAC;QACf,iCAAiC;QACjC,KAAK,EAAE,MAAM,CAAC;QACd,sCAAsC;QACtC,GAAG,EAAE,MAAM,CAAC;QACZ,qCAAqC;QACrC,IAAI,EAAE,MAAM,CAAC;QACb,oCAAoC;QACpC,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,8HAA8H"}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@atxp/base",
|
|
3
|
+
"version": "0.2.14",
|
|
4
|
+
"description": "ATXP for Base Mini Apps",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/atxp-dev/sdk.git",
|
|
9
|
+
"directory": "packages/atxp-base"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"main": "./dist/index.js",
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"typecheck": "tsc --noEmit",
|
|
20
|
+
"lint": "eslint . --ext .ts",
|
|
21
|
+
"lint:fix": "eslint . --ext .ts --fix",
|
|
22
|
+
"test": "vitest run"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@atxp/client": "0.2.14",
|
|
26
|
+
"@atxp/common": "0.2.14",
|
|
27
|
+
"@base-org/account": "^2.0.2",
|
|
28
|
+
"bignumber.js": "^9.3.0",
|
|
29
|
+
"viem": "^2.34.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "^22.13.0",
|
|
33
|
+
"@types/supertest": "^6.0.3",
|
|
34
|
+
"@typescript-eslint/eslint-plugin": "^8.38.0",
|
|
35
|
+
"@typescript-eslint/parser": "^8.38.0",
|
|
36
|
+
"eslint": "^9.32.0",
|
|
37
|
+
"fetch-mock": "^12.5.2",
|
|
38
|
+
"happy-dom": "^15.11.6",
|
|
39
|
+
"jsdom": "^25.0.1",
|
|
40
|
+
"supertest": "^7.1.4",
|
|
41
|
+
"typescript": "^5.7.3",
|
|
42
|
+
"vitest": "^3.0.9"
|
|
43
|
+
}
|
|
44
|
+
}
|