@palindromepay/sdk 1.9.9 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/PalindromePaySDK.d.ts +20 -5
- package/dist/PalindromePaySDK.js +182 -17
- package/dist/contract/PalindromePay.json +1204 -1
- package/dist/contract/PalindromePayWallet.json +306 -1
- package/package.json +1 -1
|
@@ -86,7 +86,8 @@ export declare enum SDKErrorCode {
|
|
|
86
86
|
RPC_ERROR = "RPC_ERROR",
|
|
87
87
|
EVIDENCE_ALREADY_SUBMITTED = "EVIDENCE_ALREADY_SUBMITTED",
|
|
88
88
|
ESCROW_NOT_FOUND = "ESCROW_NOT_FOUND",
|
|
89
|
-
ALREADY_ACCEPTED = "ALREADY_ACCEPTED"
|
|
89
|
+
ALREADY_ACCEPTED = "ALREADY_ACCEPTED",
|
|
90
|
+
SIGNATURE_INVALID = "SIGNATURE_INVALID"
|
|
90
91
|
}
|
|
91
92
|
export type EscrowWalletClient = WalletClient<Transport, Chain, Account>;
|
|
92
93
|
export declare class SDKError extends Error {
|
|
@@ -331,6 +332,11 @@ export declare class PalindromePaySDK {
|
|
|
331
332
|
* Used for: deposit, confirmDelivery, requestCancel, submitArbiterDecision
|
|
332
333
|
*/
|
|
333
334
|
signWalletAuthorization(walletClient: EscrowWalletClient, walletAddress: Address, escrowId: bigint): Promise<Hex>;
|
|
335
|
+
/**
|
|
336
|
+
* Verify a wallet authorization signature locally before submitting transaction
|
|
337
|
+
* This ensures the signature is cryptographically valid for the expected signer
|
|
338
|
+
*/
|
|
339
|
+
private verifyWalletSignature;
|
|
334
340
|
/**
|
|
335
341
|
* Sign a confirm delivery message (for gasless meta-tx)
|
|
336
342
|
*/
|
|
@@ -349,6 +355,7 @@ export declare class PalindromePaySDK {
|
|
|
349
355
|
isSignatureDeadlineExpired(deadline: bigint, safetySeconds?: number): boolean;
|
|
350
356
|
/**
|
|
351
357
|
* Predict the wallet address for a given escrow ID (before creation)
|
|
358
|
+
* Uses CREATE2 address computation: keccak256(0xff ++ deployer ++ salt ++ initCodeHash)
|
|
352
359
|
*/
|
|
353
360
|
predictWalletAddress(escrowId: bigint): Promise<Address>;
|
|
354
361
|
/**
|
|
@@ -488,6 +495,7 @@ export declare class PalindromePaySDK {
|
|
|
488
495
|
escrowId: bigint;
|
|
489
496
|
txHash: Hex;
|
|
490
497
|
walletAddress: Address;
|
|
498
|
+
signatureValid: boolean;
|
|
491
499
|
}>;
|
|
492
500
|
/**
|
|
493
501
|
* Create a new escrow and deposit funds as the buyer (single transaction)
|
|
@@ -517,6 +525,7 @@ export declare class PalindromePaySDK {
|
|
|
517
525
|
escrowId: bigint;
|
|
518
526
|
txHash: Hex;
|
|
519
527
|
walletAddress: Address;
|
|
528
|
+
signatureValid: boolean;
|
|
520
529
|
}>;
|
|
521
530
|
/**
|
|
522
531
|
* Deposit funds into an existing escrow as the buyer
|
|
@@ -530,13 +539,16 @@ export declare class PalindromePaySDK {
|
|
|
530
539
|
*
|
|
531
540
|
* @param walletClient - The buyer's wallet client (must have account connected)
|
|
532
541
|
* @param escrowId - The escrow ID to deposit into
|
|
533
|
-
* @returns
|
|
542
|
+
* @returns Object containing transaction hash and signature validity
|
|
534
543
|
* @throws {SDKError} WALLET_NOT_CONNECTED - If wallet client is not connected
|
|
535
544
|
* @throws {SDKError} NOT_BUYER - If caller is not the designated buyer
|
|
536
545
|
* @throws {SDKError} INVALID_STATE - If escrow is not in AWAITING_PAYMENT state
|
|
537
546
|
* @throws {SDKError} INSUFFICIENT_BALANCE - If buyer has insufficient token balance
|
|
538
547
|
*/
|
|
539
|
-
deposit(walletClient: EscrowWalletClient, escrowId: bigint): Promise<
|
|
548
|
+
deposit(walletClient: EscrowWalletClient, escrowId: bigint): Promise<{
|
|
549
|
+
txHash: Hex;
|
|
550
|
+
signatureValid: boolean;
|
|
551
|
+
}>;
|
|
540
552
|
/**
|
|
541
553
|
* Accept an escrow as the seller (for buyer-created escrows)
|
|
542
554
|
*
|
|
@@ -548,13 +560,16 @@ export declare class PalindromePaySDK {
|
|
|
548
560
|
*
|
|
549
561
|
* @param walletClient - The seller's wallet client (must have account connected)
|
|
550
562
|
* @param escrowId - The escrow ID to accept
|
|
551
|
-
* @returns
|
|
563
|
+
* @returns Object containing transaction hash and signature validity
|
|
552
564
|
* @throws {SDKError} WALLET_NOT_CONNECTED - If wallet client is not connected
|
|
553
565
|
* @throws {SDKError} NOT_SELLER - If caller is not the designated seller
|
|
554
566
|
* @throws {SDKError} INVALID_STATE - If escrow is not in AWAITING_DELIVERY state
|
|
555
567
|
* @throws {SDKError} ALREADY_ACCEPTED - If escrow was already accepted
|
|
556
568
|
*/
|
|
557
|
-
acceptEscrow(walletClient: EscrowWalletClient, escrowId: bigint): Promise<
|
|
569
|
+
acceptEscrow(walletClient: EscrowWalletClient, escrowId: bigint): Promise<{
|
|
570
|
+
txHash: Hex;
|
|
571
|
+
signatureValid: boolean;
|
|
572
|
+
}>;
|
|
558
573
|
/**
|
|
559
574
|
* Confirm delivery and release funds to the seller
|
|
560
575
|
*
|
package/dist/PalindromePaySDK.js
CHANGED
|
@@ -130,6 +130,7 @@ var SDKErrorCode;
|
|
|
130
130
|
SDKErrorCode["EVIDENCE_ALREADY_SUBMITTED"] = "EVIDENCE_ALREADY_SUBMITTED";
|
|
131
131
|
SDKErrorCode["ESCROW_NOT_FOUND"] = "ESCROW_NOT_FOUND";
|
|
132
132
|
SDKErrorCode["ALREADY_ACCEPTED"] = "ALREADY_ACCEPTED";
|
|
133
|
+
SDKErrorCode["SIGNATURE_INVALID"] = "SIGNATURE_INVALID";
|
|
133
134
|
})(SDKErrorCode || (exports.SDKErrorCode = SDKErrorCode = {}));
|
|
134
135
|
class SDKError extends Error {
|
|
135
136
|
constructor(message, code, details) {
|
|
@@ -573,6 +574,32 @@ class PalindromePaySDK {
|
|
|
573
574
|
validateSignature(signature, "wallet authorization signature");
|
|
574
575
|
return signature;
|
|
575
576
|
}
|
|
577
|
+
/**
|
|
578
|
+
* Verify a wallet authorization signature locally before submitting transaction
|
|
579
|
+
* This ensures the signature is cryptographically valid for the expected signer
|
|
580
|
+
*/
|
|
581
|
+
async verifyWalletSignature(signature, walletAddress, escrowId, expectedSigner) {
|
|
582
|
+
try {
|
|
583
|
+
return await (0, viem_1.verifyTypedData)({
|
|
584
|
+
address: expectedSigner,
|
|
585
|
+
domain: this.getWalletDomain(walletAddress),
|
|
586
|
+
types: this.walletAuthorizationTypes,
|
|
587
|
+
primaryType: "WalletAuthorization",
|
|
588
|
+
message: {
|
|
589
|
+
escrowId,
|
|
590
|
+
wallet: walletAddress,
|
|
591
|
+
participant: expectedSigner,
|
|
592
|
+
},
|
|
593
|
+
signature,
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
catch (error) {
|
|
597
|
+
this.log('warn', 'Signature verification failed', {
|
|
598
|
+
error: error instanceof Error ? error.message : String(error),
|
|
599
|
+
});
|
|
600
|
+
return false;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
576
603
|
/**
|
|
577
604
|
* Sign a confirm delivery message (for gasless meta-tx)
|
|
578
605
|
*/
|
|
@@ -644,17 +671,28 @@ class PalindromePaySDK {
|
|
|
644
671
|
// ==========================================================================
|
|
645
672
|
/**
|
|
646
673
|
* Predict the wallet address for a given escrow ID (before creation)
|
|
674
|
+
* Uses CREATE2 address computation: keccak256(0xff ++ deployer ++ salt ++ initCodeHash)
|
|
647
675
|
*/
|
|
648
676
|
async predictWalletAddress(escrowId) {
|
|
649
|
-
//
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
677
|
+
// Salt is keccak256 of the escrowId padded to 32 bytes
|
|
678
|
+
const salt = (0, viem_1.keccak256)((0, viem_1.encodeAbiParameters)([{ type: "uint256" }], [escrowId]));
|
|
679
|
+
// Get wallet bytecode from the ABI JSON
|
|
680
|
+
const walletBytecode = PalindromePayWallet_json_1.default.bytecode;
|
|
681
|
+
// Encode constructor arguments: (address _escrowContract, uint256 _escrowId)
|
|
682
|
+
const encodedArgs = (0, viem_1.encodeAbiParameters)([{ type: "address" }, { type: "uint256" }], [this.contractAddress, escrowId]);
|
|
683
|
+
// initCode = bytecode + encoded constructor args
|
|
684
|
+
const initCode = (0, viem_1.concat)([walletBytecode, encodedArgs]);
|
|
685
|
+
const initCodeHash = (0, viem_1.keccak256)(initCode);
|
|
686
|
+
// CREATE2 address: keccak256(0xff ++ deployer ++ salt ++ initCodeHash)[12:]
|
|
687
|
+
const data = (0, viem_1.concat)([
|
|
688
|
+
"0xff",
|
|
689
|
+
this.contractAddress,
|
|
690
|
+
salt,
|
|
691
|
+
initCodeHash,
|
|
692
|
+
]);
|
|
693
|
+
const hash = (0, viem_1.keccak256)(data);
|
|
694
|
+
// Take the last 20 bytes (address is derived from bytes 12-31)
|
|
695
|
+
return (0, viem_1.getAddress)(`0x${hash.slice(26)}`);
|
|
658
696
|
}
|
|
659
697
|
// ==========================================================================
|
|
660
698
|
// ESCROW DATA READING
|
|
@@ -1045,6 +1083,11 @@ class PalindromePaySDK {
|
|
|
1045
1083
|
const predictedWallet = await this.predictWalletAddress(nextId);
|
|
1046
1084
|
// Sign wallet authorization
|
|
1047
1085
|
const sellerWalletSig = await this.signWalletAuthorization(walletClient, predictedWallet, nextId);
|
|
1086
|
+
// Pre-validate signature before submitting transaction
|
|
1087
|
+
const isValidSig = await this.verifyWalletSignature(sellerWalletSig, predictedWallet, nextId, walletClient.account.address);
|
|
1088
|
+
if (!isValidSig) {
|
|
1089
|
+
throw new SDKError("Seller wallet signature is invalid - cannot create escrow", SDKErrorCode.SIGNATURE_INVALID);
|
|
1090
|
+
}
|
|
1048
1091
|
// Create escrow
|
|
1049
1092
|
const hash = await this.resilientWriteContract(walletClient, {
|
|
1050
1093
|
address: this.contractAddress,
|
|
@@ -1073,7 +1116,30 @@ class PalindromePaySDK {
|
|
|
1073
1116
|
});
|
|
1074
1117
|
const escrowId = events[0]?.args?.escrowId ?? nextId;
|
|
1075
1118
|
const deal = await this.getEscrowByIdParsed(escrowId);
|
|
1076
|
-
|
|
1119
|
+
// Verify seller signature is valid on-chain after creation
|
|
1120
|
+
let sellerSigValid = false;
|
|
1121
|
+
try {
|
|
1122
|
+
sellerSigValid = await this.publicClient.readContract({
|
|
1123
|
+
address: deal.wallet,
|
|
1124
|
+
abi: this.abiWallet,
|
|
1125
|
+
functionName: "isSignatureValid",
|
|
1126
|
+
args: [walletClient.account.address],
|
|
1127
|
+
});
|
|
1128
|
+
}
|
|
1129
|
+
catch (error) {
|
|
1130
|
+
this.log('warn', 'Failed to verify seller signature after escrow creation', {
|
|
1131
|
+
escrowId: escrowId.toString(),
|
|
1132
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
if (!sellerSigValid) {
|
|
1136
|
+
this.log('error', 'Seller wallet signature is invalid after escrow creation', {
|
|
1137
|
+
escrowId: escrowId.toString(),
|
|
1138
|
+
seller: walletClient.account.address,
|
|
1139
|
+
wallet: deal.wallet,
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
1142
|
+
return { escrowId, txHash: hash, walletAddress: deal.wallet, signatureValid: sellerSigValid };
|
|
1077
1143
|
}
|
|
1078
1144
|
/**
|
|
1079
1145
|
* Create a new escrow and deposit funds as the buyer (single transaction)
|
|
@@ -1136,6 +1202,11 @@ class PalindromePaySDK {
|
|
|
1136
1202
|
const predictedWallet = await this.predictWalletAddress(nextId);
|
|
1137
1203
|
// Sign wallet authorization
|
|
1138
1204
|
const buyerWalletSig = await this.signWalletAuthorization(walletClient, predictedWallet, nextId);
|
|
1205
|
+
// Pre-validate signature before submitting transaction
|
|
1206
|
+
const isValidSig = await this.verifyWalletSignature(buyerWalletSig, predictedWallet, nextId, walletClient.account.address);
|
|
1207
|
+
if (!isValidSig) {
|
|
1208
|
+
throw new SDKError("Buyer wallet signature is invalid - cannot create escrow", SDKErrorCode.SIGNATURE_INVALID);
|
|
1209
|
+
}
|
|
1139
1210
|
// Create escrow and deposit
|
|
1140
1211
|
const hash = await this.resilientWriteContract(walletClient, {
|
|
1141
1212
|
address: this.contractAddress,
|
|
@@ -1164,7 +1235,30 @@ class PalindromePaySDK {
|
|
|
1164
1235
|
});
|
|
1165
1236
|
const escrowId = events[0]?.args?.escrowId ?? nextId;
|
|
1166
1237
|
const deal = await this.getEscrowByIdParsed(escrowId);
|
|
1167
|
-
|
|
1238
|
+
// Verify buyer signature is valid on-chain after creation
|
|
1239
|
+
let buyerSigValid = false;
|
|
1240
|
+
try {
|
|
1241
|
+
buyerSigValid = await this.publicClient.readContract({
|
|
1242
|
+
address: deal.wallet,
|
|
1243
|
+
abi: this.abiWallet,
|
|
1244
|
+
functionName: "isSignatureValid",
|
|
1245
|
+
args: [walletClient.account.address],
|
|
1246
|
+
});
|
|
1247
|
+
}
|
|
1248
|
+
catch (error) {
|
|
1249
|
+
this.log('warn', 'Failed to verify buyer signature after escrow creation', {
|
|
1250
|
+
escrowId: escrowId.toString(),
|
|
1251
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1252
|
+
});
|
|
1253
|
+
}
|
|
1254
|
+
if (!buyerSigValid) {
|
|
1255
|
+
this.log('error', 'Buyer wallet signature is invalid after escrow creation', {
|
|
1256
|
+
escrowId: escrowId.toString(),
|
|
1257
|
+
buyer: walletClient.account.address,
|
|
1258
|
+
wallet: deal.wallet,
|
|
1259
|
+
});
|
|
1260
|
+
}
|
|
1261
|
+
return { escrowId, txHash: hash, walletAddress: deal.wallet, signatureValid: buyerSigValid };
|
|
1168
1262
|
}
|
|
1169
1263
|
// ==========================================================================
|
|
1170
1264
|
// DEPOSIT
|
|
@@ -1181,7 +1275,7 @@ class PalindromePaySDK {
|
|
|
1181
1275
|
*
|
|
1182
1276
|
* @param walletClient - The buyer's wallet client (must have account connected)
|
|
1183
1277
|
* @param escrowId - The escrow ID to deposit into
|
|
1184
|
-
* @returns
|
|
1278
|
+
* @returns Object containing transaction hash and signature validity
|
|
1185
1279
|
* @throws {SDKError} WALLET_NOT_CONNECTED - If wallet client is not connected
|
|
1186
1280
|
* @throws {SDKError} NOT_BUYER - If caller is not the designated buyer
|
|
1187
1281
|
* @throws {SDKError} INVALID_STATE - If escrow is not in AWAITING_PAYMENT state
|
|
@@ -1195,8 +1289,13 @@ class PalindromePaySDK {
|
|
|
1195
1289
|
this.verifyState(deal, EscrowState.AWAITING_PAYMENT, "deposit");
|
|
1196
1290
|
// Approve token spending
|
|
1197
1291
|
await this.approveTokenIfNeeded(walletClient, deal.token, this.contractAddress, deal.amount);
|
|
1198
|
-
// Sign wallet authorization
|
|
1292
|
+
// Sign wallet authorization using the wallet address from the escrow
|
|
1199
1293
|
const buyerWalletSig = await this.signWalletAuthorization(walletClient, deal.wallet, escrowId);
|
|
1294
|
+
// Pre-validate signature before submitting transaction
|
|
1295
|
+
const isValidSig = await this.verifyWalletSignature(buyerWalletSig, deal.wallet, escrowId, walletClient.account.address);
|
|
1296
|
+
if (!isValidSig) {
|
|
1297
|
+
throw new SDKError("Buyer wallet signature is invalid - cannot deposit", SDKErrorCode.SIGNATURE_INVALID);
|
|
1298
|
+
}
|
|
1200
1299
|
// Deposit
|
|
1201
1300
|
const hash = await this.resilientWriteContract(walletClient, {
|
|
1202
1301
|
address: this.contractAddress,
|
|
@@ -1205,7 +1304,30 @@ class PalindromePaySDK {
|
|
|
1205
1304
|
args: [escrowId, buyerWalletSig],
|
|
1206
1305
|
});
|
|
1207
1306
|
await this.waitForReceipt(hash);
|
|
1208
|
-
|
|
1307
|
+
// Verify buyer signature is valid on-chain after deposit
|
|
1308
|
+
let buyerSigValid = false;
|
|
1309
|
+
try {
|
|
1310
|
+
buyerSigValid = await this.publicClient.readContract({
|
|
1311
|
+
address: deal.wallet,
|
|
1312
|
+
abi: this.abiWallet,
|
|
1313
|
+
functionName: "isSignatureValid",
|
|
1314
|
+
args: [walletClient.account.address],
|
|
1315
|
+
});
|
|
1316
|
+
}
|
|
1317
|
+
catch (error) {
|
|
1318
|
+
this.log('warn', 'Failed to verify buyer signature after deposit', {
|
|
1319
|
+
escrowId: escrowId.toString(),
|
|
1320
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1321
|
+
});
|
|
1322
|
+
}
|
|
1323
|
+
if (!buyerSigValid) {
|
|
1324
|
+
this.log('error', 'Buyer wallet signature is invalid after deposit', {
|
|
1325
|
+
escrowId: escrowId.toString(),
|
|
1326
|
+
buyer: walletClient.account.address,
|
|
1327
|
+
wallet: deal.wallet,
|
|
1328
|
+
});
|
|
1329
|
+
}
|
|
1330
|
+
return { txHash: hash, signatureValid: buyerSigValid };
|
|
1209
1331
|
}
|
|
1210
1332
|
// ==========================================================================
|
|
1211
1333
|
// ACCEPT ESCROW (for buyer-created escrows)
|
|
@@ -1221,7 +1343,7 @@ class PalindromePaySDK {
|
|
|
1221
1343
|
*
|
|
1222
1344
|
* @param walletClient - The seller's wallet client (must have account connected)
|
|
1223
1345
|
* @param escrowId - The escrow ID to accept
|
|
1224
|
-
* @returns
|
|
1346
|
+
* @returns Object containing transaction hash and signature validity
|
|
1225
1347
|
* @throws {SDKError} WALLET_NOT_CONNECTED - If wallet client is not connected
|
|
1226
1348
|
* @throws {SDKError} NOT_SELLER - If caller is not the designated seller
|
|
1227
1349
|
* @throws {SDKError} INVALID_STATE - If escrow is not in AWAITING_DELIVERY state
|
|
@@ -1237,8 +1359,13 @@ class PalindromePaySDK {
|
|
|
1237
1359
|
if (deal.sellerWalletSig && deal.sellerWalletSig !== "0x") {
|
|
1238
1360
|
throw new SDKError("Escrow already accepted", SDKErrorCode.ALREADY_ACCEPTED);
|
|
1239
1361
|
}
|
|
1240
|
-
// Sign wallet authorization
|
|
1362
|
+
// Sign wallet authorization using the wallet address from the escrow
|
|
1241
1363
|
const sellerWalletSig = await this.signWalletAuthorization(walletClient, deal.wallet, escrowId);
|
|
1364
|
+
// Pre-validate signature before submitting transaction
|
|
1365
|
+
const isValidSig = await this.verifyWalletSignature(sellerWalletSig, deal.wallet, escrowId, walletClient.account.address);
|
|
1366
|
+
if (!isValidSig) {
|
|
1367
|
+
throw new SDKError("Seller wallet signature is invalid - cannot accept escrow", SDKErrorCode.SIGNATURE_INVALID);
|
|
1368
|
+
}
|
|
1242
1369
|
// Accept escrow
|
|
1243
1370
|
const hash = await this.resilientWriteContract(walletClient, {
|
|
1244
1371
|
address: this.contractAddress,
|
|
@@ -1247,7 +1374,30 @@ class PalindromePaySDK {
|
|
|
1247
1374
|
args: [escrowId, sellerWalletSig],
|
|
1248
1375
|
});
|
|
1249
1376
|
await this.waitForReceipt(hash);
|
|
1250
|
-
|
|
1377
|
+
// Verify seller signature is valid on-chain after accept
|
|
1378
|
+
let sellerSigValid = false;
|
|
1379
|
+
try {
|
|
1380
|
+
sellerSigValid = await this.publicClient.readContract({
|
|
1381
|
+
address: deal.wallet,
|
|
1382
|
+
abi: this.abiWallet,
|
|
1383
|
+
functionName: "isSignatureValid",
|
|
1384
|
+
args: [walletClient.account.address],
|
|
1385
|
+
});
|
|
1386
|
+
}
|
|
1387
|
+
catch (error) {
|
|
1388
|
+
this.log('warn', 'Failed to verify seller signature after accept', {
|
|
1389
|
+
escrowId: escrowId.toString(),
|
|
1390
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1391
|
+
});
|
|
1392
|
+
}
|
|
1393
|
+
if (!sellerSigValid) {
|
|
1394
|
+
this.log('error', 'Seller wallet signature is invalid after accept', {
|
|
1395
|
+
escrowId: escrowId.toString(),
|
|
1396
|
+
seller: walletClient.account.address,
|
|
1397
|
+
wallet: deal.wallet,
|
|
1398
|
+
});
|
|
1399
|
+
}
|
|
1400
|
+
return { txHash: hash, signatureValid: sellerSigValid };
|
|
1251
1401
|
}
|
|
1252
1402
|
// ==========================================================================
|
|
1253
1403
|
// CONFIRM DELIVERY
|
|
@@ -1278,6 +1428,11 @@ class PalindromePaySDK {
|
|
|
1278
1428
|
this.verifyState(deal, EscrowState.AWAITING_DELIVERY, "confirm delivery");
|
|
1279
1429
|
// Sign wallet authorization
|
|
1280
1430
|
const buyerWalletSig = await this.signWalletAuthorization(walletClient, deal.wallet, escrowId);
|
|
1431
|
+
// Pre-validate signature before submitting transaction
|
|
1432
|
+
const isValidSig = await this.verifyWalletSignature(buyerWalletSig, deal.wallet, escrowId, walletClient.account.address);
|
|
1433
|
+
if (!isValidSig) {
|
|
1434
|
+
throw new SDKError("Buyer wallet signature is invalid - cannot confirm delivery", SDKErrorCode.SIGNATURE_INVALID);
|
|
1435
|
+
}
|
|
1281
1436
|
// Confirm delivery
|
|
1282
1437
|
const hash = await this.resilientWriteContract(walletClient, {
|
|
1283
1438
|
address: this.contractAddress,
|
|
@@ -1389,6 +1544,11 @@ class PalindromePaySDK {
|
|
|
1389
1544
|
}
|
|
1390
1545
|
// Sign wallet authorization
|
|
1391
1546
|
const walletSig = await this.signWalletAuthorization(walletClient, deal.wallet, escrowId);
|
|
1547
|
+
// Pre-validate signature before submitting transaction
|
|
1548
|
+
const isValidSig = await this.verifyWalletSignature(walletSig, deal.wallet, escrowId, walletClient.account.address);
|
|
1549
|
+
if (!isValidSig) {
|
|
1550
|
+
throw new SDKError("Wallet signature is invalid - cannot request cancel", SDKErrorCode.SIGNATURE_INVALID);
|
|
1551
|
+
}
|
|
1392
1552
|
// Request cancel
|
|
1393
1553
|
const hash = await this.resilientWriteContract(walletClient, {
|
|
1394
1554
|
address: this.contractAddress,
|
|
@@ -1626,6 +1786,11 @@ class PalindromePaySDK {
|
|
|
1626
1786
|
this.verifyArbiter(walletClient.account.address, deal);
|
|
1627
1787
|
// Sign wallet authorization
|
|
1628
1788
|
const arbiterWalletSig = await this.signWalletAuthorization(walletClient, deal.wallet, escrowId);
|
|
1789
|
+
// Pre-validate signature before submitting transaction
|
|
1790
|
+
const isValidSig = await this.verifyWalletSignature(arbiterWalletSig, deal.wallet, escrowId, walletClient.account.address);
|
|
1791
|
+
if (!isValidSig) {
|
|
1792
|
+
throw new SDKError("Arbiter wallet signature is invalid - cannot submit decision", SDKErrorCode.SIGNATURE_INVALID);
|
|
1793
|
+
}
|
|
1629
1794
|
// Submit decision
|
|
1630
1795
|
const hash = await this.resilientWriteContract(walletClient, {
|
|
1631
1796
|
address: this.contractAddress,
|