Skip to content

Commit 5863f68

Browse files
authored
Merge pull request #78 from reclaimprotocol/rm-contract-stuff
Remove Contract Calls
2 parents 1af99e0 + 8b6aff4 commit 5863f68

13 files changed

Lines changed: 2675 additions & 2925 deletions

File tree

package-lock.json

Lines changed: 2565 additions & 2068 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,18 +82,18 @@
8282
"jest-environment-jsdom": "^30.1.2",
8383
"ts-jest": "^29.4.1",
8484
"tsup": "^8.0.1",
85-
"typescript": "^5.3.3"
85+
"typescript": "^5.3.3",
86+
"release-it": "^19.0.4",
87+
"@release-it/conventional-changelog": "^10.0.1",
88+
"qs": "^6.11.2"
8689
},
8790
"dependencies": {
88-
"@release-it/conventional-changelog": "^10.0.1",
8991
"canonicalize": "^2.0.0",
9092
"ethers": "^6.9.1",
91-
"qs": "^6.11.2",
92-
"release-it": "^19.0.4",
9393
"url-parse": "^1.5.10",
9494
"uuid": "^9.0.1"
9595
},
9696
"overrides": {
9797
"@conventional-changelog/git-client": "^2.0.0"
9898
}
99-
}
99+
}

src/Reclaim.ts

