@tonappchain/sdk 0.7.3-rc8 → 0.8.0-aa-alpha-test
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/artifacts/dev/tac/internal/artifacts/contracts/interfaces/ICrossChainLayer.sol/ICrossChainLayer.json +0 -7
- package/dist/artifacts/dev/tac/internal/artifacts/contracts/interfaces/ISettings.sol/ISettings.json +0 -7
- package/dist/artifacts/dev/tac/internal/artifacts/contracts/interfaces/ITokenUtils.sol/ITokenUtils.json +0 -7
- package/dist/artifacts/dev/tac/internal/artifacts/contracts/smart-account/interfaces/ISAFactory.sol/ISAFactory.json +0 -7
- package/dist/artifacts/dev/tac/internal/typechain-types/contracts/interfaces/ICrossChainLayer.d.ts +1 -5
- package/dist/artifacts/dev/tac/internal/typechain-types/contracts/interfaces/ISettings.d.ts +1 -5
- package/dist/artifacts/dev/tac/internal/typechain-types/contracts/interfaces/ITokenUtils.d.ts +1 -5
- package/dist/artifacts/dev/tac/internal/typechain-types/contracts/smart-account/interfaces/ISAFactory.d.ts +1 -5
- package/dist/artifacts/dev/ton/internal/build/Settings.compiled.json +1 -1
- package/dist/artifacts/dev/ton/internal/wrappers/Settings.d.ts +1 -0
- package/dist/artifacts/dev/ton/internal/wrappers/Settings.js +11 -7
- package/dist/artifacts/index.d.ts +5 -3
- package/dist/artifacts/index.js +6 -3
- package/dist/artifacts/mainnet/tac/internal/artifacts/contracts/interfaces/ICrossChainLayer.sol/ICrossChainLayer.json +0 -7
- package/dist/artifacts/mainnet/tac/internal/artifacts/contracts/interfaces/ISettings.sol/ISettings.json +0 -7
- package/dist/artifacts/mainnet/tac/internal/artifacts/contracts/interfaces/ITokenUtils.sol/ITokenUtils.json +0 -7
- package/dist/artifacts/mainnet/tac/internal/artifacts/contracts/smart-account/interfaces/ISAFactory.sol/ISAFactory.json +0 -7
- package/dist/artifacts/mainnet/tac/internal/typechain-types/contracts/interfaces/ICrossChainLayer.d.ts +1 -5
- package/dist/artifacts/mainnet/tac/internal/typechain-types/contracts/interfaces/ISettings.d.ts +1 -5
- package/dist/artifacts/mainnet/tac/internal/typechain-types/contracts/interfaces/ITokenUtils.d.ts +1 -5
- package/dist/artifacts/mainnet/tac/internal/typechain-types/contracts/smart-account/interfaces/ISAFactory.d.ts +1 -5
- package/dist/artifacts/mainnet/ton/internal/build/CrossChainLayer.compiled.json +1 -1
- package/dist/artifacts/mainnet/ton/internal/build/Executor.compiled.json +1 -1
- package/dist/artifacts/mainnet/ton/internal/build/JettonMinter.compiled.json +1 -1
- package/dist/artifacts/mainnet/ton/internal/build/JettonProxy.compiled.json +1 -1
- package/dist/artifacts/mainnet/ton/internal/build/JettonWallet.compiled.json +1 -1
- package/dist/artifacts/mainnet/ton/internal/build/NFTCollection.compiled.json +1 -1
- package/dist/artifacts/mainnet/ton/internal/build/NFTItem.compiled.json +1 -1
- package/dist/artifacts/mainnet/ton/internal/build/NFTProxy.compiled.json +1 -1
- package/dist/artifacts/mainnet/ton/internal/build/Settings.compiled.json +1 -1
- package/dist/artifacts/mainnet/ton/internal/wrappers/CrossChainLayer.d.ts +65 -6
- package/dist/artifacts/mainnet/ton/internal/wrappers/CrossChainLayer.js +169 -18
- package/dist/artifacts/mainnet/ton/internal/wrappers/JettonMinter.d.ts +4 -2
- package/dist/artifacts/mainnet/ton/internal/wrappers/JettonMinter.js +5 -3
- package/dist/artifacts/mainnet/ton/internal/wrappers/JettonProxy.d.ts +9 -0
- package/dist/artifacts/mainnet/ton/internal/wrappers/JettonProxy.js +11 -2
- package/dist/artifacts/mainnet/ton/internal/wrappers/JettonWallet.d.ts +7 -0
- package/dist/artifacts/mainnet/ton/internal/wrappers/JettonWallet.js +9 -2
- package/dist/artifacts/mainnet/ton/internal/wrappers/NFTCollection.d.ts +11 -1
- package/dist/artifacts/mainnet/ton/internal/wrappers/NFTCollection.js +17 -5
- package/dist/artifacts/mainnet/ton/internal/wrappers/NFTItem.d.ts +9 -1
- package/dist/artifacts/mainnet/ton/internal/wrappers/NFTItem.js +15 -5
- package/dist/artifacts/mainnet/ton/internal/wrappers/NFTProxy.d.ts +9 -1
- package/dist/artifacts/mainnet/ton/internal/wrappers/NFTProxy.js +16 -6
- package/dist/artifacts/mainnet/ton/internal/wrappers/Settings.d.ts +2 -0
- package/dist/artifacts/mainnet/ton/internal/wrappers/Settings.js +11 -6
- package/dist/artifacts/mainnet/ton/internal/wrappers/utils/CrossChainLayerPayload.d.ts +10 -0
- package/dist/artifacts/mainnet/ton/internal/wrappers/utils/CrossChainLayerPayload.js +24 -0
- package/dist/artifacts/mainnet/ton/internal/wrappers/utils/MerkleRoots.d.ts +2 -1
- package/dist/artifacts/mainnet/ton/internal/wrappers/utils/MerkleRoots.js +9 -1
- package/dist/artifacts/testnet/tac/internal/artifacts/contracts/interfaces/ICrossChainLayer.sol/ICrossChainLayer.json +0 -7
- package/dist/artifacts/testnet/tac/internal/artifacts/contracts/interfaces/ISettings.sol/ISettings.json +0 -7
- package/dist/artifacts/testnet/tac/internal/artifacts/contracts/interfaces/ITokenUtils.sol/ITokenUtils.json +0 -7
- package/dist/artifacts/testnet/tac/internal/artifacts/contracts/smart-account/interfaces/ISAFactory.sol/ISAFactory.json +0 -7
- package/dist/artifacts/testnet/tac/internal/typechain-types/contracts/interfaces/ICrossChainLayer.d.ts +1 -5
- package/dist/artifacts/testnet/tac/internal/typechain-types/contracts/interfaces/ISettings.d.ts +1 -5
- package/dist/artifacts/testnet/tac/internal/typechain-types/contracts/interfaces/ITokenUtils.d.ts +1 -5
- package/dist/artifacts/testnet/tac/internal/typechain-types/contracts/smart-account/interfaces/ISAFactory.d.ts +1 -5
- package/dist/artifacts/testnet/ton/internal/build/Settings.compiled.json +1 -1
- package/dist/artifacts/testnet/ton/internal/wrappers/Settings.d.ts +1 -0
- package/dist/artifacts/testnet/ton/internal/wrappers/Settings.js +11 -7
- package/dist/src/accountAbstraction/BaseAccountAPI.d.ts +62 -0
- package/dist/src/accountAbstraction/BaseAccountAPI.js +163 -0
- package/dist/src/accountAbstraction/Ed25519.d.ts +47 -0
- package/dist/src/accountAbstraction/Ed25519.js +100 -0
- package/dist/src/accountAbstraction/HttpRpcClient.d.ts +26 -0
- package/dist/src/accountAbstraction/HttpRpcClient.js +45 -0
- package/dist/src/accountAbstraction/PaymasterAPI.d.ts +21 -0
- package/dist/src/accountAbstraction/PaymasterAPI.js +18 -0
- package/dist/src/accountAbstraction/Permit2.d.ts +37 -0
- package/dist/src/accountAbstraction/Permit2.js +41 -0
- package/dist/src/accountAbstraction/PermitFlow.d.ts +43 -0
- package/dist/src/accountAbstraction/PermitFlow.js +80 -0
- package/dist/src/accountAbstraction/TacAccountAPI.d.ts +53 -0
- package/dist/src/accountAbstraction/TacAccountAPI.js +84 -0
- package/dist/src/accountAbstraction/TacAccountSdk.d.ts +101 -0
- package/dist/src/accountAbstraction/TacAccountSdk.js +163 -0
- package/dist/src/accountAbstraction/TacERC20PaymasterAPI.d.ts +59 -0
- package/dist/src/accountAbstraction/TacERC20PaymasterAPI.js +88 -0
- package/dist/src/accountAbstraction/TransactionDetailsForUserOp.d.ts +10 -0
- package/dist/src/accountAbstraction/TransactionDetailsForUserOp.js +2 -0
- package/dist/src/accountAbstraction/abi.d.ts +3 -0
- package/dist/src/accountAbstraction/abi.js +32 -0
- package/dist/src/accountAbstraction/index.d.ts +24 -0
- package/dist/src/accountAbstraction/index.js +44 -0
- package/dist/src/accountAbstraction/internal/entryPointAbi.d.ts +1 -0
- package/dist/src/accountAbstraction/internal/entryPointAbi.js +16 -0
- package/dist/src/accountAbstraction/internal/userOp.d.ts +54 -0
- package/dist/src/accountAbstraction/internal/userOp.js +72 -0
- package/dist/src/accountAbstraction/networks.d.ts +22 -0
- package/dist/src/accountAbstraction/networks.js +19 -0
- package/dist/src/accountAbstraction/signer.d.ts +12 -0
- package/dist/src/accountAbstraction/signer.js +14 -0
- package/dist/src/adapters/RetryableContractOpener.js +5 -2
- package/dist/src/adapters/ToncenterV3Indexer.js +1 -1
- package/dist/src/assets/AssetCache.d.ts +4 -4
- package/dist/src/assets/AssetCache.js +11 -6
- package/dist/src/assets/AssetFactory.js +2 -2
- package/dist/src/errors/index.d.ts +1 -1
- package/dist/src/errors/index.js +2 -1
- package/dist/src/errors/instances.d.ts +1 -0
- package/dist/src/errors/instances.js +3 -1
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +4 -1
- package/dist/src/interfaces/IConfiguration.d.ts +2 -2
- package/dist/src/sdk/Artifacts.d.ts +3 -0
- package/dist/src/sdk/Artifacts.js +17 -0
- package/dist/src/sdk/Configuration.d.ts +4 -4
- package/dist/src/sdk/Configuration.js +3 -3
- package/dist/src/sdk/Consts.d.ts +0 -1
- package/dist/src/sdk/Consts.js +1 -2
- package/dist/src/sdk/LiteSequencerClient.js +2 -1
- package/dist/src/sdk/StartTracking.js +2 -2
- package/dist/src/sdk/TACTransactionManager.js +5 -5
- package/dist/src/sdk/TONTransactionManager.js +23 -21
- package/dist/src/sdk/TacExplorerClient.js +4 -3
- package/dist/src/sdk/TacSdk.js +2 -15
- package/dist/src/sdk/TxFinalizer.js +1 -1
- package/dist/src/sdk/Utils.js +37 -4
- package/dist/src/structs/Struct.d.ts +4 -4
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Settings = exports.SettingsErrors = exports.SettingsOpCodes = void 0;
|
|
4
4
|
exports.settingsConfigToCell = settingsConfigToCell;
|
|
5
|
+
exports.createSettingsSetValueBody = createSettingsSetValueBody;
|
|
5
6
|
const core_1 = require("@ton/core");
|
|
6
7
|
const GasUtils_1 = require("./utils/GasUtils");
|
|
7
8
|
exports.SettingsOpCodes = {
|
|
@@ -29,6 +30,14 @@ function settingsConfigToCell(config) {
|
|
|
29
30
|
.storeDict(config.settings)
|
|
30
31
|
.endCell();
|
|
31
32
|
}
|
|
33
|
+
function createSettingsSetValueBody(params) {
|
|
34
|
+
return (0, core_1.beginCell)()
|
|
35
|
+
.storeUint(exports.SettingsOpCodes.admin_setValue, 32)
|
|
36
|
+
.storeUint(params.queryId ?? 0, 64)
|
|
37
|
+
.storeUint(params.key, 256)
|
|
38
|
+
.storeRef(params.value)
|
|
39
|
+
.endCell();
|
|
40
|
+
}
|
|
32
41
|
class Settings {
|
|
33
42
|
constructor(address, init, configuration) {
|
|
34
43
|
this.address = address;
|
|
@@ -54,12 +63,7 @@ class Settings {
|
|
|
54
63
|
await provider.internal(via, {
|
|
55
64
|
value,
|
|
56
65
|
sendMode: core_1.SendMode.PAY_GAS_SEPARATELY,
|
|
57
|
-
body: (
|
|
58
|
-
.storeUint(exports.SettingsOpCodes.admin_setValue, 32)
|
|
59
|
-
.storeUint(params.queryId ?? 0, 64)
|
|
60
|
-
.storeUint(params.key, 256)
|
|
61
|
-
.storeRef(params.value)
|
|
62
|
-
.endCell(),
|
|
66
|
+
body: createSettingsSetValueBody(params),
|
|
63
67
|
});
|
|
64
68
|
}
|
|
65
69
|
async sendGetValue(provider, via, value, params) {
|
|
@@ -148,6 +152,6 @@ class Settings {
|
|
|
148
152
|
}
|
|
149
153
|
}
|
|
150
154
|
exports.Settings = Settings;
|
|
151
|
-
Settings.storageStats = new GasUtils_1.StorageStats(
|
|
155
|
+
Settings.storageStats = new GasUtils_1.StorageStats(39175n, 118n);
|
|
152
156
|
Settings.minStorageDuration = 10 * 365 * 24 * 3600; // 10 years
|
|
153
157
|
Settings.minStorageStats = new GasUtils_1.StorageStats(29557n, 104n);
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { BigNumberish, Contract, Provider } from 'ethers';
|
|
2
|
+
import { FactoryParams, UserOperation } from './internal/userOp';
|
|
3
|
+
import { PaymasterAPI } from './PaymasterAPI';
|
|
4
|
+
import { TransactionDetailsForUserOp } from './TransactionDetailsForUserOp';
|
|
5
|
+
export interface BaseApiParams {
|
|
6
|
+
provider: Provider;
|
|
7
|
+
entryPointAddress: string;
|
|
8
|
+
accountAddress?: string;
|
|
9
|
+
paymasterAPI?: PaymasterAPI;
|
|
10
|
+
}
|
|
11
|
+
export interface UserOpResult {
|
|
12
|
+
transactionHash: string;
|
|
13
|
+
success: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Base class for ERC-4337 v0.8 account clients. A subclass implements the account-specific
|
|
17
|
+
* bits (initCode, nonce, execute encoding, signing); this class assembles + signs UserOps.
|
|
18
|
+
*/
|
|
19
|
+
export declare abstract class BaseAccountAPI {
|
|
20
|
+
private senderAddress?;
|
|
21
|
+
private isPhantom;
|
|
22
|
+
protected readonly entryPointView: Contract;
|
|
23
|
+
provider: Provider;
|
|
24
|
+
entryPointAddress: string;
|
|
25
|
+
accountAddress?: string;
|
|
26
|
+
paymasterAPI?: PaymasterAPI;
|
|
27
|
+
protected constructor(params: BaseApiParams);
|
|
28
|
+
init(): Promise<this>;
|
|
29
|
+
/** initCode `factory` + `factoryData` when the account is not yet deployed. */
|
|
30
|
+
abstract getFactoryData(): Promise<FactoryParams | null>;
|
|
31
|
+
/** Current account nonce. */
|
|
32
|
+
abstract getNonce(): Promise<bigint>;
|
|
33
|
+
/** Encode the call from EntryPoint through the account to the target contract. */
|
|
34
|
+
abstract encodeExecute(target: string, value: BigNumberish, data: string): Promise<string>;
|
|
35
|
+
/** Sign a userOpHash. */
|
|
36
|
+
abstract signUserOpHash(userOpHash: string): Promise<string>;
|
|
37
|
+
/** Whether the account contract is not yet deployed. */
|
|
38
|
+
checkAccountPhantom(): Promise<boolean>;
|
|
39
|
+
/** Compute the account address before deployment (via EntryPoint.getSenderAddress). */
|
|
40
|
+
getCounterFactualAddress(): Promise<string>;
|
|
41
|
+
/** initCode for the UserOp (factory + factoryData), or null if already deployed. */
|
|
42
|
+
getRequiredFactoryData(): Promise<FactoryParams | null>;
|
|
43
|
+
/** Maximum gas used for verification (creation cost is added on top when phantom). */
|
|
44
|
+
getVerificationGasLimit(): Promise<BigNumberish>;
|
|
45
|
+
/** Return userOpHash for signing — computed on-chain to match EntryPoint exactly. */
|
|
46
|
+
getUserOpHash(op: UserOperation): Promise<string>;
|
|
47
|
+
/** Account address (valid even before deployment). */
|
|
48
|
+
getAccountAddress(): Promise<string>;
|
|
49
|
+
encodeUserOpCallDataAndGasLimit(detailsForUserOp: TransactionDetailsForUserOp): Promise<{
|
|
50
|
+
callData: string;
|
|
51
|
+
callGasLimit: bigint;
|
|
52
|
+
}>;
|
|
53
|
+
estimateCreationGas(factoryParams: FactoryParams | null): Promise<bigint>;
|
|
54
|
+
/**
|
|
55
|
+
* Create an unsigned UserOperation with all fields filled (signature empty).
|
|
56
|
+
*/
|
|
57
|
+
createUnsignedUserOp(info: TransactionDetailsForUserOp): Promise<UserOperation>;
|
|
58
|
+
/** Sign a filled userOp. */
|
|
59
|
+
signUserOp(userOp: UserOperation): Promise<UserOperation>;
|
|
60
|
+
/** Create and sign a UserOperation. */
|
|
61
|
+
createSignedUserOp(info: TransactionDetailsForUserOp): Promise<UserOperation>;
|
|
62
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BaseAccountAPI = void 0;
|
|
4
|
+
const ethers_1 = require("ethers");
|
|
5
|
+
const entryPointAbi_1 = require("./internal/entryPointAbi");
|
|
6
|
+
const userOp_1 = require("./internal/userOp");
|
|
7
|
+
/**
|
|
8
|
+
* Base class for ERC-4337 v0.8 account clients. A subclass implements the account-specific
|
|
9
|
+
* bits (initCode, nonce, execute encoding, signing); this class assembles + signs UserOps.
|
|
10
|
+
*/
|
|
11
|
+
class BaseAccountAPI {
|
|
12
|
+
constructor(params) {
|
|
13
|
+
this.isPhantom = true;
|
|
14
|
+
this.provider = params.provider;
|
|
15
|
+
this.entryPointAddress = params.entryPointAddress;
|
|
16
|
+
this.accountAddress = params.accountAddress;
|
|
17
|
+
this.paymasterAPI = params.paymasterAPI;
|
|
18
|
+
this.entryPointView = new ethers_1.Contract(params.entryPointAddress, entryPointAbi_1.IEntryPointABI, params.provider);
|
|
19
|
+
}
|
|
20
|
+
async init() {
|
|
21
|
+
if ((await this.provider.getCode(this.entryPointAddress)) === '0x') {
|
|
22
|
+
throw new Error(`entryPoint not deployed at ${this.entryPointAddress}`);
|
|
23
|
+
}
|
|
24
|
+
await this.getAccountAddress();
|
|
25
|
+
return this;
|
|
26
|
+
}
|
|
27
|
+
/** Whether the account contract is not yet deployed. */
|
|
28
|
+
async checkAccountPhantom() {
|
|
29
|
+
if (!this.isPhantom) {
|
|
30
|
+
return this.isPhantom;
|
|
31
|
+
}
|
|
32
|
+
const senderAddressCode = await this.provider.getCode(await this.getAccountAddress());
|
|
33
|
+
if (senderAddressCode.length > 2) {
|
|
34
|
+
this.isPhantom = false;
|
|
35
|
+
}
|
|
36
|
+
return this.isPhantom;
|
|
37
|
+
}
|
|
38
|
+
/** Compute the account address before deployment (via EntryPoint.getSenderAddress). */
|
|
39
|
+
async getCounterFactualAddress() {
|
|
40
|
+
const { factory, factoryData } = (await this.getFactoryData()) ?? {};
|
|
41
|
+
if (factory == null) {
|
|
42
|
+
throw new Error('no counterfactual address without a factory');
|
|
43
|
+
}
|
|
44
|
+
const initCode = (0, ethers_1.concat)([factory, (0, userOp_1.toHexBytes)(factoryData)]);
|
|
45
|
+
try {
|
|
46
|
+
await this.entryPointView.getSenderAddress.staticCall(initCode);
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
// getSenderAddress always reverts with SenderAddressResult(sender)
|
|
50
|
+
const err = e;
|
|
51
|
+
if (err.revert?.name === 'SenderAddressResult') {
|
|
52
|
+
return err.revert.args?.[0];
|
|
53
|
+
}
|
|
54
|
+
if (err.data != null) {
|
|
55
|
+
return this.entryPointView.interface.decodeErrorResult('SenderAddressResult', err.data)[0];
|
|
56
|
+
}
|
|
57
|
+
throw e;
|
|
58
|
+
}
|
|
59
|
+
throw new Error('getSenderAddress did not revert as expected');
|
|
60
|
+
}
|
|
61
|
+
/** initCode for the UserOp (factory + factoryData), or null if already deployed. */
|
|
62
|
+
async getRequiredFactoryData() {
|
|
63
|
+
if (await this.checkAccountPhantom()) {
|
|
64
|
+
return await this.getFactoryData();
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
/** Maximum gas used for verification (creation cost is added on top when phantom). */
|
|
69
|
+
async getVerificationGasLimit() {
|
|
70
|
+
return 100000;
|
|
71
|
+
}
|
|
72
|
+
/** Return userOpHash for signing — computed on-chain to match EntryPoint exactly. */
|
|
73
|
+
async getUserOpHash(op) {
|
|
74
|
+
return await this.entryPointView.getUserOpHash.staticCall((0, userOp_1.packUserOp)(op));
|
|
75
|
+
}
|
|
76
|
+
/** Account address (valid even before deployment). */
|
|
77
|
+
async getAccountAddress() {
|
|
78
|
+
if (this.senderAddress == null) {
|
|
79
|
+
this.senderAddress = this.accountAddress ?? (await this.getCounterFactualAddress());
|
|
80
|
+
}
|
|
81
|
+
return this.senderAddress;
|
|
82
|
+
}
|
|
83
|
+
async encodeUserOpCallDataAndGasLimit(detailsForUserOp) {
|
|
84
|
+
const value = detailsForUserOp.value != null && detailsForUserOp.value !== '' ? BigInt(detailsForUserOp.value) : 0n;
|
|
85
|
+
const callData = await this.encodeExecute(detailsForUserOp.target, value, detailsForUserOp.data);
|
|
86
|
+
const callGasLimit = detailsForUserOp.gasLimit != null && detailsForUserOp.gasLimit !== ''
|
|
87
|
+
? BigInt(detailsForUserOp.gasLimit)
|
|
88
|
+
: await this.provider.estimateGas({
|
|
89
|
+
from: this.entryPointAddress,
|
|
90
|
+
to: await this.getAccountAddress(),
|
|
91
|
+
data: callData,
|
|
92
|
+
});
|
|
93
|
+
return { callData, callGasLimit };
|
|
94
|
+
}
|
|
95
|
+
async estimateCreationGas(factoryParams) {
|
|
96
|
+
if (factoryParams == null) {
|
|
97
|
+
return 0n;
|
|
98
|
+
}
|
|
99
|
+
const senderCreator = await this.entryPointView.senderCreator();
|
|
100
|
+
return await this.provider.estimateGas({
|
|
101
|
+
from: senderCreator,
|
|
102
|
+
to: factoryParams.factory,
|
|
103
|
+
data: (0, userOp_1.toHexBytes)(factoryParams.factoryData),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Create an unsigned UserOperation with all fields filled (signature empty).
|
|
108
|
+
*/
|
|
109
|
+
async createUnsignedUserOp(info) {
|
|
110
|
+
const { callData, callGasLimit } = await this.encodeUserOpCallDataAndGasLimit(info);
|
|
111
|
+
const factoryParams = await this.getRequiredFactoryData();
|
|
112
|
+
const initGas = await this.estimateCreationGas(factoryParams);
|
|
113
|
+
const verificationGasLimit = BigInt(await this.getVerificationGasLimit()) + initGas;
|
|
114
|
+
let maxFeePerGas = info.maxFeePerGas;
|
|
115
|
+
let maxPriorityFeePerGas = info.maxPriorityFeePerGas;
|
|
116
|
+
if (maxFeePerGas == null || maxPriorityFeePerGas == null) {
|
|
117
|
+
const feeData = await this.provider.getFeeData();
|
|
118
|
+
maxFeePerGas ?? (maxFeePerGas = feeData.maxFeePerGas ?? undefined);
|
|
119
|
+
maxPriorityFeePerGas ?? (maxPriorityFeePerGas = feeData.maxPriorityFeePerGas ?? undefined);
|
|
120
|
+
}
|
|
121
|
+
if (maxFeePerGas == null || maxPriorityFeePerGas == null) {
|
|
122
|
+
throw new Error('could not resolve gas fees from provider; pass maxFeePerGas/maxPriorityFeePerGas explicitly');
|
|
123
|
+
}
|
|
124
|
+
let partialUserOp = {
|
|
125
|
+
sender: await this.getAccountAddress(),
|
|
126
|
+
nonce: info.nonce ?? (await this.getNonce()),
|
|
127
|
+
factory: factoryParams?.factory,
|
|
128
|
+
factoryData: factoryParams?.factoryData,
|
|
129
|
+
callData,
|
|
130
|
+
callGasLimit,
|
|
131
|
+
verificationGasLimit,
|
|
132
|
+
maxFeePerGas,
|
|
133
|
+
maxPriorityFeePerGas,
|
|
134
|
+
preVerificationGas: 60000,
|
|
135
|
+
signature: '',
|
|
136
|
+
authorizationList: [],
|
|
137
|
+
};
|
|
138
|
+
if (this.paymasterAPI != null) {
|
|
139
|
+
const pmFields = await this.paymasterAPI.getTemporaryPaymasterData();
|
|
140
|
+
if (pmFields != null) {
|
|
141
|
+
partialUserOp = {
|
|
142
|
+
...partialUserOp,
|
|
143
|
+
paymaster: pmFields.paymaster,
|
|
144
|
+
paymasterPostOpGasLimit: pmFields.paymasterPostOpGasLimit,
|
|
145
|
+
paymasterVerificationGasLimit: pmFields.paymasterVerificationGasLimit,
|
|
146
|
+
paymasterData: pmFields.paymasterData,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return partialUserOp;
|
|
151
|
+
}
|
|
152
|
+
/** Sign a filled userOp. */
|
|
153
|
+
async signUserOp(userOp) {
|
|
154
|
+
const userOpHash = await this.getUserOpHash(userOp);
|
|
155
|
+
const signature = await this.signUserOpHash(userOpHash);
|
|
156
|
+
return { ...userOp, signature };
|
|
157
|
+
}
|
|
158
|
+
/** Create and sign a UserOperation. */
|
|
159
|
+
async createSignedUserOp(info) {
|
|
160
|
+
return await this.signUserOp(await this.createUnsignedUserOp(info));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
exports.BaseAccountAPI = BaseAccountAPI;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { BytesLike } from 'ethers';
|
|
2
|
+
/** Raw Ed25519 signature components; both `r` and `s` are 32-byte 0x-hex strings. */
|
|
3
|
+
export interface Ed25519Signature {
|
|
4
|
+
r: string;
|
|
5
|
+
s: string;
|
|
6
|
+
}
|
|
7
|
+
/** Async callback producing an Ed25519 signature over a 32-byte message (0x-hex). */
|
|
8
|
+
export type Ed25519Signer = (message: string) => Promise<Ed25519Signature>;
|
|
9
|
+
/** Pack an Ed25519 signature into the 64-byte format (abi.encode(bytes32[2])). */
|
|
10
|
+
export declare function packRawEd25519Signature(sig: Ed25519Signature): string;
|
|
11
|
+
/** Pack a Permit2-bound userOp signature: `r ‖ s ‖ permitHash` (96 bytes). */
|
|
12
|
+
export declare function packPermitBoundUserOpSignature(sig: Ed25519Signature, permitHash: BytesLike): string;
|
|
13
|
+
/** Pack a Permit2 inner signature (inside paymasterData): `r ‖ s ‖ userOpHash` (96 bytes). */
|
|
14
|
+
export declare function packPermit2InnerSignature(sig: Ed25519Signature, userOpHash: BytesLike): string;
|
|
15
|
+
/** Build the 64-byte binding `userOpHash ‖ permitHash` for the signer to sign. */
|
|
16
|
+
export declare function buildPermitBinding(userOpHash: BytesLike, permitHash: BytesLike): string;
|
|
17
|
+
/** Components a TonConnect wallet returns when it signs a binary payload. */
|
|
18
|
+
export interface TonConnectSignedParts {
|
|
19
|
+
r: string;
|
|
20
|
+
s: string;
|
|
21
|
+
timestamp: number;
|
|
22
|
+
domain: string;
|
|
23
|
+
workchain: number;
|
|
24
|
+
addrHash: string;
|
|
25
|
+
}
|
|
26
|
+
/** Async signer that drives a TonConnect wallet; receives the 64-byte binding. */
|
|
27
|
+
export type TonConnectSigner = (binding: string) => Promise<TonConnectSignedParts>;
|
|
28
|
+
/**
|
|
29
|
+
* Pack `userOp.signature` for the TonConnect-wrapped variant:
|
|
30
|
+
* abi.encode(r, s, timestamp, domain, workchain, addrHash, permitHash)
|
|
31
|
+
*/
|
|
32
|
+
export declare function packTonConnectUserOpSignature(parts: TonConnectSignedParts, permitHash?: BytesLike): string;
|
|
33
|
+
/**
|
|
34
|
+
* Pack the Permit2 inner signature for the TonConnect-wrapped variant:
|
|
35
|
+
* abi.encode(r, s, timestamp, domain, workchain, addrHash, userOpHash)
|
|
36
|
+
*/
|
|
37
|
+
export declare function packTonConnectPermit2InnerSignature(parts: TonConnectSignedParts, userOpHash: BytesLike): string;
|
|
38
|
+
/**
|
|
39
|
+
* Build an {@link Ed25519Signer} from a raw 64-byte secret key + an Ed25519 impl.
|
|
40
|
+
* The SDK bundles no Ed25519 library; pass e.g. `@ton/crypto`'s `sign`:
|
|
41
|
+
*
|
|
42
|
+
* ```ts
|
|
43
|
+
* import { sign } from '@ton/crypto';
|
|
44
|
+
* const signer = ed25519SignerFromSecretKey(secretKey, (m, sk) => sign(Buffer.from(m), Buffer.from(sk)));
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare function ed25519SignerFromSecretKey(secretKey: Uint8Array, ed25519Sign: (message: Uint8Array, secretKey: Uint8Array) => Uint8Array): Ed25519Signer;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Ed25519 signature packers for TAC accounts. The on-chain account
|
|
3
|
+
// (TacBaseAccount._validateUserOp) accepts THREE signature formats discriminated by length:
|
|
4
|
+
//
|
|
5
|
+
// 1. 64 bytes — abi.encode(bytes32[2]) = r||s. Verified directly over userOpHash.
|
|
6
|
+
// 2. 96 bytes — r ++ s ++ permitHash. Verified over `userOpHash || permitHash`.
|
|
7
|
+
// One Ed25519 signature authorises both the UserOp and a Permit2 transfer.
|
|
8
|
+
// 3. else — abi.encode(r, s, ts, domain, wc, addrHash, permitHash) (TonConnect envelope).
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.packRawEd25519Signature = packRawEd25519Signature;
|
|
11
|
+
exports.packPermitBoundUserOpSignature = packPermitBoundUserOpSignature;
|
|
12
|
+
exports.packPermit2InnerSignature = packPermit2InnerSignature;
|
|
13
|
+
exports.buildPermitBinding = buildPermitBinding;
|
|
14
|
+
exports.packTonConnectUserOpSignature = packTonConnectUserOpSignature;
|
|
15
|
+
exports.packTonConnectPermit2InnerSignature = packTonConnectPermit2InnerSignature;
|
|
16
|
+
exports.ed25519SignerFromSecretKey = ed25519SignerFromSecretKey;
|
|
17
|
+
const ethers_1 = require("ethers");
|
|
18
|
+
const abiCoder = ethers_1.AbiCoder.defaultAbiCoder();
|
|
19
|
+
/** Pack an Ed25519 signature into the 64-byte format (abi.encode(bytes32[2])). */
|
|
20
|
+
function packRawEd25519Signature(sig) {
|
|
21
|
+
return abiCoder.encode(['bytes32[2]'], [[(0, ethers_1.zeroPadValue)((0, ethers_1.hexlify)(sig.r), 32), (0, ethers_1.zeroPadValue)((0, ethers_1.hexlify)(sig.s), 32)]]);
|
|
22
|
+
}
|
|
23
|
+
/** Pack a Permit2-bound userOp signature: `r ‖ s ‖ permitHash` (96 bytes). */
|
|
24
|
+
function packPermitBoundUserOpSignature(sig, permitHash) {
|
|
25
|
+
return (0, ethers_1.concat)([(0, ethers_1.zeroPadValue)((0, ethers_1.hexlify)(sig.r), 32), (0, ethers_1.zeroPadValue)((0, ethers_1.hexlify)(sig.s), 32), (0, ethers_1.zeroPadValue)((0, ethers_1.hexlify)(permitHash), 32)]);
|
|
26
|
+
}
|
|
27
|
+
/** Pack a Permit2 inner signature (inside paymasterData): `r ‖ s ‖ userOpHash` (96 bytes). */
|
|
28
|
+
function packPermit2InnerSignature(sig, userOpHash) {
|
|
29
|
+
return (0, ethers_1.concat)([(0, ethers_1.zeroPadValue)((0, ethers_1.hexlify)(sig.r), 32), (0, ethers_1.zeroPadValue)((0, ethers_1.hexlify)(sig.s), 32), (0, ethers_1.zeroPadValue)((0, ethers_1.hexlify)(userOpHash), 32)]);
|
|
30
|
+
}
|
|
31
|
+
/** Build the 64-byte binding `userOpHash ‖ permitHash` for the signer to sign. */
|
|
32
|
+
function buildPermitBinding(userOpHash, permitHash) {
|
|
33
|
+
return (0, ethers_1.concat)([(0, ethers_1.zeroPadValue)((0, ethers_1.hexlify)(userOpHash), 32), (0, ethers_1.zeroPadValue)((0, ethers_1.hexlify)(permitHash), 32)]);
|
|
34
|
+
}
|
|
35
|
+
const ZERO_HASH = '0x' + '00'.repeat(32);
|
|
36
|
+
/**
|
|
37
|
+
* Pack `userOp.signature` for the TonConnect-wrapped variant:
|
|
38
|
+
* abi.encode(r, s, timestamp, domain, workchain, addrHash, permitHash)
|
|
39
|
+
*/
|
|
40
|
+
function packTonConnectUserOpSignature(parts, permitHash = ZERO_HASH) {
|
|
41
|
+
return abiCoder.encode(['bytes32', 'bytes32', 'uint64', 'string', 'int32', 'bytes32', 'bytes32'], [
|
|
42
|
+
(0, ethers_1.zeroPadValue)((0, ethers_1.hexlify)(parts.r), 32),
|
|
43
|
+
(0, ethers_1.zeroPadValue)((0, ethers_1.hexlify)(parts.s), 32),
|
|
44
|
+
parts.timestamp,
|
|
45
|
+
parts.domain,
|
|
46
|
+
parts.workchain,
|
|
47
|
+
(0, ethers_1.zeroPadValue)((0, ethers_1.hexlify)(parts.addrHash), 32),
|
|
48
|
+
(0, ethers_1.zeroPadValue)((0, ethers_1.hexlify)(permitHash), 32),
|
|
49
|
+
]);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Pack the Permit2 inner signature for the TonConnect-wrapped variant:
|
|
53
|
+
* abi.encode(r, s, timestamp, domain, workchain, addrHash, userOpHash)
|
|
54
|
+
*/
|
|
55
|
+
function packTonConnectPermit2InnerSignature(parts, userOpHash) {
|
|
56
|
+
return abiCoder.encode(['bytes32', 'bytes32', 'uint64', 'string', 'int32', 'bytes32', 'bytes32'], [
|
|
57
|
+
(0, ethers_1.zeroPadValue)((0, ethers_1.hexlify)(parts.r), 32),
|
|
58
|
+
(0, ethers_1.zeroPadValue)((0, ethers_1.hexlify)(parts.s), 32),
|
|
59
|
+
parts.timestamp,
|
|
60
|
+
parts.domain,
|
|
61
|
+
parts.workchain,
|
|
62
|
+
(0, ethers_1.zeroPadValue)((0, ethers_1.hexlify)(parts.addrHash), 32),
|
|
63
|
+
(0, ethers_1.zeroPadValue)((0, ethers_1.hexlify)(userOpHash), 32),
|
|
64
|
+
]);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Build an {@link Ed25519Signer} from a raw 64-byte secret key + an Ed25519 impl.
|
|
68
|
+
* The SDK bundles no Ed25519 library; pass e.g. `@ton/crypto`'s `sign`:
|
|
69
|
+
*
|
|
70
|
+
* ```ts
|
|
71
|
+
* import { sign } from '@ton/crypto';
|
|
72
|
+
* const signer = ed25519SignerFromSecretKey(secretKey, (m, sk) => sign(Buffer.from(m), Buffer.from(sk)));
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
function ed25519SignerFromSecretKey(secretKey, ed25519Sign) {
|
|
76
|
+
return async (message) => {
|
|
77
|
+
const msgBytes = hexToBytes(message);
|
|
78
|
+
const sig = ed25519Sign(msgBytes, secretKey);
|
|
79
|
+
if (sig.length !== 64) {
|
|
80
|
+
throw new Error(`expected 64-byte Ed25519 signature, got ${sig.length}`);
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
r: '0x' + bytesToHex(sig.slice(0, 32)),
|
|
84
|
+
s: '0x' + bytesToHex(sig.slice(32, 64)),
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function hexToBytes(hex) {
|
|
89
|
+
const clean = hex.startsWith('0x') ? hex.slice(2) : hex;
|
|
90
|
+
const out = new Uint8Array(clean.length / 2);
|
|
91
|
+
for (let i = 0; i < out.length; i++)
|
|
92
|
+
out[i] = parseInt(clean.slice(i * 2, i * 2 + 2), 16);
|
|
93
|
+
return out;
|
|
94
|
+
}
|
|
95
|
+
function bytesToHex(bytes) {
|
|
96
|
+
let s = '';
|
|
97
|
+
for (let i = 0; i < bytes.length; i++)
|
|
98
|
+
s += bytes[i].toString(16).padStart(2, '0');
|
|
99
|
+
return s;
|
|
100
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { UserOperation } from './internal/userOp';
|
|
2
|
+
/** Thin client for an ERC-4337 bundler's JSON-RPC endpoints. */
|
|
3
|
+
export declare class HttpRpcClient {
|
|
4
|
+
readonly bundlerUrl: string;
|
|
5
|
+
readonly entryPointAddress: string;
|
|
6
|
+
readonly chainId: number;
|
|
7
|
+
private readonly userOpJsonRpcProvider;
|
|
8
|
+
initializing: Promise<void>;
|
|
9
|
+
constructor(bundlerUrl: string, entryPointAddress: string, chainId: number);
|
|
10
|
+
validateChainId(): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Send a UserOperation to the bundler.
|
|
13
|
+
* @returns the userOpHash (id of this operation).
|
|
14
|
+
*/
|
|
15
|
+
sendUserOpToBundler(userOp: UserOperation): Promise<string>;
|
|
16
|
+
/**
|
|
17
|
+
* Ask the bundler to estimate gas for a UserOperation.
|
|
18
|
+
*/
|
|
19
|
+
estimateUserOpGas(userOp: Partial<UserOperation>): Promise<{
|
|
20
|
+
callGasLimit: number;
|
|
21
|
+
preVerificationGas: number;
|
|
22
|
+
verificationGasLimit: number;
|
|
23
|
+
}>;
|
|
24
|
+
/** Fetch the bundler's receipt for a UserOperation, or null if not yet mined. */
|
|
25
|
+
getUserOperationReceipt(userOpHash: string): Promise<unknown | null>;
|
|
26
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HttpRpcClient = void 0;
|
|
4
|
+
const ethers_1 = require("ethers");
|
|
5
|
+
const userOp_1 = require("./internal/userOp");
|
|
6
|
+
/** Thin client for an ERC-4337 bundler's JSON-RPC endpoints. */
|
|
7
|
+
class HttpRpcClient {
|
|
8
|
+
constructor(bundlerUrl, entryPointAddress, chainId) {
|
|
9
|
+
this.bundlerUrl = bundlerUrl;
|
|
10
|
+
this.entryPointAddress = entryPointAddress;
|
|
11
|
+
this.chainId = chainId;
|
|
12
|
+
this.userOpJsonRpcProvider = new ethers_1.JsonRpcProvider(this.bundlerUrl);
|
|
13
|
+
this.initializing = this.validateChainId();
|
|
14
|
+
}
|
|
15
|
+
async validateChainId() {
|
|
16
|
+
const chain = await this.userOpJsonRpcProvider.send('eth_chainId', []);
|
|
17
|
+
const bundlerChain = parseInt(chain);
|
|
18
|
+
if (bundlerChain !== this.chainId) {
|
|
19
|
+
throw new Error(`bundler ${this.bundlerUrl} is on chainId ${bundlerChain}, but the client expects ${this.chainId}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Send a UserOperation to the bundler.
|
|
24
|
+
* @returns the userOpHash (id of this operation).
|
|
25
|
+
*/
|
|
26
|
+
async sendUserOpToBundler(userOp) {
|
|
27
|
+
await this.initializing;
|
|
28
|
+
const hexifiedUserOp = (0, userOp_1.deepHexlify)(await (0, ethers_1.resolveProperties)(userOp));
|
|
29
|
+
return await this.userOpJsonRpcProvider.send('eth_sendUserOperation', [hexifiedUserOp, this.entryPointAddress]);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Ask the bundler to estimate gas for a UserOperation.
|
|
33
|
+
*/
|
|
34
|
+
async estimateUserOpGas(userOp) {
|
|
35
|
+
await this.initializing;
|
|
36
|
+
const hexifiedUserOp = (0, userOp_1.deepHexlify)(userOp);
|
|
37
|
+
return await this.userOpJsonRpcProvider.send('eth_estimateUserOperationGas', [hexifiedUserOp, this.entryPointAddress]);
|
|
38
|
+
}
|
|
39
|
+
/** Fetch the bundler's receipt for a UserOperation, or null if not yet mined. */
|
|
40
|
+
async getUserOperationReceipt(userOpHash) {
|
|
41
|
+
await this.initializing;
|
|
42
|
+
return await this.userOpJsonRpcProvider.send('eth_getUserOperationReceipt', [userOpHash]);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.HttpRpcClient = HttpRpcClient;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BigNumberish, BytesLike } from 'ethers';
|
|
2
|
+
/**
|
|
3
|
+
* Returned paymaster parameters. If a paymaster is specified, the gas limits must be
|
|
4
|
+
* specified too (even if postOp is not called, paymasterPostOpGasLimit must be set).
|
|
5
|
+
*/
|
|
6
|
+
export interface PaymasterParams {
|
|
7
|
+
paymaster: string;
|
|
8
|
+
paymasterData?: BytesLike;
|
|
9
|
+
paymasterVerificationGasLimit: BigNumberish;
|
|
10
|
+
paymasterPostOpGasLimit: BigNumberish;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* An API to fill a UserOperation with paymaster info. Subclass and override to implement a
|
|
14
|
+
* specific paymaster (see {@link TacERC20PaymasterAPI}).
|
|
15
|
+
*/
|
|
16
|
+
export declare class PaymasterAPI {
|
|
17
|
+
/** Temporary values to put into the paymaster fields (used for gas estimation). */
|
|
18
|
+
getTemporaryPaymasterData(): Promise<PaymasterParams | null>;
|
|
19
|
+
/** Final paymaster parameters (after gas estimation). */
|
|
20
|
+
getPaymasterData(): Promise<PaymasterParams | null>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PaymasterAPI = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* An API to fill a UserOperation with paymaster info. Subclass and override to implement a
|
|
6
|
+
* specific paymaster (see {@link TacERC20PaymasterAPI}).
|
|
7
|
+
*/
|
|
8
|
+
class PaymasterAPI {
|
|
9
|
+
/** Temporary values to put into the paymaster fields (used for gas estimation). */
|
|
10
|
+
async getTemporaryPaymasterData() {
|
|
11
|
+
return await this.getPaymasterData();
|
|
12
|
+
}
|
|
13
|
+
/** Final paymaster parameters (after gas estimation). */
|
|
14
|
+
async getPaymasterData() {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.PaymasterAPI = PaymasterAPI;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { BigNumberish } from 'ethers';
|
|
2
|
+
export interface Permit2TokenPermission {
|
|
3
|
+
token: string;
|
|
4
|
+
amount: BigNumberish;
|
|
5
|
+
}
|
|
6
|
+
export interface PermitBatchTransferFromInput {
|
|
7
|
+
permitted: Permit2TokenPermission[];
|
|
8
|
+
/** Unique per-permit nonce (Permit2 replay protection). */
|
|
9
|
+
nonce: BigNumberish;
|
|
10
|
+
/** Deadline in unix seconds. Use `ethers.MaxUint256` for no expiry. */
|
|
11
|
+
deadline: BigNumberish;
|
|
12
|
+
/** Chain id this permit is bound to. */
|
|
13
|
+
chainId: BigNumberish;
|
|
14
|
+
/** Address of the deployed `TacPermit2` (the verifyingContract). */
|
|
15
|
+
verifyingContract: string;
|
|
16
|
+
}
|
|
17
|
+
/** Internal packed representation matching the contract's tuple layout. */
|
|
18
|
+
export type PermitBatchTransferFromTuple = [
|
|
19
|
+
Array<[string, BigNumberish]>,
|
|
20
|
+
BigNumberish,
|
|
21
|
+
BigNumberish,
|
|
22
|
+
BigNumberish,
|
|
23
|
+
string
|
|
24
|
+
];
|
|
25
|
+
/** Build the TAC `PermitBatchTransferFrom` tuple, its abi-encoded message, and hash. */
|
|
26
|
+
export declare function buildPermitMessage(input: PermitBatchTransferFromInput): {
|
|
27
|
+
permit: PermitBatchTransferFromTuple;
|
|
28
|
+
messageHex: string;
|
|
29
|
+
permitHash: string;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Wrap a permit tuple + signature blob into the `(permit, signature)` abi-encoded payload
|
|
33
|
+
* that `TacERC20Paymaster._parsePermitData` consumes.
|
|
34
|
+
*/
|
|
35
|
+
export declare function packPermitData(permit: PermitBatchTransferFromTuple, signatureBlob: string): string;
|
|
36
|
+
/** Convenience: full `paymasterData` for Mode 1 = `0x01 ‖ abi.encode(permit, signatureBlob)`. */
|
|
37
|
+
export declare function packPermitPaymasterData(permit: PermitBatchTransferFromTuple, signatureBlob: string): string;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Permit2 helpers — build TAC's `PermitBatchTransferFrom` struct, compute its hash,
|
|
3
|
+
// and pack it into paymasterData.
|
|
4
|
+
//
|
|
5
|
+
// TAC's PermitBatchTransferFrom is a tuple matching ISignatureTransfer, with two extra
|
|
6
|
+
// TAC fields (chainId, verifyingContract=TacPermit2):
|
|
7
|
+
// tuple(tuple(address token,uint256 amount)[], uint256 nonce, uint256 deadline, uint256 chainId, address verifyingContract)
|
|
8
|
+
//
|
|
9
|
+
// permitHash = keccak256(abi.encode(permit)) — the same value `keccak256(message)` equals
|
|
10
|
+
// when TacPermit2 calls account.isValidSignature(message, signature).
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.buildPermitMessage = buildPermitMessage;
|
|
13
|
+
exports.packPermitData = packPermitData;
|
|
14
|
+
exports.packPermitPaymasterData = packPermitPaymasterData;
|
|
15
|
+
const ethers_1 = require("ethers");
|
|
16
|
+
const abiCoder = ethers_1.AbiCoder.defaultAbiCoder();
|
|
17
|
+
const PERMIT_TUPLE_TYPE = 'tuple(tuple(address,uint256)[],uint256,uint256,uint256,address)';
|
|
18
|
+
/** Build the TAC `PermitBatchTransferFrom` tuple, its abi-encoded message, and hash. */
|
|
19
|
+
function buildPermitMessage(input) {
|
|
20
|
+
const permit = [
|
|
21
|
+
input.permitted.map((p) => [p.token, p.amount]),
|
|
22
|
+
input.nonce,
|
|
23
|
+
input.deadline,
|
|
24
|
+
input.chainId,
|
|
25
|
+
input.verifyingContract,
|
|
26
|
+
];
|
|
27
|
+
const messageHex = abiCoder.encode([PERMIT_TUPLE_TYPE], [permit]);
|
|
28
|
+
const permitHash = (0, ethers_1.keccak256)(messageHex);
|
|
29
|
+
return { permit, messageHex, permitHash };
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Wrap a permit tuple + signature blob into the `(permit, signature)` abi-encoded payload
|
|
33
|
+
* that `TacERC20Paymaster._parsePermitData` consumes.
|
|
34
|
+
*/
|
|
35
|
+
function packPermitData(permit, signatureBlob) {
|
|
36
|
+
return abiCoder.encode([PERMIT_TUPLE_TYPE, 'bytes'], [permit, signatureBlob]);
|
|
37
|
+
}
|
|
38
|
+
/** Convenience: full `paymasterData` for Mode 1 = `0x01 ‖ abi.encode(permit, signatureBlob)`. */
|
|
39
|
+
function packPermitPaymasterData(permit, signatureBlob) {
|
|
40
|
+
return (0, ethers_1.concat)(['0x01', packPermitData(permit, signatureBlob)]);
|
|
41
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { BigNumberish } from 'ethers';
|
|
2
|
+
import { Ed25519Signer, TonConnectSigner } from './Ed25519';
|
|
3
|
+
import { UserOperation } from './internal/userOp';
|
|
4
|
+
import { PermitBatchTransferFromInput } from './Permit2';
|
|
5
|
+
import { TacAccountAPI } from './TacAccountAPI';
|
|
6
|
+
import { TransactionDetailsForUserOp } from './TransactionDetailsForUserOp';
|
|
7
|
+
/**
|
|
8
|
+
* Inputs to {@link buildSignedUserOpWithPermit}.
|
|
9
|
+
*
|
|
10
|
+
* @param accountAPI the TacAccountAPI driving sender/factory/callData/nonce. Should NOT have
|
|
11
|
+
* a paymasterAPI configured — this helper owns paymasterData.
|
|
12
|
+
* @param paymaster TacERC20Paymaster contract address.
|
|
13
|
+
* @param permitInput the permit struct to authorise (permitted[].amount caps the gas budget).
|
|
14
|
+
* @param ed25519Signer invoked twice (once per round) with a 64-byte binding.
|
|
15
|
+
* @param txDetails execution target/value/data for the UserOp.
|
|
16
|
+
*/
|
|
17
|
+
export interface BuildPermitUserOpInput {
|
|
18
|
+
accountAPI: TacAccountAPI;
|
|
19
|
+
paymaster: string;
|
|
20
|
+
paymasterVerificationGasLimit?: BigNumberish;
|
|
21
|
+
paymasterPostOpGasLimit?: BigNumberish;
|
|
22
|
+
permitInput: PermitBatchTransferFromInput;
|
|
23
|
+
ed25519Signer: Ed25519Signer;
|
|
24
|
+
txDetails: TransactionDetailsForUserOp;
|
|
25
|
+
}
|
|
26
|
+
/** TonConnect-wallet variant inputs. */
|
|
27
|
+
export interface BuildPermitUserOpInputTonConnect {
|
|
28
|
+
accountAPI: TacAccountAPI;
|
|
29
|
+
paymaster: string;
|
|
30
|
+
paymasterVerificationGasLimit?: BigNumberish;
|
|
31
|
+
paymasterPostOpGasLimit?: BigNumberish;
|
|
32
|
+
permitInput: PermitBatchTransferFromInput;
|
|
33
|
+
tonConnectSigner: TonConnectSigner;
|
|
34
|
+
txDetails: TransactionDetailsForUserOp;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Build a fully-signed UserOp paying gas via TacERC20Paymaster's TRANSFER_VIA_PERMIT mode.
|
|
38
|
+
* Performs the two-round double-sign; the EntryPoint (for userOpHash) is derived from the
|
|
39
|
+
* accountAPI's entryPointAddress + provider.
|
|
40
|
+
*/
|
|
41
|
+
export declare function buildSignedUserOpWithPermit(input: BuildPermitUserOpInput): Promise<UserOperation>;
|
|
42
|
+
/** TonConnect-wallet variant of {@link buildSignedUserOpWithPermit}. */
|
|
43
|
+
export declare function buildSignedUserOpWithPermitTonConnect(input: BuildPermitUserOpInputTonConnect): Promise<UserOperation>;
|