@dynamic-labs-wallet/browser-wallet-client 1.1.40 → 1.1.41
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/index.cjs +52 -13
- package/index.esm.js +52 -13
- package/package.json +2 -2
- package/src/assertPreparedSigningIntentMatchesRequest.d.ts.map +1 -1
package/index.cjs
CHANGED
|
@@ -2339,31 +2339,70 @@ const limitKeys = [
|
|
|
2339
2339
|
'maxPriorityFeePerGas',
|
|
2340
2340
|
'maxTotalFee'
|
|
2341
2341
|
];
|
|
2342
|
+
const isHex = (value)=>typeof value === 'string' && /^0x(?:[0-9a-f]{2})*$/.test(value);
|
|
2343
|
+
const isSvmTransactionIntent = (intent)=>intent.operation.kind === 'transaction' && intent.operation.chainName === 'SVM';
|
|
2344
|
+
const isEvmTransactionIntent = (intent)=>intent.operation.kind === 'transaction' && intent.operation.chainName === 'EVM';
|
|
2342
2345
|
const assertMatches = (matches, message)=>{
|
|
2343
2346
|
if (!matches) throw new Error(message);
|
|
2344
2347
|
};
|
|
2345
|
-
const
|
|
2348
|
+
const hasLifetime = (lifetime, refreshable)=>{
|
|
2349
|
+
if (refreshable === undefined) return lifetime === undefined;
|
|
2350
|
+
const keys = lifetime && typeof lifetime === 'object' ? Object.keys(lifetime) : [];
|
|
2351
|
+
return keys.length === 1 && lifetime.refreshable === refreshable;
|
|
2352
|
+
};
|
|
2353
|
+
const hasMatchingMetadata = (intent, request)=>{
|
|
2346
2354
|
const sameAddress = request.chainName === 'EVM' ? intent.accountAddress.toLowerCase() === request.accountAddress.toLowerCase() : intent.accountAddress === request.accountAddress;
|
|
2347
|
-
|
|
2355
|
+
return Object.values(core.WaasChainEnum).includes(request.chainName) && intent.actionType === 'waasSigningQuorumApprove' && Boolean(intent.intentId) && Number.isFinite(Date.parse(intent.createdAt)) && sameAddress && intent.businessAccountId === request.businessAccountId && intent.initiatorUserId === request.initiatorUserId && intent.completeBy === request.completeBy && intent.operation.chainName === request.chainName && intent.operation.kind === request.kind;
|
|
2356
|
+
};
|
|
2357
|
+
const hasValidSvmHeader = (intent)=>{
|
|
2358
|
+
const { header, staticAccountKeys } = intent.operation;
|
|
2359
|
+
return Number.isInteger(header.numRequiredSignatures) && header.numRequiredSignatures >= 1 && header.numRequiredSignatures <= staticAccountKeys.length && Number.isInteger(header.numReadonlySignedAccounts) && header.numReadonlySignedAccounts >= 0 && header.numReadonlySignedAccounts < header.numRequiredSignatures && Number.isInteger(header.numReadonlyUnsignedAccounts) && header.numReadonlyUnsignedAccounts >= 0 && header.numReadonlyUnsignedAccounts <= staticAccountKeys.length - header.numRequiredSignatures;
|
|
2360
|
+
};
|
|
2361
|
+
const hasValidSvmInstructions = (intent)=>{
|
|
2362
|
+
const { instructions, staticAccountKeys } = intent.operation;
|
|
2363
|
+
const isIndex = (value)=>Number.isInteger(value) && value >= 0 && value < staticAccountKeys.length;
|
|
2364
|
+
return instructions.every((instruction)=>isIndex(instruction.programIdIndex) && instruction.accountKeyIndexes.every(isIndex) && isHex(instruction.data));
|
|
2365
|
+
};
|
|
2366
|
+
const assertSvmTransactionMatchesRequest = (intent, request)=>{
|
|
2367
|
+
var _request_chainId;
|
|
2368
|
+
const { operation } = intent;
|
|
2369
|
+
const isBase58 = (value)=>/^[1-9A-HJ-NP-Za-km-z]+$/.test(value);
|
|
2370
|
+
assertMatches(request.chainName === 'SVM' && Boolean(request.chainId) && ((_request_chainId = request.chainId) == null ? void 0 : _request_chainId.trim()) === request.chainId && operation.chainId === request.chainId && request.refreshLimits === undefined && !request.refreshableNonce && intent.limits === undefined && hasLifetime(intent.lifetime, 'blockhash') && (operation.messageVersion === 'legacy' || operation.messageVersion === 'v0') && operation.staticAccountKeys.length > 0 && operation.staticAccountKeys.every(isBase58) && operation.feePayer === request.accountAddress && operation.feePayer === operation.staticAccountKeys[0] && hasValidSvmHeader(intent) && hasValidSvmInstructions(intent), 'Prepared SVM transaction signing intent is malformed');
|
|
2371
|
+
};
|
|
2372
|
+
const assertEvmTransactionMatchesRequest = (intent, request)=>{
|
|
2373
|
+
if (request.chainName !== 'EVM') throw new Error('Unsupported transaction signing intent');
|
|
2374
|
+
const { operation, limits } = intent;
|
|
2375
|
+
if (!limits) throw new Error('Prepared transaction signing intent is malformed');
|
|
2376
|
+
assertMatches(hasLifetime(intent.lifetime, request.refreshableNonce ? 'nonce' : undefined), 'Transaction lifetime does not match request');
|
|
2377
|
+
assertMatches(operation.from === intent.accountAddress.toLowerCase(), 'Transaction signer does not match request');
|
|
2378
|
+
assertMatches(!request.chainId || operation.chainId === request.chainId, 'Transaction chain does not match request');
|
|
2379
|
+
assertMatches(!request.refreshLimits || limitKeys.every((key)=>{
|
|
2380
|
+
var _request_refreshLimits;
|
|
2381
|
+
return limits[key] === ((_request_refreshLimits = request.refreshLimits) == null ? void 0 : _request_refreshLimits[key]);
|
|
2382
|
+
}), 'Transaction signing limits do not match request');
|
|
2383
|
+
// Wallet-service parses the transaction it signs and rejects any mismatch with
|
|
2384
|
+
// the approved operation, so the transaction fields are not re-derived here.
|
|
2385
|
+
};
|
|
2386
|
+
const assertPreparedSigningIntentMatchesRequest = ({ intent, request, preparedPayload })=>{
|
|
2387
|
+
assertMatches(hasMatchingMetadata(intent, request), 'Prepared signing intent does not match request');
|
|
2348
2388
|
if (intent.operation.kind === 'transaction') {
|
|
2349
|
-
if (request.kind !== 'transaction'
|
|
2389
|
+
if (request.kind !== 'transaction') {
|
|
2390
|
+
throw new Error('Unsupported transaction signing intent');
|
|
2391
|
+
}
|
|
2392
|
+
if (isSvmTransactionIntent(intent)) {
|
|
2393
|
+
assertSvmTransactionMatchesRequest(intent, request);
|
|
2394
|
+
return;
|
|
2395
|
+
}
|
|
2396
|
+
if (!isEvmTransactionIntent(intent)) {
|
|
2350
2397
|
throw new Error('Unsupported transaction signing intent');
|
|
2351
2398
|
}
|
|
2352
|
-
|
|
2353
|
-
if (!limits) throw new Error('Prepared transaction signing intent is malformed');
|
|
2354
|
-
assertMatches(operation.from === intent.accountAddress.toLowerCase(), 'Transaction signer does not match request');
|
|
2355
|
-
assertMatches(!request.chainId || operation.chainId === request.chainId, 'Transaction chain does not match request');
|
|
2356
|
-
assertMatches(!request.refreshLimits || limitKeys.every((key)=>{
|
|
2357
|
-
var _request_refreshLimits;
|
|
2358
|
-
return limits[key] === ((_request_refreshLimits = request.refreshLimits) == null ? void 0 : _request_refreshLimits[key]);
|
|
2359
|
-
}), 'Transaction signing limits do not match request');
|
|
2360
|
-
// Wallet-service parses the transaction it signs and rejects any mismatch with
|
|
2361
|
-
// the approved operation, so the transaction fields are not re-derived here.
|
|
2399
|
+
assertEvmTransactionMatchesRequest(intent, request);
|
|
2362
2400
|
return;
|
|
2363
2401
|
}
|
|
2364
2402
|
const { operation } = intent;
|
|
2365
2403
|
assertMatches(preparedPayload !== undefined && operation.payload === preparedPayload, 'Prepared signing intent payload does not match request');
|
|
2366
2404
|
assertMatches(intent.limits === undefined, 'Exact signing intent cannot include refresh limits');
|
|
2405
|
+
assertMatches(hasLifetime(intent.lifetime, undefined), 'Exact signing intent cannot include a lifetime');
|
|
2367
2406
|
if (operation.kind === 'message') {
|
|
2368
2407
|
assertMatches(request.kind === 'message' && request.chainName !== 'TRON' && operation.message === request.message, 'Prepared signing intent message does not match request');
|
|
2369
2408
|
return;
|
package/index.esm.js
CHANGED
|
@@ -2338,31 +2338,70 @@ const limitKeys = [
|
|
|
2338
2338
|
'maxPriorityFeePerGas',
|
|
2339
2339
|
'maxTotalFee'
|
|
2340
2340
|
];
|
|
2341
|
+
const isHex = (value)=>typeof value === 'string' && /^0x(?:[0-9a-f]{2})*$/.test(value);
|
|
2342
|
+
const isSvmTransactionIntent = (intent)=>intent.operation.kind === 'transaction' && intent.operation.chainName === 'SVM';
|
|
2343
|
+
const isEvmTransactionIntent = (intent)=>intent.operation.kind === 'transaction' && intent.operation.chainName === 'EVM';
|
|
2341
2344
|
const assertMatches = (matches, message)=>{
|
|
2342
2345
|
if (!matches) throw new Error(message);
|
|
2343
2346
|
};
|
|
2344
|
-
const
|
|
2347
|
+
const hasLifetime = (lifetime, refreshable)=>{
|
|
2348
|
+
if (refreshable === undefined) return lifetime === undefined;
|
|
2349
|
+
const keys = lifetime && typeof lifetime === 'object' ? Object.keys(lifetime) : [];
|
|
2350
|
+
return keys.length === 1 && lifetime.refreshable === refreshable;
|
|
2351
|
+
};
|
|
2352
|
+
const hasMatchingMetadata = (intent, request)=>{
|
|
2345
2353
|
const sameAddress = request.chainName === 'EVM' ? intent.accountAddress.toLowerCase() === request.accountAddress.toLowerCase() : intent.accountAddress === request.accountAddress;
|
|
2346
|
-
|
|
2354
|
+
return Object.values(WaasChainEnum).includes(request.chainName) && intent.actionType === 'waasSigningQuorumApprove' && Boolean(intent.intentId) && Number.isFinite(Date.parse(intent.createdAt)) && sameAddress && intent.businessAccountId === request.businessAccountId && intent.initiatorUserId === request.initiatorUserId && intent.completeBy === request.completeBy && intent.operation.chainName === request.chainName && intent.operation.kind === request.kind;
|
|
2355
|
+
};
|
|
2356
|
+
const hasValidSvmHeader = (intent)=>{
|
|
2357
|
+
const { header, staticAccountKeys } = intent.operation;
|
|
2358
|
+
return Number.isInteger(header.numRequiredSignatures) && header.numRequiredSignatures >= 1 && header.numRequiredSignatures <= staticAccountKeys.length && Number.isInteger(header.numReadonlySignedAccounts) && header.numReadonlySignedAccounts >= 0 && header.numReadonlySignedAccounts < header.numRequiredSignatures && Number.isInteger(header.numReadonlyUnsignedAccounts) && header.numReadonlyUnsignedAccounts >= 0 && header.numReadonlyUnsignedAccounts <= staticAccountKeys.length - header.numRequiredSignatures;
|
|
2359
|
+
};
|
|
2360
|
+
const hasValidSvmInstructions = (intent)=>{
|
|
2361
|
+
const { instructions, staticAccountKeys } = intent.operation;
|
|
2362
|
+
const isIndex = (value)=>Number.isInteger(value) && value >= 0 && value < staticAccountKeys.length;
|
|
2363
|
+
return instructions.every((instruction)=>isIndex(instruction.programIdIndex) && instruction.accountKeyIndexes.every(isIndex) && isHex(instruction.data));
|
|
2364
|
+
};
|
|
2365
|
+
const assertSvmTransactionMatchesRequest = (intent, request)=>{
|
|
2366
|
+
var _request_chainId;
|
|
2367
|
+
const { operation } = intent;
|
|
2368
|
+
const isBase58 = (value)=>/^[1-9A-HJ-NP-Za-km-z]+$/.test(value);
|
|
2369
|
+
assertMatches(request.chainName === 'SVM' && Boolean(request.chainId) && ((_request_chainId = request.chainId) == null ? void 0 : _request_chainId.trim()) === request.chainId && operation.chainId === request.chainId && request.refreshLimits === undefined && !request.refreshableNonce && intent.limits === undefined && hasLifetime(intent.lifetime, 'blockhash') && (operation.messageVersion === 'legacy' || operation.messageVersion === 'v0') && operation.staticAccountKeys.length > 0 && operation.staticAccountKeys.every(isBase58) && operation.feePayer === request.accountAddress && operation.feePayer === operation.staticAccountKeys[0] && hasValidSvmHeader(intent) && hasValidSvmInstructions(intent), 'Prepared SVM transaction signing intent is malformed');
|
|
2370
|
+
};
|
|
2371
|
+
const assertEvmTransactionMatchesRequest = (intent, request)=>{
|
|
2372
|
+
if (request.chainName !== 'EVM') throw new Error('Unsupported transaction signing intent');
|
|
2373
|
+
const { operation, limits } = intent;
|
|
2374
|
+
if (!limits) throw new Error('Prepared transaction signing intent is malformed');
|
|
2375
|
+
assertMatches(hasLifetime(intent.lifetime, request.refreshableNonce ? 'nonce' : undefined), 'Transaction lifetime does not match request');
|
|
2376
|
+
assertMatches(operation.from === intent.accountAddress.toLowerCase(), 'Transaction signer does not match request');
|
|
2377
|
+
assertMatches(!request.chainId || operation.chainId === request.chainId, 'Transaction chain does not match request');
|
|
2378
|
+
assertMatches(!request.refreshLimits || limitKeys.every((key)=>{
|
|
2379
|
+
var _request_refreshLimits;
|
|
2380
|
+
return limits[key] === ((_request_refreshLimits = request.refreshLimits) == null ? void 0 : _request_refreshLimits[key]);
|
|
2381
|
+
}), 'Transaction signing limits do not match request');
|
|
2382
|
+
// Wallet-service parses the transaction it signs and rejects any mismatch with
|
|
2383
|
+
// the approved operation, so the transaction fields are not re-derived here.
|
|
2384
|
+
};
|
|
2385
|
+
const assertPreparedSigningIntentMatchesRequest = ({ intent, request, preparedPayload })=>{
|
|
2386
|
+
assertMatches(hasMatchingMetadata(intent, request), 'Prepared signing intent does not match request');
|
|
2347
2387
|
if (intent.operation.kind === 'transaction') {
|
|
2348
|
-
if (request.kind !== 'transaction'
|
|
2388
|
+
if (request.kind !== 'transaction') {
|
|
2389
|
+
throw new Error('Unsupported transaction signing intent');
|
|
2390
|
+
}
|
|
2391
|
+
if (isSvmTransactionIntent(intent)) {
|
|
2392
|
+
assertSvmTransactionMatchesRequest(intent, request);
|
|
2393
|
+
return;
|
|
2394
|
+
}
|
|
2395
|
+
if (!isEvmTransactionIntent(intent)) {
|
|
2349
2396
|
throw new Error('Unsupported transaction signing intent');
|
|
2350
2397
|
}
|
|
2351
|
-
|
|
2352
|
-
if (!limits) throw new Error('Prepared transaction signing intent is malformed');
|
|
2353
|
-
assertMatches(operation.from === intent.accountAddress.toLowerCase(), 'Transaction signer does not match request');
|
|
2354
|
-
assertMatches(!request.chainId || operation.chainId === request.chainId, 'Transaction chain does not match request');
|
|
2355
|
-
assertMatches(!request.refreshLimits || limitKeys.every((key)=>{
|
|
2356
|
-
var _request_refreshLimits;
|
|
2357
|
-
return limits[key] === ((_request_refreshLimits = request.refreshLimits) == null ? void 0 : _request_refreshLimits[key]);
|
|
2358
|
-
}), 'Transaction signing limits do not match request');
|
|
2359
|
-
// Wallet-service parses the transaction it signs and rejects any mismatch with
|
|
2360
|
-
// the approved operation, so the transaction fields are not re-derived here.
|
|
2398
|
+
assertEvmTransactionMatchesRequest(intent, request);
|
|
2361
2399
|
return;
|
|
2362
2400
|
}
|
|
2363
2401
|
const { operation } = intent;
|
|
2364
2402
|
assertMatches(preparedPayload !== undefined && operation.payload === preparedPayload, 'Prepared signing intent payload does not match request');
|
|
2365
2403
|
assertMatches(intent.limits === undefined, 'Exact signing intent cannot include refresh limits');
|
|
2404
|
+
assertMatches(hasLifetime(intent.lifetime, undefined), 'Exact signing intent cannot include a lifetime');
|
|
2366
2405
|
if (operation.kind === 'message') {
|
|
2367
2406
|
assertMatches(request.kind === 'message' && request.chainName !== 'TRON' && operation.message === request.message, 'Prepared signing intent message does not match request');
|
|
2368
2407
|
return;
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs-wallet/browser-wallet-client",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.41",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@dynamic-labs-wallet/core": "1.1.
|
|
7
|
+
"@dynamic-labs-wallet/core": "1.1.41",
|
|
8
8
|
"@dynamic-labs/logger": "^5.9.4",
|
|
9
9
|
"@dynamic-labs/message-transport": "^5.9.1"
|
|
10
10
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assertPreparedSigningIntentMatchesRequest.d.ts","sourceRoot":"","sources":["../../packages/src/assertPreparedSigningIntentMatchesRequest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,2BAA2B,EAAE,KAAK,aAAa,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"assertPreparedSigningIntentMatchesRequest.d.ts","sourceRoot":"","sources":["../../packages/src/assertPreparedSigningIntentMatchesRequest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,2BAA2B,EAAE,KAAK,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAiHhH,eAAO,MAAM,yCAAyC,0CAInD;IACD,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,2BAA2B,CAAC;IACrC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,KAAG,IA6DH,CAAC"}
|