Lines changed: 58 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import { type Proof, type Context, RECLAIM_EXTENSION_ACTIONS, ExtensionMessage } from './utils/interfaces'
2-
import { getIdentifierFromClaimInfo } from './witness'
32
import {
4-
SignedClaim,
53
ProofRequestOptions,
64
StartSessionParams,
75
ProofPropertiesJSON,
@@ -39,11 +37,12 @@ import {
3937
} from './utils/errors'
4038
import { validateContext, validateFunctionParams, validateParameters, validateSignature, validateURL, validateModalOptions, validateFunctionParamsWithFn, validateRedirectionMethod, validateRedirectionBody } from './utils/validationUtils'
4139
import { fetchStatusUrl, initSession, updateSession } from './utils/sessionUtils'
42-
import { assertValidSignedClaim, createLinkWithTemplateData, getWitnessesForClaim } from './utils/proofUtils'
40+
import { createLinkWithTemplateData, getAttestors, recoverSignersOfSignedClaim } from './utils/proofUtils'
4341
import { QRCodeModal } from './utils/modalUtils'
4442
import loggerModule from './utils/logger';
45-
import { getDeviceType, getMobileDeviceType, isMobileDevice } from './utils/device'
43+
import { getDeviceType, getMobileDeviceType } from './utils/device'
4644
import { canonicalStringify } from './utils/strings'
45+
4746
const logger = loggerModule.logger
4847

4948
const sdkVersion = require('../package.json').version;
@@ -64,66 +63,39 @@ const sdkVersion = require('../package.json').version;
6463
* const isValidWithAI = await verifyProof(proof, true);
6564
* ```
6665
*/
67-
export async function verifyProof(proofOrProofs: Proof | Proof[], allowAiWitness?: boolean): Promise<boolean> {
68-
// If input is an array of proofs
69-
if (Array.isArray(proofOrProofs)) {
70-
for (const proof of proofOrProofs) {
71-
const isVerified = await verifyProof(proof, allowAiWitness);
72-
if (!isVerified) {
73-
return false;
74-
}
75-
}
76-
return true;
77-
}
78-
79-
// Single proof verification logic
80-
const proof = proofOrProofs;
81-
if (!proof.signatures.length) {
82-
throw new SignatureNotFoundError('No signatures')
83-
}
84-
85-
try {
86-
// check if witness array exist and first element is ai-witness
87-
let witnesses = []
88-
if (proof.witnesses.length && proof.witnesses[0]?.url === 'ai-witness' && allowAiWitness === true) {
89-
witnesses.push(proof.witnesses[0].id)
90-
} else {
91-
witnesses = await getWitnessesForClaim(
92-
proof.claimData.epoch,
93-
proof.identifier,
94-
proof.claimData.timestampS
95-
)
96-
}
97-
// then hash the claim info with the encoded ctx to get the identifier
98-
const calculatedIdentifier = getIdentifierFromClaimInfo({
99-
parameters: JSON.parse(
100-
canonicalize(proof.claimData.parameters) as string
101-
),
102-
provider: proof.claimData.provider,
103-
context: proof.claimData.context
104-
})
105-
proof.identifier = replaceAll(proof.identifier, '"', '')
106-
// check if the identifier matches the one in the proof
107-
if (calculatedIdentifier !== proof.identifier) {
108-
throw new ProofNotVerifiedError('Identifier Mismatch')
109-
}
110-
111-
const signedClaim: SignedClaim = {
112-
claim: {
113-
...proof.claimData
114-
},
115-
signatures: proof.signatures.map(signature => {
116-
return ethers.getBytes(signature)
117-
})
118-
}
119-
120-
assertValidSignedClaim(signedClaim, witnesses)
121-
} catch (e: Error | unknown) {
122-
logger.info(`Error verifying proof: ${e instanceof Error ? e.message : String(e)}`)
123-
return false
124-
}
66+
export async function verifyProof(
67+
proofOrProofs: Proof | Proof[],
68+
allowAiWitness = false
69+
) {
70+
try {
71+
await assertValidProof(proofOrProofs, allowAiWitness)
72+
return true
73+
} catch (error) {
74+
logger.error('error in validating proof', error)
75+
return false
76+
}
77+
}
12578

126-
return true
79+
export async function assertValidProof(
80+
proofOrProofs: Proof | Proof[],
81+
allowAiWitness = false
82+
) {
83+
const attestors = await getAttestors()
84+
proofOrProofs = Array.isArray(proofOrProofs) ? proofOrProofs : [proofOrProofs]
85+
for (const proof of proofOrProofs) {
86+
const signers = recoverSignersOfSignedClaim({
87+
claim: proof.claimData,
88+
signatures: proof.signatures
89+
.map(signature => ethers.getBytes(signature))
90+
})
91+
// ensure at least one signer is an attestor
92+
if (
93+
!attestors
94+
.some(attestor => signers.includes(attestor.id.toLowerCase()))
95+
) {
96+
throw new ProofNotVerifiedError('Identifier mismatch')
97+
}
98+
}
12799
}
128100

129101
/**
@@ -214,7 +186,7 @@ export class ReclaimProofRequest {
214186
this.timeStamp = Date.now().toString();
215187
this.applicationId = applicationId;
216188
this.sessionId = "";
217-
// keep template data as empty object
189+
// keep template data as empty object
218190
this.templateData = emptyTemplateData;
219191
this.parameters = {};
220192

@@ -531,11 +503,11 @@ export class ReclaimProofRequest {
531503
/**
532504
* Sets a custom callback URL where proofs will be submitted via HTTP `POST`
533505
*
534-
* By default, proofs are sent as HTTP POST with `Content-Type` as `application/x-www-form-urlencoded`.
506+
* By default, proofs are sent as HTTP POST with `Content-Type` as `application/x-www-form-urlencoded`.
535507
* Pass function argument `jsonProofResponse` as `true` to send proofs with `Content-Type` as `application/json`.
536-
*
508+
*
537509
* When a custom callback URL is set, proofs are sent to the custom URL *instead* of the Reclaim backend.
538-
* Consequently, the startSession `onSuccess` callback will be invoked with an empty array (`[]`)
510+
* Consequently, the startSession `onSuccess` callback will be invoked with an empty array (`[]`)
539511
* instead of the proof data, as the proof is not available to the SDK in this flow.
540512
*
541513
* This verification session's id will be present in `X-Reclaim-Session-Id` header of the request.
@@ -570,7 +542,7 @@ export class ReclaimProofRequest {
570542
* `When `method` is set to `POST`, `body` will be sent with 'application/x-www-form-urlencoded' content type.
571543
* When `method` is set to `GET`, if `body` is set then `body` will be sent as query parameters.
572544
* Sending `body` on redirection is only supported in In-Browser SDK.
573-
*
545+
*
574546
* @throws {InvalidParamError} When URL is invalid
575547
*
576548
* @example
@@ -596,7 +568,7 @@ export class ReclaimProofRequest {
596568
* coordinate with your backend to receive errors.
597569
*
598570
* This verification session's id will be present in `X-Reclaim-Session-Id` header of the request.
599-
*
571+
*
600572
* Following is the data format which is sent as an HTTP POST request to the url with `Content-Type: application/json`:
601573
602574
* ```json
@@ -610,7 +582,7 @@ export class ReclaimProofRequest {
610582
* // [key: any]: any
611583
* }
612584
* ```
613-
*
585+
*
614586
* For more details about response format, check out [official documentation of Error Callback URL](https://docs.reclaimprotocol.org/js-sdk/preparing-request#cancel-callback).
615587
*
616588
* @param url - The URL where errors should be submitted via HTTP POST
@@ -620,9 +592,9 @@ export class ReclaimProofRequest {
620592
* ```typescript
621593
* proofRequest.setCancelCallbackUrl('https://your-backend.com/error-callback');
622594
* ```
623-
*
595+
*
624596
* @since 4.8.1
625-
*
597+
*
626598
*/
627599
setCancelCallbackUrl(url: string): void {
628600
validateURL(url, 'setCancelCallbackUrl')
@@ -645,9 +617,9 @@ export class ReclaimProofRequest {
645617
* ```typescript
646618
* proofRequest.setCancelRedirectUrl('https://your-app.com/error');
647619
* ```
648-
*
620+
*
649621
* @since 4.10.0
650-
*
622+
*
651623
*/
652624
setCancelRedirectUrl(url: string, method: HttpRedirectionMethod = 'GET', body?: HttpFormEntry[] | undefined): void {
653625
validateURL(url, 'setCancelRedirectUrl');
@@ -704,12 +676,12 @@ export class ReclaimProofRequest {
704676
* Sets additional context data to be stored with the claim
705677
*
706678
* This allows you to associate custom JSON serializable data with the proof claim.
707-
* The context can be retrieved and validated when verifying the proof.
708-
*
679+
* The context can be retrieved and validated when verifying the proof.
680+
*
709681
* Also see [setContext] which is an alternate way to set context that has an address & message.
710682
*
711683
* [setContext] and [setJsonContext] overwrite each other. Each call replaces the existing context.
712-
*
684+
*
713685
* @param context - Any additional data you want to store with the claim. Should be serializable to a JSON string.
714686
* @throws {SetContextError} When context parameters are invalid
715687
*
@@ -738,9 +710,9 @@ export class ReclaimProofRequest {
738710
* The context can be retrieved and validated when verifying the proof.
739711
*
740712
* Also see [setJsonContext] which is an alternate way to set context that allows for custom JSON serializable data.
741-
*
713+
*
742714
* [setContext] and [setJsonContext] overwrite each other. Each call replaces the existing context.
743-
*
715+
*
744716
* @param address - Context address identifier
745717
* @param message - Additional data to associate with the address
746718
* @throws {SetContextError} When context parameters are invalid
@@ -766,8 +738,8 @@ export class ReclaimProofRequest {
766738
/**
767739
* @deprecated use setContext instead
768740
*
769-
* @param address
770-
* @param message additional data you want associated with the [address]
741+
* @param address
742+
* @param message additional data you want associated with the [address]
771743
*/
772744
addContext(address: string, message: string): void {
773745
this.setContext(address, message);
@@ -976,7 +948,7 @@ export class ReclaimProofRequest {
976948
cancelRedirectUrl: this.cancelRedirectUrl,
977949
cancelRedirectUrlOptions: this.cancelRedirectUrlOptions,
978950
timestamp: this.timeStamp, // New field with correct spelling
979-
timeStamp: this.timeStamp, // @deprecated: Remove in future versions
951+
timeStamp: this.timeStamp, // @deprecated: Remove in future versions
980952
options: this.options,
981953
sdkVersion: this.sdkVersion,
982954
jsonProofResponse: this.jsonProofResponse,
@@ -995,7 +967,7 @@ export class ReclaimProofRequest {
995967

996968
/**
997969
* Validates signature and returns template data
998-
* @returns
970+
* @returns
999971
*/
1000972
private getTemplateData = (): TemplateData => {
1001973
if (!this.signature) {
@@ -1356,10 +1328,10 @@ export class ReclaimProofRequest {
13561328
* In the custom-callback flow (where the SDK submits a proof to a provided callback URL),
13571329
* onSuccess may be invoked with an empty array (onSuccess([])) when no proof is available
13581330
* (this happens when a callback is set using setAppCallbackUrl where proof is sent to callback instead of reclaim backend).
1359-
*
1331+
*
13601332
* Please refer to the OnSuccess type signature ((proof?: Proof | Proof[]) => void)
13611333
* and the startSession function source for more details.
1362-
*
1334+
*
13631335
* > [!TIP]
13641336
* > **Best Practice:** When using `setAppCallbackUrl` and/or `setCancelCallbackUrl`, your backend receives the proof or cancellation details directly. We recommend your backend notifies the frontend (e.g. via WebSockets, SSE, or polling) to stop the verification process and handle the appropriate success/failure action. Do not rely completely on `startSession` callbacks on the frontend when using these backend callbacks.
13651337
*
@@ -1431,7 +1403,7 @@ export class ReclaimProofRequest {
14311403
throw new ProofNotVerifiedError();
14321404
}
14331405
}
1434-
// check if the proofs array has only one proof then send the proofs in onSuccess
1406+
// check if the proofs array has only one proof then send the proofs in onSuccess
14351407
if (proofs.length === 1) {
14361408

14371409
onSuccess(proofs[0]);
@@ -1504,4 +1476,3 @@ export class ReclaimProofRequest {
15041476
return this.jsonProofResponse;
15051477
}
15061478
}
1507-

src/contract-types/config.json

Lines changed: 0 additions & 13 deletions
This file was deleted.

0 commit comments

Comments
 (0)