@trustvc/trustvc 2.15.0-beta.1 → 2.15.0-beta.2

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/README.md CHANGED
@@ -28,6 +28,15 @@ TrustVC is a comprehensive wrapper library designed to simplify the signing and
28
28
  - [8. **Document Builder**](#8-document-builder)
29
29
  - [9. **Document Store**](#9-document-store)
30
30
  - [10. **Transaction Cancel**](#10-transaction-cancel)
31
+ - [11. **Gasless Operations (EIP-7702)**](#11-gasless-operations-eip-7702)
32
+ - [Overview](#overview-1)
33
+ - [deployPlatformPaymaster](#deployplatformpaymaster)
34
+ - [deployTokenRegistryGasless](#deploytokenregistrygasless)
35
+ - [mintGasless](#mintgasless)
36
+ - [Transfer Functions](#transfer-functions)
37
+ - [Reject Transfer Functions](#reject-transfer-functions)
38
+ - [Return to Issuer Functions](#return-to-issuer-functions)
39
+ - [Admin Functions](#admin-functions)
31
40
 
32
41
  ## Installation
33
42
 
@@ -1203,3 +1212,297 @@ const replacementHash2 = await cancelTransaction(signer, {
1203
1212
  gasPrice: '25000000000', // 25 gwei in wei
1204
1213
  });
1205
1214
  ```
1215
+
1216
+ ---
1217
+
1218
+ ## 11. **Gasless Operations (EIP-7702)**
1219
+
1220
+ > **Beta:** Gasless transactions are currently in beta. APIs and contract addresses may change before the stable release. Use on testnet only.
1221
+
1222
+ ### Overview
1223
+
1224
+ TrustVC supports gasless trade document operations via **EIP-7702** (smart account delegation) and **ERC-4337** (account abstraction). Users can deploy token registries, mint documents, and perform all title escrow operations without holding ETH — gas is sponsored by a **PlatformPaymaster** deployed per platform.
1225
+
1226
+ **How it works:**
1227
+
1228
+ 1. An EOA signs an EIP-7702 authorization, delegating to the `EIP7702Implementation` contract. Its bytecode becomes `0xef0100 || impl_address` while keeping the same address and private key.
1229
+ 2. The platform deploys a `PlatformPaymaster` clone via `PlatformAccountFactory`.
1230
+ 3. Users submit `UserOperation`s through a bundler (Pimlico). The paymaster validates and sponsors gas for authorized operations.
1231
+
1232
+ All gasless functions accept a `smartAccountClient` built with [permissionless](https://docs.pimlico.io/permissionless) and return `Promise<string>` (transaction hash).
1233
+
1234
+ ```ts
1235
+ import { buildSmartAccountClient } from './your-pimlico-setup';
1236
+
1237
+ const { smartAccountClient } = await buildSmartAccountClient(
1238
+ ownerAddress, // delegated EOA
1239
+ paymasterAddress, // platform's PlatformPaymaster
1240
+ );
1241
+ ```
1242
+
1243
+ ---
1244
+
1245
+ ### deployPlatformPaymaster
1246
+
1247
+ Deploys a new `PlatformPaymaster` clone for your platform via `PlatformAccountFactory`. Accepts a viem `WalletClient` or ethers v5/v6 signer.
1248
+
1249
+ ```ts
1250
+ import { deployPlatformPaymaster } from '@trustvc/trustvc';
1251
+ import { createWalletClient, createPublicClient, http } from 'viem';
1252
+ import { sepolia } from 'viem/chains';
1253
+
1254
+ const { txHash, paymasterAddress } = await deployPlatformPaymaster(
1255
+ walletClient,
1256
+ {
1257
+ platformAddress: '0xYourPlatformOwner...',
1258
+ dailyLimit: 0n, // 0n = unlimited; set in wei to cap per-user daily spend
1259
+ salt: `0x${'ab'.repeat(32)}`, // bytes32 CREATE2 salt — must be unique per platform
1260
+ },
1261
+ publicClient,
1262
+ );
1263
+
1264
+ console.log('Paymaster deployed at:', paymasterAddress);
1265
+ ```
1266
+
1267
+ ---
1268
+
1269
+ ### deployTokenRegistryGasless
1270
+
1271
+ Deploys a new `TradeTrustToken` registry clone through the paymaster. The caller must have at least 1 deployment credit (`setUserWhitelist`). Emits `RegistryDeployed(user, deployed, creditsLeft)`.
1272
+
1273
+ ```ts
1274
+ import { deployTokenRegistryGasless } from '@trustvc/trustvc';
1275
+
1276
+ const txHash = await deployTokenRegistryGasless(
1277
+ 'My Shipping Line', // registry name
1278
+ 'MSL', // registry symbol
1279
+ smartAccountClient,
1280
+ {
1281
+ paymasterAddress: '0xYourPaymaster...',
1282
+ tokenRegistryImplAddress: '0x64bc665056DC8bE4092e569ED13a7F273Be28cD2', // TDocDeployer on Sepolia
1283
+ },
1284
+ );
1285
+ ```
1286
+
1287
+ ---
1288
+
1289
+ ### mintGasless
1290
+
1291
+ Mints a new trade document on an authorized registry. Automatically authorizes the beneficiary, holder, and the new `TitleEscrow` on the paymaster. Emits `TitleEscrowLinked(titleEscrow, registry)`.
1292
+
1293
+ ```ts
1294
+ import { mintGasless } from '@trustvc/trustvc';
1295
+
1296
+ const txHash = await mintGasless(
1297
+ {
1298
+ paymasterAddress: '0xYourPaymaster...',
1299
+ tokenRegistryAddress: '0xYourRegistry...',
1300
+ },
1301
+ smartAccountClient,
1302
+ {
1303
+ beneficiaryAddress: '0xBeneficiary...',
1304
+ holderAddress: '0xHolder...',
1305
+ tokenId: '0xdeadbeef',
1306
+ remarks: 'Initial issuance', // optional — encrypted on-chain with options.id
1307
+ },
1308
+ { id: 'document-uuid' },
1309
+ );
1310
+ ```
1311
+
1312
+ ---
1313
+
1314
+ ### Transfer Functions
1315
+
1316
+ All transfer functions target the `TitleEscrow` contract. Remarks are automatically encrypted with `options.id` before being sent on-chain.
1317
+
1318
+ #### transferHolderGasless
1319
+
1320
+ Transfers the **holder** role. Caller must be the current holder.
1321
+
1322
+ ```ts
1323
+ import { transferHolderGasless } from '@trustvc/trustvc';
1324
+
1325
+ const txHash = await transferHolderGasless(
1326
+ { titleEscrowAddress: '0xTitleEscrow...' },
1327
+ smartAccountClient,
1328
+ { holderAddress: '0xNewHolder...', remarks: 'Transferring to forwarder' },
1329
+ { id: 'document-uuid' },
1330
+ );
1331
+ ```
1332
+
1333
+ #### transferBeneficiaryGasless
1334
+
1335
+ Transfers the **beneficiary** role. Caller must be the current beneficiary.
1336
+
1337
+ ```ts
1338
+ import { transferBeneficiaryGasless } from '@trustvc/trustvc';
1339
+
1340
+ const txHash = await transferBeneficiaryGasless(
1341
+ { titleEscrowAddress: '0xTitleEscrow...' },
1342
+ smartAccountClient,
1343
+ { newBeneficiaryAddress: '0xNewBeneficiary...', remarks: 'Endorsing to buyer' },
1344
+ { id: 'document-uuid' },
1345
+ );
1346
+ ```
1347
+
1348
+ #### transferOwnersGasless
1349
+
1350
+ Transfers both holder and beneficiary in one transaction. Caller must be both.
1351
+
1352
+ ```ts
1353
+ import { transferOwnersGasless } from '@trustvc/trustvc';
1354
+
1355
+ const txHash = await transferOwnersGasless(
1356
+ { titleEscrowAddress: '0xTitleEscrow...' },
1357
+ smartAccountClient,
1358
+ {
1359
+ newBeneficiaryAddress: '0xNewBeneficiary...',
1360
+ newHolderAddress: '0xNewHolder...',
1361
+ remarks: 'Full transfer',
1362
+ },
1363
+ { id: 'document-uuid' },
1364
+ );
1365
+ ```
1366
+
1367
+ #### nominateGasless
1368
+
1369
+ Nominates a new beneficiary without immediately completing the transfer.
1370
+
1371
+ ```ts
1372
+ import { nominateGasless } from '@trustvc/trustvc';
1373
+
1374
+ const txHash = await nominateGasless(
1375
+ { titleEscrowAddress: '0xTitleEscrow...' },
1376
+ smartAccountClient,
1377
+ { newBeneficiaryAddress: '0xNominated...', remarks: 'Nomination' },
1378
+ { id: 'document-uuid' },
1379
+ );
1380
+ ```
1381
+
1382
+ ---
1383
+
1384
+ ### Reject Transfer Functions
1385
+
1386
+ Mirror of Token Registry v5's rejection methods — see [section 7](#b-token-registry-v5) for the on-chain rules.
1387
+
1388
+ ```ts
1389
+ import {
1390
+ rejectTransferHolderGasless,
1391
+ rejectTransferBeneficiaryGasless,
1392
+ rejectTransferOwnersGasless,
1393
+ } from '@trustvc/trustvc';
1394
+
1395
+ // Reject a pending holder transfer (caller = current holder)
1396
+ await rejectTransferHolderGasless(
1397
+ { titleEscrowAddress: '0xTitleEscrow...' },
1398
+ smartAccountClient,
1399
+ { remarks: 'Rejecting transfer' },
1400
+ { id: 'document-uuid' },
1401
+ );
1402
+
1403
+ // Reject a pending beneficiary nomination (caller = current beneficiary)
1404
+ await rejectTransferBeneficiaryGasless(
1405
+ { titleEscrowAddress: '0xTitleEscrow...' },
1406
+ smartAccountClient,
1407
+ { remarks: 'Rejecting nomination' },
1408
+ { id: 'document-uuid' },
1409
+ );
1410
+
1411
+ // Reject a combined transfer (caller = both holder and beneficiary)
1412
+ await rejectTransferOwnersGasless(
1413
+ { titleEscrowAddress: '0xTitleEscrow...' },
1414
+ smartAccountClient,
1415
+ { remarks: 'Rejecting combined transfer' },
1416
+ { id: 'document-uuid' },
1417
+ );
1418
+ ```
1419
+
1420
+ ---
1421
+
1422
+ ### Return to Issuer Functions
1423
+
1424
+ #### returnToIssuerGasless
1425
+
1426
+ Returns the document to the issuer. Caller must be both holder and beneficiary.
1427
+
1428
+ ```ts
1429
+ import { returnToIssuerGasless } from '@trustvc/trustvc';
1430
+
1431
+ await returnToIssuerGasless(
1432
+ { titleEscrowAddress: '0xTitleEscrow...' },
1433
+ smartAccountClient,
1434
+ { remarks: 'Surrendering document' },
1435
+ { id: 'document-uuid' },
1436
+ );
1437
+ ```
1438
+
1439
+ #### rejectReturnedGasless
1440
+
1441
+ Restores the document back to the title escrow (registry admin rejects the return).
1442
+
1443
+ ```ts
1444
+ import { rejectReturnedGasless } from '@trustvc/trustvc';
1445
+
1446
+ await rejectReturnedGasless(
1447
+ { tokenRegistryAddress: '0xYourRegistry...' },
1448
+ smartAccountClient,
1449
+ { tokenId: '0xdeadbeef', remarks: 'Return rejected' },
1450
+ { id: 'document-uuid' },
1451
+ );
1452
+ ```
1453
+
1454
+ #### acceptReturnedGasless
1455
+
1456
+ Burns the document (registry admin accepts the return).
1457
+
1458
+ ```ts
1459
+ import { acceptReturnedGasless } from '@trustvc/trustvc';
1460
+
1461
+ await acceptReturnedGasless(
1462
+ { tokenRegistryAddress: '0xYourRegistry...' },
1463
+ smartAccountClient,
1464
+ { tokenId: '0xdeadbeef', remarks: 'Document accepted and destroyed' },
1465
+ { id: 'document-uuid' },
1466
+ );
1467
+ ```
1468
+
1469
+ ---
1470
+
1471
+ ### Admin Functions
1472
+
1473
+ `onlyOwner` functions for managing the `PlatformPaymaster`. All accept a viem `WalletClient` or ethers v5/v6 signer and return `Promise<string>` (tx hash).
1474
+
1475
+ ```ts
1476
+ import {
1477
+ setUserWhitelist,
1478
+ removeUserFromWhitelist,
1479
+ addRegistry,
1480
+ removeRegistry,
1481
+ addTitleEscrow,
1482
+ removeTitleEscrow,
1483
+ addAuthorizedCaller,
1484
+ removeAuthorizedCaller,
1485
+ setDailyLimit,
1486
+ } from '@trustvc/trustvc';
1487
+
1488
+ // Grant a user 2 registry deployment credits (max 3)
1489
+ await setUserWhitelist(ownerSigner, paymasterAddress, '0xUser...', 2n);
1490
+
1491
+ // Remove a user from the whitelist
1492
+ await removeUserFromWhitelist(ownerSigner, paymasterAddress, '0xUser...');
1493
+
1494
+ // Authorize a registry so the paymaster will sponsor its calls
1495
+ await addRegistry(ownerSigner, paymasterAddress, '0xRegistry...');
1496
+ await removeRegistry(ownerSigner, paymasterAddress, '0xRegistry...');
1497
+
1498
+ // Authorize a title escrow
1499
+ await addTitleEscrow(ownerSigner, paymasterAddress, '0xTitleEscrow...');
1500
+ await removeTitleEscrow(ownerSigner, paymasterAddress, '0xTitleEscrow...');
1501
+
1502
+ // Manage authorized callers (beneficiary / holder addresses for Path A)
1503
+ await addAuthorizedCaller(ownerSigner, paymasterAddress, '0xCaller...');
1504
+ await removeAuthorizedCaller(ownerSigner, paymasterAddress, '0xCaller...');
1505
+
1506
+ // Update the per-user daily gas spend cap (0n = unlimited)
1507
+ await setDailyLimit(ownerSigner, paymasterAddress, 0n);
1508
+ ```
@@ -3,24 +3,29 @@
3
3
  var tokenRegistryFunctionsGasless = require('./token-registry-functions-gasless');
4
4
  var deploy = require('./deploy');
5
5
  var platformPaymasterFunctions = require('./platform-paymaster-functions');
6
+ var eip7702 = require('@trustvc/eip7702');
6
7
 
7
8
 
8
9
 
10
+ Object.defineProperty(exports, "eip7702Abis", {
11
+ enumerable: true,
12
+ get: function () { return eip7702.abis; }
13
+ });
9
14
  Object.keys(tokenRegistryFunctionsGasless).forEach(function (k) {
10
- if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
11
- enumerable: true,
12
- get: function () { return tokenRegistryFunctionsGasless[k]; }
13
- });
15
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
16
+ enumerable: true,
17
+ get: function () { return tokenRegistryFunctionsGasless[k]; }
18
+ });
14
19
  });
15
20
  Object.keys(deploy).forEach(function (k) {
16
- if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
17
- enumerable: true,
18
- get: function () { return deploy[k]; }
19
- });
21
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
22
+ enumerable: true,
23
+ get: function () { return deploy[k]; }
24
+ });
20
25
  });
21
26
  Object.keys(platformPaymasterFunctions).forEach(function (k) {
22
- if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
23
- enumerable: true,
24
- get: function () { return platformPaymasterFunctions[k]; }
25
- });
27
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
28
+ enumerable: true,
29
+ get: function () { return platformPaymasterFunctions[k]; }
30
+ });
26
31
  });
@@ -1,3 +1,4 @@
1
1
  export * from './token-registry-functions-gasless';
2
2
  export * from './deploy';
3
3
  export * from './platform-paymaster-functions';
4
+ export { abis as eip7702Abis } from '@trustvc/eip7702';
@@ -5,6 +5,7 @@ export { nominateGasless, transferBeneficiaryGasless, transferHolderGasless, tra
5
5
  export { DeployPlatformPaymasterOptions, DeployPlatformPaymasterResult, deployPlatformPaymaster } from './deploy/platform-paymaster.js';
6
6
  export { DeployTokenRegistryGaslessOptions, deployTokenRegistryGasless } from './deploy/token-registry.js';
7
7
  export { addAuthorizedCaller, addRegistry, addTitleEscrow, removeAuthorizedCaller, removeRegistry, removeTitleEscrow, removeUserFromWhitelist, setDailyLimit, setUserWhitelist } from './platform-paymaster-functions/admin.js';
8
+ export { abis as eip7702Abis } from '@trustvc/eip7702';
8
9
  import '../token-registry-functions/types.js';
9
10
  import '../utils/supportedChains/index.js';
10
11
  import '../utils/gasStation/index.js';
@@ -33,6 +33,7 @@ export { nominateGasless, transferBeneficiaryGasless, transferHolderGasless, tra
33
33
  export { DeployPlatformPaymasterOptions, DeployPlatformPaymasterResult, deployPlatformPaymaster } from './eip7702-functions/deploy/platform-paymaster.js';
34
34
  export { DeployTokenRegistryGaslessOptions, deployTokenRegistryGasless } from './eip7702-functions/deploy/token-registry.js';
35
35
  export { addAuthorizedCaller, addRegistry, addTitleEscrow, removeAuthorizedCaller, removeRegistry, removeTitleEscrow, removeUserFromWhitelist, setDailyLimit, setUserWhitelist } from './eip7702-functions/platform-paymaster-functions/admin.js';
36
+ export { abis as eip7702Abis } from '@trustvc/eip7702';
36
37
  export { decrypt } from './core/decrypt.js';
37
38
  export { encrypt } from './core/encrypt.js';
38
39
  export { verifyDocument } from './core/verify.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trustvc/trustvc",
3
- "version": "2.15.0-beta.1",
3
+ "version": "2.15.0-beta.2",
4
4
  "description": "TrustVC library",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",