Comparing version 1.2.98 to 1.2.99
@@ -1,7 +0,7 @@ | ||
export type { IChainDriver, UniversalTxn, IChainDriverWithHelpers, IGetAssetDetails, ILookupTransactionById, IGetChallengeStringFromBytesToSign, IVerifySignature, IVerifyAssets, IMakeAssetTxn, IMakeAssetTransferTxn, ISendTx, IGetAssets, IGetLastBlockIndex, IGetTimestampForBlock, IIsValidAddress, IGetPublicKey, } from './types/ChainDriver.types.js'; | ||
export type { CreateAssetParams, CreateTransferAssetParams, } from './types/auth.types.js'; | ||
export type { ChallengeParams, VerifyChallengeOptions, CreateChallengeOptions, Asset, } from './types/verify.types.js'; | ||
export { convertAsset, convertChallengeParams, } from './types/verify.types.js'; | ||
export { convertAssetWithUIDetails, } from './ui/BlockinUIDisplay/BlockinUIDisplay.types.js'; | ||
export type { SignAndVerifyChallengeResponse, PresetUri, AssetWithUIDetails, SupportedChainMetadata } from './ui/BlockinUIDisplay/BlockinUIDisplay.types.js'; | ||
export type { IChainDriver, UniversalTxn, IChainDriverWithHelpers, IGetAssetDetails, ILookupTransactionById, IGetChallengeStringFromBytesToSign, IVerifySignature, IVerifyAssets, IMakeAssetTxn, IMakeAssetTransferTxn, ISendTx, IGetAssets, IGetLastBlockIndex, IGetTimestampForBlock, IIsValidAddress, IGetPublicKey, } from './types/ChainDriver.types'; | ||
export type { CreateAssetParams, CreateTransferAssetParams, } from './types/auth.types'; | ||
export type { ChallengeParams, VerifyChallengeOptions, CreateChallengeOptions, AssetConditionGroup, } from './types/verify.types'; | ||
export { convertAssetConditionGroup, convertChallengeParams, } from './types/verify.types'; | ||
export {} from './ui/BlockinUIDisplay/BlockinUIDisplay.types'; | ||
export type { SignAndVerifyChallengeResponse, PresetUri, AssetUIDetails, SupportedChainMetadata } from './ui/BlockinUIDisplay/BlockinUIDisplay.types'; | ||
/** | ||
@@ -16,2 +16,2 @@ * We have removed ChainDrivers from being exported for a few reasons. | ||
*/ | ||
export { createChallenge, verifyChallenge, constructChallengeObjectFromString, validateChallengeObjectIsWellFormed, generateNonceUsingLastBlockTimestamp } from './verify.js'; | ||
export { createChallenge, verifyChallenge, constructChallengeObjectFromString, validateChallengeObjectIsWellFormed, generateNonceUsingLastBlockTimestamp } from './verify'; |
@@ -1,49 +0,64 @@ | ||
function convertAsset(item, convertFunction) { | ||
const { collectionId, assetIds, ownershipTimes, mustOwnAmounts, ...rest } = item; | ||
let isCollectionIdNumeric = false; | ||
try { | ||
BigInt(collectionId); | ||
isCollectionIdNumeric = true; | ||
function convertAssetConditionGroup(item, convertFunction) { | ||
const andItem = item; | ||
const orItem = item; | ||
const ownershipRequirements = item; | ||
if (andItem['$and'] !== undefined) { | ||
return { | ||
$and: andItem.$and.map(group => convertAssetConditionGroup(group, convertFunction)) | ||
}; | ||
} | ||
catch (e) { | ||
isCollectionIdNumeric = false; | ||
else if (orItem['$or'] !== undefined) { | ||
return { | ||
$or: orItem.$or.map(group => convertAssetConditionGroup(group, convertFunction)) | ||
}; | ||
} | ||
return { | ||
...rest, | ||
collectionId: isCollectionIdNumeric ? convertFunction(collectionId) : collectionId, | ||
assetIds: assetIds.map(id => { | ||
if (typeof id === 'string') { | ||
return id; | ||
} | ||
return { | ||
start: convertFunction(id.start), | ||
end: convertFunction(id.end), | ||
}; | ||
}), | ||
ownershipTimes: ownershipTimes?.map(time => ({ | ||
start: convertFunction(time.start), | ||
end: convertFunction(time.end), | ||
})), | ||
mustOwnAmounts: { | ||
start: convertFunction(mustOwnAmounts.start), | ||
end: convertFunction(mustOwnAmounts.end), | ||
}, | ||
}; | ||
else { | ||
return { | ||
assets: ownershipRequirements.assets.map(asset => { | ||
let isCollectionIdNumeric = false; | ||
try { | ||
BigInt(asset.collectionId); | ||
isCollectionIdNumeric = true; | ||
} | ||
catch (e) { | ||
isCollectionIdNumeric = false; | ||
} | ||
return { | ||
...asset, | ||
collectionId: isCollectionIdNumeric ? convertFunction(asset.collectionId) : asset.collectionId, | ||
assetIds: asset.assetIds.map(id => { | ||
if (typeof id === 'string') { | ||
return id; | ||
} | ||
return { | ||
start: convertFunction(id.start), | ||
end: convertFunction(id.end), | ||
}; | ||
}), | ||
ownershipTimes: asset.ownershipTimes?.map(time => ({ | ||
start: convertFunction(time.start), | ||
end: convertFunction(time.end), | ||
})), | ||
mustOwnAmounts: { | ||
start: convertFunction(asset.mustOwnAmounts.start), | ||
end: convertFunction(asset.mustOwnAmounts.end), | ||
}, | ||
}; | ||
}), | ||
options: ownershipRequirements.options ? { | ||
numMatchesForVerification: ownershipRequirements.options.numMatchesForVerification ? convertFunction(ownershipRequirements.options.numMatchesForVerification) : undefined | ||
} : undefined | ||
}; | ||
} | ||
} | ||
function convertChallengeParams(item, convertFunction) { | ||
const { assets, ...rest } = item; | ||
const { assetOwnershipRequirements, ...rest } = item; | ||
return { | ||
...rest, | ||
assets: assets?.map(asset => convertAsset(asset, convertFunction)), | ||
assetOwnershipRequirements: assetOwnershipRequirements ? | ||
convertAssetConditionGroup(assetOwnershipRequirements, convertFunction) | ||
: undefined | ||
}; | ||
} | ||
function convertAssetWithUIDetails(item, convertFunction) { | ||
const { collectionId, assetIds, ownershipTimes, mustOwnAmounts, ...rest } = item; | ||
return { | ||
...rest, | ||
...convertAsset(item, convertFunction), | ||
}; | ||
} | ||
function compareObjects(obj1, obj2) { | ||
@@ -124,3 +139,3 @@ if (obj1 === obj2) { | ||
*/ | ||
const { domain, statement, address, uri, nonce, version = "1", chainId = "1", issuedAt = new Date().toISOString(), expirationDate = undefined, notBefore = undefined, resources = undefined, assets = undefined } = challengeParams; | ||
const { domain, statement, address, uri, nonce, version = "1", chainId = "1", issuedAt = new Date().toISOString(), expirationDate = undefined, notBefore = undefined, resources = undefined, assetOwnershipRequirements = undefined } = challengeParams; | ||
try { | ||
@@ -139,3 +154,3 @@ const challenge = { | ||
resources, | ||
assets | ||
assetOwnershipRequirements | ||
}; | ||
@@ -206,6 +221,6 @@ validateChallengeObjectIsWellFormed(challenge); // will throw error if invalid | ||
//This also handles the undefined stuff | ||
if (options.expectedChallengeParams.assets) | ||
options.expectedChallengeParams.assets = options.expectedChallengeParams.assets?.map(asset => convertAsset(asset, convertFunction)); | ||
if (challenge.assets) | ||
challenge.assets = challenge.assets?.map(asset => convertAsset(asset, convertFunction)); | ||
if (options.expectedChallengeParams.assetOwnershipRequirements) | ||
options.expectedChallengeParams.assetOwnershipRequirements = convertAssetConditionGroup(options.expectedChallengeParams.assetOwnershipRequirements, convertFunction); | ||
if (challenge.assetOwnershipRequirements) | ||
challenge.assetOwnershipRequirements = convertAssetConditionGroup(challenge.assetOwnershipRequirements, convertFunction); | ||
for (const key of Object.keys(options?.expectedChallengeParams ?? {})) { | ||
@@ -220,7 +235,7 @@ const expected = options?.expectedChallengeParams[key]; | ||
const toSkipAssetVerification = options?.skipAssetVerification ?? false; | ||
if (challenge.resources || challenge.assets) { | ||
if (challenge.resources || challenge.assetOwnershipRequirements) { | ||
if (!toSkipAssetVerification) { | ||
if (!chainDriver) | ||
throw `ChainDriver is required to verify assets`; | ||
const assetLookupData = await verifyAssets(chainDriver, challenge.address, (challenge.resources ?? []), (challenge.assets ?? []), options?.balancesSnapshot); | ||
const assetLookupData = await verifyAssets(chainDriver, challenge.address, (challenge.resources ?? []), challenge.assetOwnershipRequirements ?? undefined, options?.balancesSnapshot); | ||
verificationData.assetLookupData = assetLookupData; | ||
@@ -277,9 +292,84 @@ } | ||
} | ||
function parseAssetConditionGroup(lines, convertFunction) { | ||
//lines 0 and 1 are same whitespace | ||
const isAllCondition = lines[0].trim().includes('(satisfied if all'); | ||
const isOrCondition = lines[0].trim().includes('(satisfied if one'); | ||
//Little weird bc normal ones are not an array but $and and $or are | ||
//For normal ones, we are already at the Requirement X line and we want to parse the whole condition until Requirement X+1 as its own non-array object | ||
//For $and and $or, we need to parse everything indented as a single array | ||
//We add two lines bc we have Requirement X: then Must satisfy line | ||
//Pretty much, if we have an $and or $or, we will have the following | ||
//Requirement X: | ||
//Must satisfy... | ||
// Requirement 1: | ||
// ... | ||
// We want to parse everything indented as a single array ($and or $or) | ||
//If we are parsing a non $and or $or, we will already be indented to the Requirement X line we want to parse | ||
//We want to parse everything on the same indent level as the Requirement X line | ||
//If this is the case, we can assume that we have no more $ands or $ors going down the tree (this is the leaf assets) | ||
let nextIndentDepth = lines[0].search(/\S/); | ||
if (isAllCondition || isOrCondition) { | ||
nextIndentDepth = lines[1].search(/\S/); | ||
} | ||
//Find the lines with matching depths = to the first lines depth | ||
const idxs = []; | ||
for (let i = 0; i < lines.length; i++) { | ||
if (lines[i].search(/\S/) === nextIndentDepth) { | ||
idxs.push(i); | ||
i++; //avoid the edge case where the next line is the same depth ($ands and $ors) | ||
} | ||
} | ||
idxs.push(lines.length); | ||
const andItem = { $and: [] }; | ||
const orItem = { $or: [] }; | ||
//In all of these the startIdx should be the next Requirement line to parse | ||
if (isAllCondition) { | ||
//Parse all subsequent conditions as an array of asset details and options | ||
andItem['$and'] = []; | ||
for (let i = 0; i < idxs.length - 1; i++) { | ||
andItem['$and'].push(parseAssetConditionGroup(lines.slice(idxs[i], idxs[i + 1]), convertFunction)); | ||
} | ||
return andItem; | ||
} | ||
else if (isOrCondition) { | ||
//Parse all subsequent conditions as an array of asset details and options | ||
orItem['$or'] = []; | ||
for (let i = 0; i < idxs.length - 1; i++) { | ||
orItem['$or'].push(parseAssetConditionGroup(lines.slice(idxs[i], idxs[i + 1]), convertFunction)); | ||
} | ||
return orItem; | ||
} | ||
else { | ||
//Parse | ||
const assets = []; | ||
let options = {}; | ||
const trimmedLine = lines[0].trim(); | ||
if (trimmedLine.includes('(must satisfy for a minimum of')) { | ||
const numMatches = trimmedLine.split(" ")[9]; | ||
options = { numMatchesForVerification: convertFunction(numMatches) }; | ||
} | ||
for (let i = 0; i < idxs.length - 1; i++) { | ||
const assetDetails = parseChallengeAssetDetails(lines.slice(idxs[i], idxs[i + 1]), convertFunction); | ||
assets.push(...assetDetails.assets); | ||
if (options) { | ||
options.numMatchesForVerification = options.numMatchesForVerification ? convertFunction(options.numMatchesForVerification) : undefined; | ||
} | ||
} | ||
return convertAssetConditionGroup({ assets, options }, convertFunction); | ||
} | ||
} | ||
function parseChallengeAssets(challengeString, convertFunction) { | ||
const lines = challengeString.split("\n"); | ||
const assetIdx = lines.findIndex(line => line.trim().startsWith('Asset Ownership Requirements:')); | ||
if (assetIdx === -1) | ||
return undefined; | ||
const assetLines = lines.slice(assetIdx + 1); | ||
return parseAssetConditionGroup(assetLines, convertFunction); | ||
} | ||
function parseChallengeAssetDetails(lines, convertFunction) { | ||
const assets = []; | ||
const lines = challengeString.split("\n"); | ||
let currentAsset = null; | ||
for (const line of lines) { | ||
const trimmedLine = line.trim(); | ||
if (trimmedLine.startsWith("- Chain:")) { | ||
if (trimmedLine.startsWith("Chain:")) { | ||
if (currentAsset) { | ||
@@ -290,3 +380,3 @@ if (currentAsset.assetIds) { | ||
} | ||
currentAsset = { chain: trimmedLine.substring(9).trim() }; | ||
currentAsset = { chain: trimmedLine.substring(7).trim() }; | ||
} | ||
@@ -303,3 +393,3 @@ else if (trimmedLine.startsWith("Collection ID:")) { | ||
} | ||
else if (trimmedLine.startsWith("- ID Range:")) { | ||
else if (trimmedLine.startsWith("Asset IDs:")) { | ||
if (currentAsset) { | ||
@@ -309,7 +399,7 @@ if (!currentAsset.assetIds) { | ||
} | ||
const range = trimmedLine.substring(11).trim().split(" to "); | ||
const range = trimmedLine.substring(10).trim().split(" to "); | ||
currentAsset.assetIds.push({ start: convertFunction(range[0]), end: convertFunction(range[1]) }); | ||
} | ||
} | ||
else if (trimmedLine.startsWith("- Time Range:")) { | ||
else if (trimmedLine.startsWith("Ownership Times:")) { | ||
if (currentAsset) { | ||
@@ -321,3 +411,3 @@ if (!currentAsset.ownershipTimes) { | ||
if (hasOnwards) { | ||
const range = trimmedLine.substring(14).trim().split(" onwards"); | ||
const range = trimmedLine.substring(17).trim().split(" onwards"); | ||
const firstDate = new Date(range[0].trim()); | ||
@@ -330,3 +420,3 @@ currentAsset.ownershipTimes.push({ | ||
else { | ||
const range = trimmedLine.substring(14).trim().split(" to "); | ||
const range = trimmedLine.substring(17).trim().split(" to "); | ||
currentAsset.ownershipTimes.push({ | ||
@@ -339,5 +429,5 @@ start: convertFunction(new Date(range[0].substring(0, range[0].length).trim()).valueOf()), | ||
} | ||
else if (trimmedLine.startsWith("- Range: x")) { | ||
else if (trimmedLine.startsWith("Ownership Amounts: x")) { | ||
if (currentAsset) { | ||
const range = trimmedLine.substring(9).trim().split(" to "); | ||
const range = trimmedLine.substring(12).trim().split(" to "); | ||
const firstAmount = range[0].substring(0, range[0].length - 5).trim().substring(1); //-5 to account for (min) (max) | ||
@@ -351,5 +441,5 @@ const secondAmount = range[1].substring(0, range[1].length - 5).trim().substring(1); | ||
} | ||
else if (trimmedLine.startsWith("- Amount: Exactly x")) { | ||
else if (trimmedLine.startsWith("Ownership Amount: x")) { | ||
if (currentAsset) { | ||
const range = trimmedLine.substring(17).trim().split(" to "); | ||
const range = trimmedLine.substring(25 - 8).trim().split(" to "); | ||
const firstAmount = range[0].substring(1).trim(); | ||
@@ -362,3 +452,3 @@ currentAsset.mustOwnAmounts = { | ||
} | ||
else if (trimmedLine.startsWith("- Time: ")) { | ||
else if (trimmedLine.startsWith("Ownership Time: ")) { | ||
if (currentAsset) { | ||
@@ -368,11 +458,14 @@ if (!currentAsset.ownershipTimes) { | ||
} | ||
const range = trimmedLine.substring(7).trim(); | ||
currentAsset.ownershipTimes.push({ | ||
start: convertFunction(new Date(range).valueOf()), | ||
end: convertFunction(new Date(range).valueOf()), | ||
}); | ||
const range = trimmedLine.substring(15).trim(); | ||
if (range === "Authentication Time") ; | ||
else { | ||
currentAsset.ownershipTimes.push({ | ||
start: convertFunction(new Date(range).valueOf()), | ||
end: convertFunction(new Date(range).valueOf()), | ||
}); | ||
} | ||
} | ||
} | ||
else if (trimmedLine.startsWith('- Sign-In Time')) ; | ||
else if (trimmedLine.startsWith('Additional Criteria:')) { | ||
else if (trimmedLine.startsWith('Other:')) { | ||
if (currentAsset) { | ||
@@ -382,3 +475,3 @@ currentAsset.additionalCriteria = trimmedLine.substring(20).trim(); | ||
} | ||
else if (trimmedLine.startsWith("- ")) { | ||
else if (trimmedLine.startsWith("Asset ID: ")) { | ||
if (currentAsset) { | ||
@@ -388,16 +481,6 @@ if (!currentAsset.assetIds) { | ||
} | ||
const range = trimmedLine.substring(2).trim(); | ||
const range = trimmedLine.substring(10).trim(); | ||
currentAsset.assetIds.push(range); | ||
} | ||
} | ||
else if (trimmedLine.startsWith("Must meet ownership requirements for all assets")) { | ||
if (currentAsset) { | ||
currentAsset.mustSatisfyForAllAssets = true; | ||
} | ||
} | ||
else if (trimmedLine.startsWith("Must meet ownership requirements for one of the assets")) { | ||
if (currentAsset) { | ||
currentAsset.mustSatisfyForAllAssets = false; | ||
} | ||
} | ||
} | ||
@@ -407,3 +490,5 @@ if (currentAsset && currentAsset.assetIds && currentAsset.chain && currentAsset.collectionId && currentAsset.mustOwnAmounts) { | ||
} | ||
return assets; | ||
return { | ||
assets, | ||
}; | ||
} | ||
@@ -448,8 +533,109 @@ /** | ||
} | ||
if (challenge.assets) { | ||
for (const asset of challenge.assets) { | ||
if (challenge.assetOwnershipRequirements) { | ||
validateAssetConditionGroup(challenge.assetOwnershipRequirements); | ||
} | ||
} | ||
function validateAssetConditionGroup(assetConditionGroup) { | ||
const andItem = assetConditionGroup; | ||
const orItem = assetConditionGroup; | ||
const ownershipRequirements = assetConditionGroup; | ||
if (andItem['$and'] !== undefined) { | ||
for (const item of andItem['$and']) { | ||
validateAssetConditionGroup(item); | ||
} | ||
} | ||
else if (orItem['$or'] !== undefined) { | ||
for (const item of orItem['$or']) { | ||
validateAssetConditionGroup(item); | ||
} | ||
} | ||
else { | ||
for (const asset of ownershipRequirements.assets) { | ||
assertAssetType(asset); | ||
} | ||
if (ownershipRequirements.options) { | ||
try { | ||
if (ownershipRequirements.options.numMatchesForVerification !== undefined) | ||
BigInt(ownershipRequirements.options.numMatchesForVerification); | ||
} | ||
catch (e) { | ||
throw new Error("Invalid numMatchesForVerification type"); | ||
} | ||
} | ||
} | ||
} | ||
function generateAssetConditionGroupString(assetConditionGroup, depth = 0, bulletNumber, parentBullet) { | ||
let message = ""; | ||
const andItem = assetConditionGroup; | ||
const orItem = assetConditionGroup; | ||
const ownershipRequirements = assetConditionGroup; | ||
const depthLetter = String.fromCharCode(65 + depth); | ||
const nextDepthLetter = String.fromCharCode(65 + depth + 1); | ||
message += ' '.repeat(depth * 2) + `- Requirement ${depthLetter}${parentBullet}-${bulletNumber}`; | ||
if (andItem['$and'] !== undefined) { | ||
message += ` (satisfied if all of ${nextDepthLetter}${bulletNumber} are satisfied):\n`; | ||
for (let i = 0; i < andItem['$and'].length; i++) { | ||
message += generateAssetConditionGroupString(andItem['$and'][i], depth + 1, i + 1, bulletNumber); | ||
} | ||
} | ||
else if (orItem['$or'] !== undefined) { | ||
message += ` (satisfied if one of ${nextDepthLetter}${bulletNumber} is satisfied):\n`; | ||
for (let i = 0; i < orItem['$or'].length; i++) { | ||
message += generateAssetConditionGroupString(orItem['$or'][i], depth + 1, i + 1, bulletNumber); | ||
} | ||
} | ||
else { | ||
const groupOptions = ownershipRequirements.options; | ||
if (groupOptions?.numMatchesForVerification && groupOptions.numMatchesForVerification) { | ||
message += ` (must satisfy for a minimum of ${groupOptions.numMatchesForVerification} of the asset IDs):\n`; | ||
} | ||
for (const asset of ownershipRequirements.assets) { | ||
message += ' '.repeat(depth * 2 + 2) + ` Chain: ${asset.chain}\n`; | ||
message += ' '.repeat(depth * 2 + 2) + ` Collection ID: ${asset.collectionId}\n`; | ||
if (asset.assetIds) { | ||
for (const assetId of asset.assetIds) { | ||
if (typeof assetId === "string") { | ||
message += ' '.repeat(depth * 2 + 4) + `Asset ID: ${assetId}\n`; | ||
} | ||
else if (typeof assetId === "object") { | ||
message += ' '.repeat(depth * 2 + 4) + `Asset IDs: ${assetId.start} to ${assetId.end}\n`; | ||
} | ||
} | ||
} | ||
if (asset.ownershipTimes) { | ||
for (const time of asset.ownershipTimes) { | ||
if (typeof time === "string") { | ||
message += ' '.repeat(depth * 2 + 4) + `Ownership Time: ${new Date(time).toISOString}\n`; | ||
} | ||
else if (typeof time === "object") { | ||
const startDate = new Date(Number(BigInt(time.start))).toISOString(); | ||
const endDateNumber = BigInt(time.end); | ||
if (endDateNumber > Number.MAX_SAFE_INTEGER) { | ||
message += ' '.repeat(depth * 2 + 4) + `Ownership Times: ${startDate} onwards\n`; | ||
} | ||
else { | ||
message += ' '.repeat(depth * 2 + 4) + `Ownership Times: ${startDate} to ${new Date(Number(BigInt(time.end))).toISOString()}\n`; | ||
} | ||
} | ||
} | ||
} | ||
else { | ||
message += ' '.repeat(depth * 2 + 4) + `Ownership Time: Authentication Time\n`; | ||
} | ||
if (asset.mustOwnAmounts) { | ||
if (asset.mustOwnAmounts.start === asset.mustOwnAmounts.end) { | ||
message += ' '.repeat(depth * 2 + 4) + `Ownership Amount: x${asset.mustOwnAmounts.start}\n`; | ||
} | ||
else { | ||
message += ' '.repeat(depth * 2 + 4) + `Ownership Amounts: x${asset.mustOwnAmounts.start} (min) to x${asset.mustOwnAmounts.end} (max)\n`; | ||
} | ||
} | ||
if (asset.additionalCriteria) { | ||
message += ' '.repeat(depth * 2 + 4) + `Other: ${asset.additionalCriteria}\n`; | ||
} | ||
message += '\n'; | ||
} | ||
} | ||
return message; | ||
} | ||
/** | ||
@@ -487,57 +673,5 @@ * Parses a JSON object that specifies the challenge fields and returns a well-formatted EIP-4361 string. | ||
} | ||
if (challenge.assets) { | ||
message += `\nAssets:\n`; | ||
for (const asset of challenge.assets) { | ||
message += `- Chain: ${asset.chain}\n`; | ||
message += ` Collection ID: ${asset.collectionId}\n`; | ||
message += ` ${asset.mustSatisfyForAllAssets ? "Must meet ownership requirements for all assets" : "Must meet ownership requirements for one of the assets"}\n`; | ||
message += ` Asset IDs:\n`; | ||
for (const assetId of asset.assetIds) { | ||
if (typeof assetId === "string") { | ||
message += ` - ${assetId}\n`; | ||
} | ||
else if (typeof assetId === "object") { | ||
message += ` - ID Range: ${assetId.start} to ${assetId.end}\n`; | ||
} | ||
} | ||
message += ` Ownership Times:\n`; | ||
if (!asset.ownershipTimes) { | ||
message += ` - Sign-In Time\n`; | ||
} | ||
if (asset.ownershipTimes) { | ||
for (const time of asset.ownershipTimes) { | ||
if (typeof time === "string") { | ||
message += ` - Time: ${new Date(time).toISOString}\n`; | ||
} | ||
else if (typeof time === "object") { | ||
if (typeof time === "string") { | ||
message += ` - Time: ${new Date(time).toISOString}\n`; | ||
} | ||
else if (typeof time === "object") { | ||
const startDate = new Date(Number(BigInt(time.start))).toISOString(); | ||
const endDateNumber = BigInt(time.end); | ||
if (endDateNumber > Number.MAX_SAFE_INTEGER) { | ||
message += ` - Time Range: ${startDate} onwards\n`; | ||
} | ||
else { | ||
message += ` - Time Range: ${startDate} to ${new Date(Number(BigInt(time.end))).toISOString()}\n`; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
message += ` Ownership Amounts:\n`; | ||
if (typeof asset.mustOwnAmounts === "object") { | ||
if (asset.mustOwnAmounts.start === asset.mustOwnAmounts.end) { | ||
message += ` - Amount: Exactly x${asset.mustOwnAmounts.start}\n`; | ||
} | ||
else { | ||
message += ` - Range: x${asset.mustOwnAmounts.start} (min) to x${asset.mustOwnAmounts.end} (max)\n`; | ||
} | ||
} | ||
if (asset.additionalCriteria) { | ||
message += ` Additional Criteria: ${asset.additionalCriteria}\n`; | ||
} | ||
message += `\n`; | ||
} | ||
if (challenge.assetOwnershipRequirements) { | ||
message += `\nAsset Ownership Requirements:\n`; | ||
message += generateAssetConditionGroupString(challenge.assetOwnershipRequirements, 0, 1, 1); | ||
} | ||
@@ -566,3 +700,3 @@ return message; | ||
let resources = []; | ||
let assets = []; | ||
let assetOwnershipRequirements; | ||
for (let i = 10; i < messageArray.length; i++) { | ||
@@ -578,3 +712,3 @@ if (messageArray[i].indexOf('Expiration Time:') !== -1) { | ||
for (let j = i + 1; j < messageArray.length; j++) { | ||
if (messageArray[j].indexOf('Assets:') !== -1) { | ||
if (messageArray[j].indexOf('Asset Ownership Requirements:') !== -1) { | ||
break; | ||
@@ -586,8 +720,8 @@ } | ||
} | ||
else if (messageArray[i].indexOf('Assets:') !== -1) { | ||
assets = parseChallengeAssets(challenge, convertFunction); | ||
else if (messageArray[i].indexOf('Asset Ownership Requirements:') !== -1) { | ||
assetOwnershipRequirements = parseChallengeAssets(challenge, convertFunction); | ||
break; | ||
} | ||
} | ||
return { domain, address, statement, expirationDate, notBefore, resources, issuedAt, uri, version, chainId, nonce, assets }; | ||
return { domain, address, statement, expirationDate, notBefore, resources, issuedAt, uri, version, chainId, nonce, assetOwnershipRequirements }; | ||
} | ||
@@ -622,3 +756,3 @@ /** | ||
export { constructChallengeObjectFromString, convertAsset, convertAssetWithUIDetails, convertChallengeParams, createChallenge, generateNonceUsingLastBlockTimestamp, validateChallengeObjectIsWellFormed, verifyChallenge }; | ||
export { constructChallengeObjectFromString, convertAssetConditionGroup, convertChallengeParams, createChallenge, generateNonceUsingLastBlockTimestamp, validateChallengeObjectIsWellFormed, verifyChallenge }; | ||
//# sourceMappingURL=index.js.map |
import { CreateAssetParams, CreateTransferAssetParams } from "./auth.types.js"; | ||
import { Asset, NumberType } from "./verify.types.js"; | ||
import { AssetConditionGroup, NumberType } from "./verify.types.js"; | ||
export type UniversalTxn = { | ||
@@ -46,3 +46,3 @@ txn: Uint8Array; | ||
export interface IVerifyAssets<T extends NumberType> { | ||
(address: string, resources: string[], assets: Asset<T>[], balancesSnapshot?: object): Promise<any>; | ||
(address: string, resources: string[], assets: AssetConditionGroup<T> | undefined, balancesSnapshot?: object): Promise<any>; | ||
} | ||
@@ -49,0 +49,0 @@ /** |
@@ -6,7 +6,9 @@ export type NumberType = string | bigint | number | boolean; | ||
} | ||
export interface StringRange { | ||
start: string; | ||
end: string; | ||
export interface AndGroup<T extends NumberType> { | ||
$and: AssetConditionGroup<T>[]; | ||
} | ||
export interface Asset<T extends NumberType> { | ||
export interface OrGroup<T extends NumberType> { | ||
$or: AssetConditionGroup<T>[]; | ||
} | ||
export interface AssetDetails<T extends NumberType> { | ||
chain: string; | ||
@@ -17,5 +19,11 @@ collectionId: T | string; | ||
mustOwnAmounts: UintRange<T>; | ||
mustSatisfyForAllAssets: boolean; | ||
additionalCriteria?: string; | ||
} | ||
export interface OwnershipRequirements<T extends NumberType> { | ||
assets: AssetDetails<T>[]; | ||
options?: { | ||
numMatchesForVerification?: T; | ||
}; | ||
} | ||
export type AssetConditionGroup<T extends NumberType> = AndGroup<T> | OrGroup<T> | OwnershipRequirements<T>; | ||
/** | ||
@@ -40,5 +48,5 @@ * Interface for EIP-4361 Challenge - Sign in With Ethereum | ||
resources?: string[]; | ||
assets?: Asset<T>[]; | ||
assetOwnershipRequirements?: AssetConditionGroup<T>; | ||
} | ||
export declare function convertAsset<T extends NumberType, U extends NumberType>(item: Asset<T>, convertFunction: (item: T) => U): Asset<U>; | ||
export declare function convertAssetConditionGroup<T extends NumberType, U extends NumberType>(item: AssetConditionGroup<T>, convertFunction: (item: T) => U): AssetConditionGroup<U>; | ||
export declare function convertChallengeParams<T extends NumberType, U extends NumberType>(item: ChallengeParams<T>, convertFunction: (item: T) => U): ChallengeParams<U>; | ||
@@ -45,0 +53,0 @@ /** |
import { ReactNode } from "react"; | ||
import { Asset, ChallengeParams, NumberType } from "../../types/verify.types.js"; | ||
import { ChallengeParams, NumberType } from "../../types/verify.types"; | ||
import { AssetConditionGroupWithUIDetails } from "../SignInModal/SignInModal.types"; | ||
/** | ||
@@ -21,5 +22,2 @@ * Defines schema for displaying a resource within the pop-up modal. | ||
} | ||
export interface AssetWithUIDetails<T extends NumberType> extends Asset<T>, AssetUIDetails<T> { | ||
} | ||
export declare function convertAssetWithUIDetails<T extends NumberType, U extends NumberType>(item: AssetWithUIDetails<T>, convertFunction: (item: T) => U): AssetWithUIDetails<U>; | ||
/** | ||
@@ -151,3 +149,3 @@ * Expected return trype for signAndVerifyChallenge() | ||
*/ | ||
displayedAssets?: AssetWithUIDetails<T>[]; | ||
displayedAssetGroups?: AssetConditionGroupWithUIDetails<T>[]; | ||
/** | ||
@@ -154,0 +152,0 @@ * Hides the hover to learn more tooltip |
import { ReactNode } from "react"; | ||
import { Asset, ChallengeParams, NumberType } from "../../types/verify.types.js"; | ||
import { AssetConditionGroup, ChallengeParams, NumberType } from "../../types/verify.types.js"; | ||
/** | ||
@@ -22,9 +22,10 @@ * Expected return trype for signAndVerifyChallenge() | ||
}; | ||
export interface PresetAsset<T extends NumberType> extends Asset<T> { | ||
export interface AssetConditionGroupWithUIDetails<T extends NumberType> { | ||
name: string; | ||
description?: string | ReactNode; | ||
image?: string; | ||
image: string; | ||
frozen: boolean; | ||
defaultSelected: boolean; | ||
additionalDisplay?: ReactNode; | ||
assetConditionGroup: AssetConditionGroup<T>; | ||
} | ||
@@ -99,3 +100,3 @@ /** | ||
*/ | ||
displayedAssets?: PresetAsset<T>[]; | ||
displayedAssetGroups?: AssetConditionGroupWithUIDetails<T>[]; | ||
/** | ||
@@ -102,0 +103,0 @@ * Resources to be displayed to sign-in with. See PresetResource type. |
@@ -1,4 +0,3 @@ | ||
import { NumberType } from "bitbadgesjs-utils"; | ||
import React from "react"; | ||
import { ChallengeParams, VerifyChallengeOptions } from "../../types/verify.types"; | ||
import { ChallengeParams, NumberType, VerifyChallengeOptions } from "../../types/verify.types"; | ||
export declare const SignInWithBitBadgesButton: React.FC<{ | ||
@@ -5,0 +4,0 @@ noDefaultStyles?: boolean; |
import { IChainDriver, IChainDriverWithHelpers } from './index.js'; | ||
import { Asset, ChallengeParams, CreateChallengeOptions, NumberType, VerifyChallengeOptions } from './types/verify.types'; | ||
import { AssetConditionGroup, ChallengeParams, CreateChallengeOptions, NumberType, VerifyChallengeOptions } from './types/verify.types'; | ||
/** | ||
@@ -38,3 +38,3 @@ * Creates a challenge that is well-formed according to EIP-4361 - Sign in With Ethereum. Some | ||
export declare function generateNonceUsingLastBlockTimestamp(chainDriver: IChainDriverWithHelpers<NumberType>): Promise<any>; | ||
export declare function parseChallengeAssets<T extends NumberType, U extends NumberType>(challengeString: string, convertFunction: (item: U) => T): Asset<T>[]; | ||
export declare function parseChallengeAssets<T extends NumberType, U extends NumberType>(challengeString: string, convertFunction: (item: NumberType) => T): AssetConditionGroup<T> | undefined; | ||
/** | ||
@@ -46,2 +46,3 @@ * Validates the object is well-formed according to the EIP-4361 interface, plus our additional add-ons | ||
export declare function validateChallengeObjectIsWellFormed<T extends NumberType>(challenge: ChallengeParams<T>): void; | ||
export declare function generateAssetConditionGroupString<T extends NumberType>(assetConditionGroup: AssetConditionGroup<T>, depth: number | undefined, bulletNumber: number, parentBullet: number): string; | ||
/** | ||
@@ -54,2 +55,2 @@ * Constructs a valid JSON challenge object from a valid well-formed EIP-4361 string. Note this | ||
*/ | ||
export declare function constructChallengeObjectFromString<T extends NumberType, U extends NumberType>(challenge: string, convertFunction: (item: U) => T): ChallengeParams<T>; | ||
export declare function constructChallengeObjectFromString<T extends NumberType>(challenge: string, convertFunction: (item: NumberType) => T): ChallengeParams<T>; |
{ | ||
"name": "blockin", | ||
"version": "1.2.98", | ||
"version": "1.2.99", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "files": [ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1890930
48873