@palindromepay/sdk 1.9.9 → 2.0.1
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.
|
@@ -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
|
+
* Calls the contract's computeWalletAddress function - single source of truth
|
|
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,16 @@ class PalindromePaySDK {
|
|
|
644
671
|
// ==========================================================================
|
|
645
672
|
/**
|
|
646
673
|
* Predict the wallet address for a given escrow ID (before creation)
|
|
674
|
+
* Calls the contract's computeWalletAddress function - single source of truth
|
|
647
675
|
*/
|
|
648
676
|
async predictWalletAddress(escrowId) {
|
|
649
|
-
|
|
650
|
-
// This ensures the SDK always matches the contract's CREATE2 computation
|
|
651
|
-
const walletAddress = await this.publicClient.readContract({
|
|
677
|
+
const predicted = await (0, actions_1.readContract)(this.publicClient, {
|
|
652
678
|
address: this.contractAddress,
|
|
653
|
-
abi:
|
|
679
|
+
abi: PalindromePay_json_1.default.abi,
|
|
654
680
|
functionName: "computeWalletAddress",
|
|
655
681
|
args: [escrowId],
|
|
656
682
|
});
|
|
657
|
-
return
|
|
683
|
+
return predicted;
|
|
658
684
|
}
|
|
659
685
|
// ==========================================================================
|
|
660
686
|
// ESCROW DATA READING
|
|
@@ -1045,6 +1071,11 @@ class PalindromePaySDK {
|
|
|
1045
1071
|
const predictedWallet = await this.predictWalletAddress(nextId);
|
|
1046
1072
|
// Sign wallet authorization
|
|
1047
1073
|
const sellerWalletSig = await this.signWalletAuthorization(walletClient, predictedWallet, nextId);
|
|
1074
|
+
// Pre-validate signature before submitting transaction
|
|
1075
|
+
const isValidSig = await this.verifyWalletSignature(sellerWalletSig, predictedWallet, nextId, walletClient.account.address);
|
|
1076
|
+
if (!isValidSig) {
|
|
1077
|
+
throw new SDKError("Seller wallet signature is invalid - cannot create escrow", SDKErrorCode.SIGNATURE_INVALID);
|
|
1078
|
+
}
|
|
1048
1079
|
// Create escrow
|
|
1049
1080
|
const hash = await this.resilientWriteContract(walletClient, {
|
|
1050
1081
|
address: this.contractAddress,
|
|
@@ -1073,7 +1104,30 @@ class PalindromePaySDK {
|
|
|
1073
1104
|
});
|
|
1074
1105
|
const escrowId = events[0]?.args?.escrowId ?? nextId;
|
|
1075
1106
|
const deal = await this.getEscrowByIdParsed(escrowId);
|
|
1076
|
-
|
|
1107
|
+
// Verify seller signature is valid on-chain after creation
|
|
1108
|
+
let sellerSigValid = false;
|
|
1109
|
+
try {
|
|
1110
|
+
sellerSigValid = await this.publicClient.readContract({
|
|
1111
|
+
address: deal.wallet,
|
|
1112
|
+
abi: this.abiWallet,
|
|
1113
|
+
functionName: "isSignatureValid",
|
|
1114
|
+
args: [walletClient.account.address],
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
1117
|
+
catch (error) {
|
|
1118
|
+
this.log('warn', 'Failed to verify seller signature after escrow creation', {
|
|
1119
|
+
escrowId: escrowId.toString(),
|
|
1120
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1121
|
+
});
|
|
1122
|
+
}
|
|
1123
|
+
if (!sellerSigValid) {
|
|
1124
|
+
this.log('error', 'Seller wallet signature is invalid after escrow creation', {
|
|
1125
|
+
escrowId: escrowId.toString(),
|
|
1126
|
+
seller: walletClient.account.address,
|
|
1127
|
+
wallet: deal.wallet,
|
|
1128
|
+
});
|
|
1129
|
+
}
|
|
1130
|
+
return { escrowId, txHash: hash, walletAddress: deal.wallet, signatureValid: sellerSigValid };
|
|
1077
1131
|
}
|
|
1078
1132
|
/**
|
|
1079
1133
|
* Create a new escrow and deposit funds as the buyer (single transaction)
|
|
@@ -1136,6 +1190,11 @@ class PalindromePaySDK {
|
|
|
1136
1190
|
const predictedWallet = await this.predictWalletAddress(nextId);
|
|
1137
1191
|
// Sign wallet authorization
|
|
1138
1192
|
const buyerWalletSig = await this.signWalletAuthorization(walletClient, predictedWallet, nextId);
|
|
1193
|
+
// Pre-validate signature before submitting transaction
|
|
1194
|
+
const isValidSig = await this.verifyWalletSignature(buyerWalletSig, predictedWallet, nextId, walletClient.account.address);
|
|
1195
|
+
if (!isValidSig) {
|
|
1196
|
+
throw new SDKError("Buyer wallet signature is invalid - cannot create escrow", SDKErrorCode.SIGNATURE_INVALID);
|
|
1197
|
+
}
|
|
1139
1198
|
// Create escrow and deposit
|
|
1140
1199
|
const hash = await this.resilientWriteContract(walletClient, {
|
|
1141
1200
|
address: this.contractAddress,
|
|
@@ -1164,7 +1223,30 @@ class PalindromePaySDK {
|
|
|
1164
1223
|
});
|
|
1165
1224
|
const escrowId = events[0]?.args?.escrowId ?? nextId;
|
|
1166
1225
|
const deal = await this.getEscrowByIdParsed(escrowId);
|
|
1167
|
-
|
|
1226
|
+
// Verify buyer signature is valid on-chain after creation
|
|
1227
|
+
let buyerSigValid = false;
|
|
1228
|
+
try {
|
|
1229
|
+
buyerSigValid = await this.publicClient.readContract({
|
|
1230
|
+
address: deal.wallet,
|
|
1231
|
+
abi: this.abiWallet,
|
|
1232
|
+
functionName: "isSignatureValid",
|
|
1233
|
+
args: [walletClient.account.address],
|
|
1234
|
+
});
|
|
1235
|
+
}
|
|
1236
|
+
catch (error) {
|
|
1237
|
+
this.log('warn', 'Failed to verify buyer signature after escrow creation', {
|
|
1238
|
+
escrowId: escrowId.toString(),
|
|
1239
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1240
|
+
});
|
|
1241
|
+
}
|
|
1242
|
+
if (!buyerSigValid) {
|
|
1243
|
+
this.log('error', 'Buyer wallet signature is invalid after escrow creation', {
|
|
1244
|
+
escrowId: escrowId.toString(),
|
|
1245
|
+
buyer: walletClient.account.address,
|
|
1246
|
+
wallet: deal.wallet,
|
|
1247
|
+
});
|
|
1248
|
+
}
|
|
1249
|
+
return { escrowId, txHash: hash, walletAddress: deal.wallet, signatureValid: buyerSigValid };
|
|
1168
1250
|
}
|
|
1169
1251
|
// ==========================================================================
|
|
1170
1252
|
// DEPOSIT
|
|
@@ -1181,7 +1263,7 @@ class PalindromePaySDK {
|
|
|
1181
1263
|
*
|
|
1182
1264
|
* @param walletClient - The buyer's wallet client (must have account connected)
|
|
1183
1265
|
* @param escrowId - The escrow ID to deposit into
|
|
1184
|
-
* @returns
|
|
1266
|
+
* @returns Object containing transaction hash and signature validity
|
|
1185
1267
|
* @throws {SDKError} WALLET_NOT_CONNECTED - If wallet client is not connected
|
|
1186
1268
|
* @throws {SDKError} NOT_BUYER - If caller is not the designated buyer
|
|
1187
1269
|
* @throws {SDKError} INVALID_STATE - If escrow is not in AWAITING_PAYMENT state
|
|
@@ -1195,8 +1277,13 @@ class PalindromePaySDK {
|
|
|
1195
1277
|
this.verifyState(deal, EscrowState.AWAITING_PAYMENT, "deposit");
|
|
1196
1278
|
// Approve token spending
|
|
1197
1279
|
await this.approveTokenIfNeeded(walletClient, deal.token, this.contractAddress, deal.amount);
|
|
1198
|
-
// Sign wallet authorization
|
|
1280
|
+
// Sign wallet authorization using the wallet address from the escrow
|
|
1199
1281
|
const buyerWalletSig = await this.signWalletAuthorization(walletClient, deal.wallet, escrowId);
|
|
1282
|
+
// Pre-validate signature before submitting transaction
|
|
1283
|
+
const isValidSig = await this.verifyWalletSignature(buyerWalletSig, deal.wallet, escrowId, walletClient.account.address);
|
|
1284
|
+
if (!isValidSig) {
|
|
1285
|
+
throw new SDKError("Buyer wallet signature is invalid - cannot deposit", SDKErrorCode.SIGNATURE_INVALID);
|
|
1286
|
+
}
|
|
1200
1287
|
// Deposit
|
|
1201
1288
|
const hash = await this.resilientWriteContract(walletClient, {
|
|
1202
1289
|
address: this.contractAddress,
|
|
@@ -1205,7 +1292,30 @@ class PalindromePaySDK {
|
|
|
1205
1292
|
args: [escrowId, buyerWalletSig],
|
|
1206
1293
|
});
|
|
1207
1294
|
await this.waitForReceipt(hash);
|
|
1208
|
-
|
|
1295
|
+
// Verify buyer signature is valid on-chain after deposit
|
|
1296
|
+
let buyerSigValid = false;
|
|
1297
|
+
try {
|
|
1298
|
+
buyerSigValid = await this.publicClient.readContract({
|
|
1299
|
+
address: deal.wallet,
|
|
1300
|
+
abi: this.abiWallet,
|
|
1301
|
+
functionName: "isSignatureValid",
|
|
1302
|
+
args: [walletClient.account.address],
|
|
1303
|
+
});
|
|
1304
|
+
}
|
|
1305
|
+
catch (error) {
|
|
1306
|
+
this.log('warn', 'Failed to verify buyer signature after deposit', {
|
|
1307
|
+
escrowId: escrowId.toString(),
|
|
1308
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1309
|
+
});
|
|
1310
|
+
}
|
|
1311
|
+
if (!buyerSigValid) {
|
|
1312
|
+
this.log('error', 'Buyer wallet signature is invalid after deposit', {
|
|
1313
|
+
escrowId: escrowId.toString(),
|
|
1314
|
+
buyer: walletClient.account.address,
|
|
1315
|
+
wallet: deal.wallet,
|
|
1316
|
+
});
|
|
1317
|
+
}
|
|
1318
|
+
return { txHash: hash, signatureValid: buyerSigValid };
|
|
1209
1319
|
}
|
|
1210
1320
|
// ==========================================================================
|
|
1211
1321
|
// ACCEPT ESCROW (for buyer-created escrows)
|
|
@@ -1221,7 +1331,7 @@ class PalindromePaySDK {
|
|
|
1221
1331
|
*
|
|
1222
1332
|
* @param walletClient - The seller's wallet client (must have account connected)
|
|
1223
1333
|
* @param escrowId - The escrow ID to accept
|
|
1224
|
-
* @returns
|
|
1334
|
+
* @returns Object containing transaction hash and signature validity
|
|
1225
1335
|
* @throws {SDKError} WALLET_NOT_CONNECTED - If wallet client is not connected
|
|
1226
1336
|
* @throws {SDKError} NOT_SELLER - If caller is not the designated seller
|
|
1227
1337
|
* @throws {SDKError} INVALID_STATE - If escrow is not in AWAITING_DELIVERY state
|
|
@@ -1237,8 +1347,13 @@ class PalindromePaySDK {
|
|
|
1237
1347
|
if (deal.sellerWalletSig && deal.sellerWalletSig !== "0x") {
|
|
1238
1348
|
throw new SDKError("Escrow already accepted", SDKErrorCode.ALREADY_ACCEPTED);
|
|
1239
1349
|
}
|
|
1240
|
-
// Sign wallet authorization
|
|
1350
|
+
// Sign wallet authorization using the wallet address from the escrow
|
|
1241
1351
|
const sellerWalletSig = await this.signWalletAuthorization(walletClient, deal.wallet, escrowId);
|
|
1352
|
+
// Pre-validate signature before submitting transaction
|
|
1353
|
+
const isValidSig = await this.verifyWalletSignature(sellerWalletSig, deal.wallet, escrowId, walletClient.account.address);
|
|
1354
|
+
if (!isValidSig) {
|
|
1355
|
+
throw new SDKError("Seller wallet signature is invalid - cannot accept escrow", SDKErrorCode.SIGNATURE_INVALID);
|
|
1356
|
+
}
|
|
1242
1357
|
// Accept escrow
|
|
1243
1358
|
const hash = await this.resilientWriteContract(walletClient, {
|
|
1244
1359
|
address: this.contractAddress,
|
|
@@ -1247,7 +1362,30 @@ class PalindromePaySDK {
|
|
|
1247
1362
|
args: [escrowId, sellerWalletSig],
|
|
1248
1363
|
});
|
|
1249
1364
|
await this.waitForReceipt(hash);
|
|
1250
|
-
|
|
1365
|
+
// Verify seller signature is valid on-chain after accept
|
|
1366
|
+
let sellerSigValid = false;
|
|
1367
|
+
try {
|
|
1368
|
+
sellerSigValid = await this.publicClient.readContract({
|
|
1369
|
+
address: deal.wallet,
|
|
1370
|
+
abi: this.abiWallet,
|
|
1371
|
+
functionName: "isSignatureValid",
|
|
1372
|
+
args: [walletClient.account.address],
|
|
1373
|
+
});
|
|
1374
|
+
}
|
|
1375
|
+
catch (error) {
|
|
1376
|
+
this.log('warn', 'Failed to verify seller signature after accept', {
|
|
1377
|
+
escrowId: escrowId.toString(),
|
|
1378
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1379
|
+
});
|
|
1380
|
+
}
|
|
1381
|
+
if (!sellerSigValid) {
|
|
1382
|
+
this.log('error', 'Seller wallet signature is invalid after accept', {
|
|
1383
|
+
escrowId: escrowId.toString(),
|
|
1384
|
+
seller: walletClient.account.address,
|
|
1385
|
+
wallet: deal.wallet,
|
|
1386
|
+
});
|
|
1387
|
+
}
|
|
1388
|
+
return { txHash: hash, signatureValid: sellerSigValid };
|
|
1251
1389
|
}
|
|
1252
1390
|
// ==========================================================================
|
|
1253
1391
|
// CONFIRM DELIVERY
|
|
@@ -1278,6 +1416,11 @@ class PalindromePaySDK {
|
|
|
1278
1416
|
this.verifyState(deal, EscrowState.AWAITING_DELIVERY, "confirm delivery");
|
|
1279
1417
|
// Sign wallet authorization
|
|
1280
1418
|
const buyerWalletSig = await this.signWalletAuthorization(walletClient, deal.wallet, escrowId);
|
|
1419
|
+
// Pre-validate signature before submitting transaction
|
|
1420
|
+
const isValidSig = await this.verifyWalletSignature(buyerWalletSig, deal.wallet, escrowId, walletClient.account.address);
|
|
1421
|
+
if (!isValidSig) {
|
|
1422
|
+
throw new SDKError("Buyer wallet signature is invalid - cannot confirm delivery", SDKErrorCode.SIGNATURE_INVALID);
|
|
1423
|
+
}
|
|
1281
1424
|
// Confirm delivery
|
|
1282
1425
|
const hash = await this.resilientWriteContract(walletClient, {
|
|
1283
1426
|
address: this.contractAddress,
|
|
@@ -1389,6 +1532,11 @@ class PalindromePaySDK {
|
|
|
1389
1532
|
}
|
|
1390
1533
|
// Sign wallet authorization
|
|
1391
1534
|
const walletSig = await this.signWalletAuthorization(walletClient, deal.wallet, escrowId);
|
|
1535
|
+
// Pre-validate signature before submitting transaction
|
|
1536
|
+
const isValidSig = await this.verifyWalletSignature(walletSig, deal.wallet, escrowId, walletClient.account.address);
|
|
1537
|
+
if (!isValidSig) {
|
|
1538
|
+
throw new SDKError("Wallet signature is invalid - cannot request cancel", SDKErrorCode.SIGNATURE_INVALID);
|
|
1539
|
+
}
|
|
1392
1540
|
// Request cancel
|
|
1393
1541
|
const hash = await this.resilientWriteContract(walletClient, {
|
|
1394
1542
|
address: this.contractAddress,
|
|
@@ -1626,6 +1774,11 @@ class PalindromePaySDK {
|
|
|
1626
1774
|
this.verifyArbiter(walletClient.account.address, deal);
|
|
1627
1775
|
// Sign wallet authorization
|
|
1628
1776
|
const arbiterWalletSig = await this.signWalletAuthorization(walletClient, deal.wallet, escrowId);
|
|
1777
|
+
// Pre-validate signature before submitting transaction
|
|
1778
|
+
const isValidSig = await this.verifyWalletSignature(arbiterWalletSig, deal.wallet, escrowId, walletClient.account.address);
|
|
1779
|
+
if (!isValidSig) {
|
|
1780
|
+
throw new SDKError("Arbiter wallet signature is invalid - cannot submit decision", SDKErrorCode.SIGNATURE_INVALID);
|
|
1781
|
+
}
|
|
1629
1782
|
// Submit decision
|
|
1630
1783
|
const hash = await this.resilientWriteContract(walletClient, {
|
|
1631
1784
|
address: this.contractAddress,
|