@palindromepay/sdk 2.0.6 → 2.0.7
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 +17 -2
- package/dist/PalindromePaySDK.d.ts +18 -2
- package/dist/PalindromePaySDK.js +74 -27
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -10,7 +10,22 @@ A TypeScript/Node SDK for interacting with the PalindromePay escrow smart contra
|
|
|
10
10
|
|
|
11
11
|
## 📚 Documentation
|
|
12
12
|
|
|
13
|
-
**Full documentation available at: [
|
|
13
|
+
**Full documentation available at: [palindromepay.com/sdk](https://www.palindromepay.com/sdk)**
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## ✨ Features
|
|
18
|
+
|
|
19
|
+
- Interact with on-chain escrow contracts using public & wallet clients
|
|
20
|
+
- Supports ERC20 deposits, fee calculation, and contract state queries
|
|
21
|
+
- Buyer, Seller, Arbiter roles—plus dispute/resolve logic
|
|
22
|
+
- Meta-transaction signature helpers (EIP-712 compatible)
|
|
23
|
+
- Auto-release and time/maturity helpers
|
|
24
|
+
- Subgraph GraphQL queries to fetch and filter escrows and dispute messages
|
|
25
|
+
- Flexible error classes and codes for wallet/client state
|
|
26
|
+
- Utilities for fee calculation, token formatting, deadlines, and maturity times
|
|
27
|
+
- Gas estimation helpers for transaction planning
|
|
28
|
+
- Comprehensive state and role validation helpers
|
|
14
29
|
|
|
15
30
|
---
|
|
16
31
|
|
|
@@ -67,4 +82,4 @@ Contributions are welcome! Please feel free to submit a Pull Request.
|
|
|
67
82
|
## 📞 Support
|
|
68
83
|
|
|
69
84
|
- GitHub Issues: https://github.com/palindromepay/SDKPalindromePay/issues
|
|
70
|
-
- Documentation: https://
|
|
85
|
+
- Documentation: https://www.palindromepay.com/sdk
|
|
@@ -99,7 +99,8 @@ export interface PalindromePaySDKConfig {
|
|
|
99
99
|
publicClient: PublicClient;
|
|
100
100
|
contractAddress: Address;
|
|
101
101
|
walletClient?: EscrowWalletClient;
|
|
102
|
-
|
|
102
|
+
/** Apollo client for subgraph queries (required) */
|
|
103
|
+
apolloClient: ApolloClient;
|
|
103
104
|
chain?: Chain;
|
|
104
105
|
/** Cache TTL in milliseconds (default: 5000) */
|
|
105
106
|
cacheTTL?: number;
|
|
@@ -115,7 +116,6 @@ export interface PalindromePaySDKConfig {
|
|
|
115
116
|
gasBuffer?: number;
|
|
116
117
|
/** Transaction receipt timeout in milliseconds (default: 60000) */
|
|
117
118
|
receiptTimeout?: number;
|
|
118
|
-
subgraphUrl?: string;
|
|
119
119
|
/**
|
|
120
120
|
* Skip eth_call simulation before sending transactions (default: false)
|
|
121
121
|
* Enable this for chains with unreliable RPC simulation (e.g., Base Sepolia)
|
|
@@ -237,6 +237,8 @@ export declare class PalindromePaySDK {
|
|
|
237
237
|
private tokenDecimalsCache;
|
|
238
238
|
/** Cache for immutable contract values */
|
|
239
239
|
private feeReceiverCache;
|
|
240
|
+
/** Cached default arbiter from contract (immutable) */
|
|
241
|
+
private defaultArbiterCache;
|
|
240
242
|
/** Cached multicall support status per chain (null = not yet detected) */
|
|
241
243
|
private multicallSupported;
|
|
242
244
|
private readonly STATE_NAMES;
|
|
@@ -1214,6 +1216,20 @@ export declare class PalindromePaySDK {
|
|
|
1214
1216
|
* @param forceRefresh - Set to true to bypass cache and fetch fresh value
|
|
1215
1217
|
*/
|
|
1216
1218
|
getFeeReceiver(forceRefresh?: boolean): Promise<Address>;
|
|
1219
|
+
/**
|
|
1220
|
+
* Check if an escrow uses the default Palindrome Pay arbiter.
|
|
1221
|
+
*
|
|
1222
|
+
* @param escrow - The escrow data to check
|
|
1223
|
+
* @returns True if the escrow uses the default arbiter
|
|
1224
|
+
*/
|
|
1225
|
+
isDefaultArbiter(escrow: EscrowData): Promise<boolean>;
|
|
1226
|
+
/**
|
|
1227
|
+
* Get the default Palindrome Pay arbiter address from contract.
|
|
1228
|
+
* Result is cached since the value is immutable.
|
|
1229
|
+
*
|
|
1230
|
+
* @returns The default arbiter address
|
|
1231
|
+
*/
|
|
1232
|
+
getDefaultArbiter(): Promise<Address>;
|
|
1217
1233
|
/** Cached fee basis points (lazily computed from contract) */
|
|
1218
1234
|
private cachedFeeBps;
|
|
1219
1235
|
/**
|
package/dist/PalindromePaySDK.js
CHANGED
|
@@ -30,7 +30,6 @@ const actions_1 = require("viem/actions");
|
|
|
30
30
|
const PalindromePay_json_1 = __importDefault(require("./contract/PalindromePay.json"));
|
|
31
31
|
const PalindromePayWallet_json_1 = __importDefault(require("./contract/PalindromePayWallet.json"));
|
|
32
32
|
const USDT_json_1 = __importDefault(require("./contract/USDT.json"));
|
|
33
|
-
const client_1 = require("@apollo/client");
|
|
34
33
|
/** Type guard to check if error is a Viem error */
|
|
35
34
|
function isViemError(error) {
|
|
36
35
|
return (typeof error === 'object' &&
|
|
@@ -100,6 +99,8 @@ const MAX_STRING_LENGTH = 500;
|
|
|
100
99
|
const USER_REJECTION_CODE = 4001;
|
|
101
100
|
/** Seconds per day for maturity calculations */
|
|
102
101
|
const SECONDS_PER_DAY = 86400n;
|
|
102
|
+
/** Maximum maturity days (10 years) */
|
|
103
|
+
const MAX_MATURITY_DAYS = 3650n;
|
|
103
104
|
/** Nonce bitmap word size in bits */
|
|
104
105
|
const NONCE_BITMAP_SIZE = 256;
|
|
105
106
|
/** Default cache TTL in milliseconds */
|
|
@@ -201,6 +202,8 @@ class PalindromePaySDK {
|
|
|
201
202
|
this.tokenDecimalsCache = new Map();
|
|
202
203
|
/** Cache for immutable contract values */
|
|
203
204
|
this.feeReceiverCache = null;
|
|
205
|
+
/** Cached default arbiter from contract (immutable) */
|
|
206
|
+
this.defaultArbiterCache = null;
|
|
204
207
|
/** Cached multicall support status per chain (null = not yet detected) */
|
|
205
208
|
this.multicallSupported = null;
|
|
206
209
|
this.STATE_NAMES = [
|
|
@@ -267,12 +270,10 @@ class PalindromePaySDK {
|
|
|
267
270
|
this.defaultGasLimit = config.defaultGasLimit ?? 500000n;
|
|
268
271
|
this.logLevel = config.logLevel ?? 'info';
|
|
269
272
|
this.logger = config.logger ?? (this.logLevel === 'none' ? noOpLogger : defaultLogger);
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
cache: new client_1.InMemoryCache(),
|
|
275
|
-
});
|
|
273
|
+
if (!config.apolloClient) {
|
|
274
|
+
throw new SDKError("apolloClient is required", SDKErrorCode.VALIDATION_ERROR);
|
|
275
|
+
}
|
|
276
|
+
this.apollo = config.apolloClient;
|
|
276
277
|
}
|
|
277
278
|
// ==========================================================================
|
|
278
279
|
// PRIVATE HELPERS
|
|
@@ -419,6 +420,9 @@ class PalindromePaySDK {
|
|
|
419
420
|
if (maturityDays < 0n) {
|
|
420
421
|
throw new SDKError("Maturity days cannot be negative", SDKErrorCode.VALIDATION_ERROR);
|
|
421
422
|
}
|
|
423
|
+
if (maturityDays > MAX_MATURITY_DAYS) {
|
|
424
|
+
throw new SDKError(`Maturity days cannot exceed ${MAX_MATURITY_DAYS} days (10 years)`, SDKErrorCode.VALIDATION_ERROR);
|
|
425
|
+
}
|
|
422
426
|
if (!title || title.trim().length === 0) {
|
|
423
427
|
throw new SDKError("Title cannot be empty", SDKErrorCode.VALIDATION_ERROR);
|
|
424
428
|
}
|
|
@@ -1041,10 +1045,19 @@ class PalindromePaySDK {
|
|
|
1041
1045
|
// Validate and normalize addresses
|
|
1042
1046
|
const token = validateAddress(params.token, "token");
|
|
1043
1047
|
const buyer = validateAddress(params.buyer, "buyer");
|
|
1044
|
-
const arbiter = params.arbiter
|
|
1045
|
-
? validateAddress(params.arbiter, "arbiter")
|
|
1046
|
-
: viem_1.zeroAddress;
|
|
1047
1048
|
const sellerAddress = walletClient.account.address;
|
|
1049
|
+
// Use default arbiter if none provided, reject zero address
|
|
1050
|
+
let arbiter;
|
|
1051
|
+
if (params.arbiter) {
|
|
1052
|
+
const validatedArbiter = validateAddress(params.arbiter, "arbiter");
|
|
1053
|
+
if (isZeroAddress(validatedArbiter)) {
|
|
1054
|
+
throw new SDKError("Zero address not allowed for arbiter. Omit arbiter param to use Palindrome Pay default.", SDKErrorCode.VALIDATION_ERROR);
|
|
1055
|
+
}
|
|
1056
|
+
arbiter = validatedArbiter;
|
|
1057
|
+
}
|
|
1058
|
+
else {
|
|
1059
|
+
arbiter = await this.getDefaultArbiter();
|
|
1060
|
+
}
|
|
1048
1061
|
const maturityDays = params.maturityTimeDays ?? 1n;
|
|
1049
1062
|
// Validate using helper
|
|
1050
1063
|
this.validateCreateEscrowParams({
|
|
@@ -1057,13 +1070,11 @@ class PalindromePaySDK {
|
|
|
1057
1070
|
title: params.title,
|
|
1058
1071
|
});
|
|
1059
1072
|
// Validate arbiter is not buyer or seller
|
|
1060
|
-
if (
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
throw new SDKError("Arbiter cannot be the seller", SDKErrorCode.VALIDATION_ERROR);
|
|
1066
|
-
}
|
|
1073
|
+
if ((0, viem_1.getAddress)(arbiter) === (0, viem_1.getAddress)(buyer)) {
|
|
1074
|
+
throw new SDKError("Arbiter cannot be the buyer", SDKErrorCode.VALIDATION_ERROR);
|
|
1075
|
+
}
|
|
1076
|
+
if ((0, viem_1.getAddress)(arbiter) === (0, viem_1.getAddress)(sellerAddress)) {
|
|
1077
|
+
throw new SDKError("Arbiter cannot be the seller", SDKErrorCode.VALIDATION_ERROR);
|
|
1067
1078
|
}
|
|
1068
1079
|
const ipfsHash = params.ipfsHash ?? "";
|
|
1069
1080
|
// Predict next escrow ID and wallet address
|
|
@@ -1158,10 +1169,19 @@ class PalindromePaySDK {
|
|
|
1158
1169
|
// Validate and normalize addresses
|
|
1159
1170
|
const token = validateAddress(params.token, "token");
|
|
1160
1171
|
const seller = validateAddress(params.seller, "seller");
|
|
1161
|
-
const arbiter = params.arbiter
|
|
1162
|
-
? validateAddress(params.arbiter, "arbiter")
|
|
1163
|
-
: viem_1.zeroAddress;
|
|
1164
1172
|
const buyerAddress = walletClient.account.address;
|
|
1173
|
+
// Use default arbiter if none provided, reject zero address
|
|
1174
|
+
let arbiter;
|
|
1175
|
+
if (params.arbiter) {
|
|
1176
|
+
const validatedArbiter = validateAddress(params.arbiter, "arbiter");
|
|
1177
|
+
if (isZeroAddress(validatedArbiter)) {
|
|
1178
|
+
throw new SDKError("Zero address not allowed for arbiter. Omit arbiter param to use Palindrome Pay default.", SDKErrorCode.VALIDATION_ERROR);
|
|
1179
|
+
}
|
|
1180
|
+
arbiter = validatedArbiter;
|
|
1181
|
+
}
|
|
1182
|
+
else {
|
|
1183
|
+
arbiter = await this.getDefaultArbiter();
|
|
1184
|
+
}
|
|
1165
1185
|
const maturityDays = params.maturityTimeDays ?? 1n;
|
|
1166
1186
|
// Validate using helper
|
|
1167
1187
|
this.validateCreateEscrowParams({
|
|
@@ -1174,13 +1194,11 @@ class PalindromePaySDK {
|
|
|
1174
1194
|
title: params.title,
|
|
1175
1195
|
});
|
|
1176
1196
|
// Validate arbiter is not buyer or seller
|
|
1177
|
-
if (
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
throw new SDKError("Arbiter cannot be the buyer", SDKErrorCode.VALIDATION_ERROR);
|
|
1183
|
-
}
|
|
1197
|
+
if ((0, viem_1.getAddress)(arbiter) === (0, viem_1.getAddress)(seller)) {
|
|
1198
|
+
throw new SDKError("Arbiter cannot be the seller", SDKErrorCode.VALIDATION_ERROR);
|
|
1199
|
+
}
|
|
1200
|
+
if ((0, viem_1.getAddress)(arbiter) === (0, viem_1.getAddress)(buyerAddress)) {
|
|
1201
|
+
throw new SDKError("Arbiter cannot be the buyer", SDKErrorCode.VALIDATION_ERROR);
|
|
1184
1202
|
}
|
|
1185
1203
|
const ipfsHash = params.ipfsHash ?? "";
|
|
1186
1204
|
// Approve token spending
|
|
@@ -2189,6 +2207,7 @@ class PalindromePaySDK {
|
|
|
2189
2207
|
this.escrowCache.clear();
|
|
2190
2208
|
this.tokenDecimalsCache.clear();
|
|
2191
2209
|
this.feeReceiverCache = null;
|
|
2210
|
+
this.defaultArbiterCache = null;
|
|
2192
2211
|
this.cachedFeeBps = null;
|
|
2193
2212
|
this.multicallSupported = null;
|
|
2194
2213
|
await this.clearApolloCache();
|
|
@@ -2814,6 +2833,34 @@ class PalindromePaySDK {
|
|
|
2814
2833
|
});
|
|
2815
2834
|
return this.feeReceiverCache;
|
|
2816
2835
|
}
|
|
2836
|
+
/**
|
|
2837
|
+
* Check if an escrow uses the default Palindrome Pay arbiter.
|
|
2838
|
+
*
|
|
2839
|
+
* @param escrow - The escrow data to check
|
|
2840
|
+
* @returns True if the escrow uses the default arbiter
|
|
2841
|
+
*/
|
|
2842
|
+
async isDefaultArbiter(escrow) {
|
|
2843
|
+
const defaultArbiter = await this.getDefaultArbiter();
|
|
2844
|
+
return escrow.arbiter.toLowerCase() === defaultArbiter.toLowerCase();
|
|
2845
|
+
}
|
|
2846
|
+
/**
|
|
2847
|
+
* Get the default Palindrome Pay arbiter address from contract.
|
|
2848
|
+
* Result is cached since the value is immutable.
|
|
2849
|
+
*
|
|
2850
|
+
* @returns The default arbiter address
|
|
2851
|
+
*/
|
|
2852
|
+
async getDefaultArbiter() {
|
|
2853
|
+
if (this.defaultArbiterCache) {
|
|
2854
|
+
return this.defaultArbiterCache;
|
|
2855
|
+
}
|
|
2856
|
+
const arbiter = await (0, actions_1.readContract)(this.publicClient, {
|
|
2857
|
+
address: this.contractAddress,
|
|
2858
|
+
abi: PalindromePay_json_1.default.abi,
|
|
2859
|
+
functionName: "DEFAULT_ARBITER",
|
|
2860
|
+
});
|
|
2861
|
+
this.defaultArbiterCache = arbiter;
|
|
2862
|
+
return this.defaultArbiterCache;
|
|
2863
|
+
}
|
|
2817
2864
|
/**
|
|
2818
2865
|
* Get fee percentage in basis points.
|
|
2819
2866
|
* Tries to read FEE_BPS from contract, falls back to default (100 = 1%).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@palindromepay/sdk",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.7",
|
|
4
4
|
"description": "TypeScript SDK for PalindromeCryptoEscrow - Secure blockchain escrow with buyer/seller protection",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"bugs": {
|
|
35
35
|
"url": "https://github.com/palindromepay/SDKPalindromePay/issues"
|
|
36
36
|
},
|
|
37
|
-
"homepage": "https://
|
|
37
|
+
"homepage": "https://www.palindromepay.com/sdk",
|
|
38
38
|
"files": [
|
|
39
39
|
"dist",
|
|
40
40
|
"README.md",
|
|
@@ -56,6 +56,9 @@
|
|
|
56
56
|
"undici-types": "^7.16.0",
|
|
57
57
|
"viem": "^2.38.0"
|
|
58
58
|
},
|
|
59
|
+
"peerDependencies": {
|
|
60
|
+
"@apollo/client": "^4.0.0"
|
|
61
|
+
},
|
|
59
62
|
"devDependencies": {
|
|
60
63
|
"@apollo/client": "^4.0.7",
|
|
61
64
|
"@types/jest": "^30.0.0",
|