@oma3/omatrust 0.1.0-alpha.5 → 0.1.0-alpha.7

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/index.cjs CHANGED
@@ -385,6 +385,7 @@ __export(reputation_exports, {
385
385
  formatSchemaUid: () => formatSchemaUid,
386
386
  formatTransferAmount: () => formatTransferAmount,
387
387
  getAttestation: () => getAttestation,
388
+ getAttestationsByAttester: () => getAttestationsByAttester,
388
389
  getAttestationsForDid: () => getAttestationsForDid,
389
390
  getChainConstants: () => getChainConstants,
390
391
  getExplorerAddressUrl: () => getExplorerAddressUrl,
@@ -400,10 +401,12 @@ __export(reputation_exports, {
400
401
  normalizeSchema: () => normalizeSchema,
401
402
  parseDnsTxtRecord: () => parseDnsTxtRecord,
402
403
  prepareDelegatedAttestation: () => prepareDelegatedAttestation,
404
+ revokeAttestation: () => revokeAttestation,
403
405
  schemaToString: () => schemaToString,
404
406
  splitSignature: () => splitSignature,
405
407
  submitAttestation: () => submitAttestation,
406
408
  submitDelegatedAttestation: () => submitDelegatedAttestation,
409
+ validateAttestationData: () => validateAttestationData,
407
410
  verifyAttestation: () => verifyAttestation,
408
411
  verifyDidDocumentControllerDid: () => verifyDidDocumentControllerDid,
409
412
  verifyDnsTxtControllerDid: () => verifyDnsTxtControllerDid,
@@ -445,6 +448,13 @@ function encodeAttestationData(schema, data) {
445
448
  if (!data || typeof data !== "object") {
446
449
  throw new OmaTrustError("INVALID_INPUT", "data must be an object");
447
450
  }
451
+ const validationErrors = validateAttestationData(schema, data);
452
+ if (validationErrors.length > 0) {
453
+ const summary = validationErrors.map((error) => `Field "${error.schemaFieldName}" (${error.expectedType}) got ${error.providedType}`).join("; ");
454
+ throw new OmaTrustError("INVALID_INPUT", `Attestation data validation failed: ${summary}`, {
455
+ errors: validationErrors
456
+ });
457
+ }
448
458
  const fields = normalizeSchema(schema);
449
459
  const schemaString = schemaToString(fields);
450
460
  const encoder = new easSdk.SchemaEncoder(schemaString);
@@ -457,6 +467,99 @@ function encodeAttestationData(schema, data) {
457
467
  );
458
468
  return encoded;
459
469
  }
470
+ function getActualType(value) {
471
+ if (value === null) {
472
+ return "null";
473
+ }
474
+ if (value === void 0) {
475
+ return "undefined";
476
+ }
477
+ if (Array.isArray(value)) {
478
+ return "array";
479
+ }
480
+ if (typeof value === "number") {
481
+ return Number.isFinite(value) ? "number" : "non-finite-number";
482
+ }
483
+ return typeof value;
484
+ }
485
+ function isNumericValue(value, allowNegative) {
486
+ if (typeof value === "bigint") {
487
+ return allowNegative || value >= 0n;
488
+ }
489
+ if (typeof value === "number") {
490
+ if (!Number.isFinite(value) || !Number.isInteger(value)) {
491
+ return false;
492
+ }
493
+ return allowNegative || value >= 0;
494
+ }
495
+ if (typeof value === "string") {
496
+ if (value.length === 0) {
497
+ return false;
498
+ }
499
+ const pattern = allowNegative ? /^-?\d+$/ : /^\d+$/;
500
+ return pattern.test(value);
501
+ }
502
+ return false;
503
+ }
504
+ function isHex(value) {
505
+ return typeof value === "string" && /^0x[0-9a-fA-F]*$/.test(value);
506
+ }
507
+ function validateFieldValue(type, value) {
508
+ const normalizedType = type.trim().toLowerCase();
509
+ const bytesNMatch = normalizedType.match(/^bytes([1-9]|[12]\d|3[0-2])$/);
510
+ if (/^uint\d*$/.test(normalizedType)) {
511
+ return isNumericValue(value, false);
512
+ }
513
+ if (/^int\d*$/.test(normalizedType)) {
514
+ return isNumericValue(value, true);
515
+ }
516
+ if (normalizedType === "string") {
517
+ return typeof value === "string";
518
+ }
519
+ if (normalizedType === "string[]") {
520
+ return Array.isArray(value) && value.every((entry) => typeof entry === "string");
521
+ }
522
+ if (normalizedType === "bool") {
523
+ return typeof value === "boolean";
524
+ }
525
+ if (normalizedType === "address") {
526
+ return typeof value === "string" && ethers.isAddress(value);
527
+ }
528
+ if (normalizedType === "bytes") {
529
+ return isHex(value) && (value.length - 2) % 2 === 0;
530
+ }
531
+ if (bytesNMatch) {
532
+ const expectedBytes = Number(bytesNMatch[1]);
533
+ return isHex(value) && value.length === 2 + expectedBytes * 2;
534
+ }
535
+ return true;
536
+ }
537
+ function validateAttestationData(schema, data) {
538
+ if (!data || typeof data !== "object") {
539
+ return [{
540
+ schemaFieldName: "data",
541
+ expectedType: "object",
542
+ providedType: getActualType(data),
543
+ providedValue: data
544
+ }];
545
+ }
546
+ const fields = normalizeSchema(schema);
547
+ const errors = [];
548
+ for (const field of fields) {
549
+ const value = data[field.name];
550
+ const isValid = validateFieldValue(field.type, value);
551
+ if (isValid) {
552
+ continue;
553
+ }
554
+ errors.push({
555
+ schemaFieldName: field.name,
556
+ expectedType: field.type,
557
+ providedType: getActualType(value),
558
+ providedValue: value
559
+ });
560
+ }
561
+ return errors;
562
+ }
460
563
  function decodeAttestationData(schema, encodedData) {
461
564
  if (typeof encodedData !== "string" || !encodedData.startsWith("0x")) {
462
565
  throw new OmaTrustError("INVALID_INPUT", "encodedData must be a hex string");
@@ -477,22 +580,11 @@ function decodeAttestationData(schema, encodedData) {
477
580
  return result;
478
581
  }
479
582
  function extractExpirationTime(data) {
480
- const keys = ["expirationTime", "expiration", "validUntil", "expiresAt", "expires"];
481
- for (const key of keys) {
482
- const value = data[key];
483
- if (value === void 0 || value === null) {
484
- continue;
485
- }
486
- if (typeof value === "bigint") {
487
- return value;
488
- }
489
- if (typeof value === "number") {
490
- return value;
491
- }
492
- if (typeof value === "string" && /^\d+$/.test(value)) {
493
- return BigInt(value);
494
- }
495
- }
583
+ const value = data["expiresAt"];
584
+ if (value === void 0 || value === null) return void 0;
585
+ if (typeof value === "bigint") return value;
586
+ if (typeof value === "number") return value;
587
+ if (typeof value === "string" && /^\d+$/.test(value)) return BigInt(value);
496
588
  return void 0;
497
589
  }
498
590
  var ZERO_UID = "0x0000000000000000000000000000000000000000000000000000000000000000";
@@ -621,6 +713,34 @@ async function submitAttestation(params) {
621
713
  throw new OmaTrustError("NETWORK_ERROR", "Failed to submit attestation", { err });
622
714
  }
623
715
  }
716
+ async function revokeAttestation(params) {
717
+ if (!params || typeof params !== "object") {
718
+ throw new OmaTrustError("INVALID_INPUT", "params must be provided");
719
+ }
720
+ if (!params.signer) {
721
+ throw new OmaTrustError("INVALID_INPUT", "signer is required");
722
+ }
723
+ const eas = new easSdk.EAS(params.easContractAddress);
724
+ eas.connect(params.signer);
725
+ try {
726
+ const tx = await eas.revoke({
727
+ schema: params.schemaUid,
728
+ data: {
729
+ uid: params.uid,
730
+ value: toBigIntOrDefault(params.value, 0n)
731
+ }
732
+ });
733
+ await tx.wait();
734
+ const txHash = getEasTransactionHash(tx) ?? ZERO_UID;
735
+ const receipt = getEasTransactionReceipt(tx);
736
+ return {
737
+ txHash,
738
+ receipt
739
+ };
740
+ } catch (err) {
741
+ throw new OmaTrustError("NETWORK_ERROR", "Failed to revoke attestation", { err });
742
+ }
743
+ }
624
744
  function buildDelegatedTypedData(params) {
625
745
  return {
626
746
  domain: {
@@ -821,21 +941,18 @@ async function getAttestation(params) {
821
941
  throw new OmaTrustError("NETWORK_ERROR", "Failed to read attestation", { err });
822
942
  }
823
943
  }
824
- async function getAttestationsForDid(params) {
825
- const provider = params.provider;
826
- const contract = new ethers.Contract(params.easContractAddress, EAS_EVENT_ABI, provider);
827
- const toBlock = params.toBlock ?? await provider.getBlockNumber();
828
- const fromBlock = params.fromBlock ?? Math.max(0, toBlock - 5e4);
829
- const filter = contract.filters.Attested(didToAddress(params.did));
944
+ async function queryAttestationEvents(easContractAddress, provider, fromBlock, toBlock, options) {
945
+ const contract = new ethers.Contract(easContractAddress, EAS_EVENT_ABI, provider);
946
+ const filter = contract.filters.Attested(options?.recipient ?? null, options?.attester ?? null);
830
947
  let events;
831
948
  try {
832
949
  events = await contract.queryFilter(filter, fromBlock, toBlock);
833
950
  } catch (err) {
834
951
  throw new OmaTrustError("NETWORK_ERROR", "Failed to query attestation events", { err });
835
952
  }
836
- const eas = new easSdk.EAS(params.easContractAddress);
953
+ const eas = new easSdk.EAS(easContractAddress);
837
954
  eas.connect(provider);
838
- const schemaFilter = params.schemas?.map((schema) => schema.toLowerCase());
955
+ const schemaFilter = options?.schemas?.map((s) => s.toLowerCase());
839
956
  const results = [];
840
957
  for (const event of events) {
841
958
  if (!("args" in event && Array.isArray(event.args))) {
@@ -859,6 +976,34 @@ async function getAttestationsForDid(params) {
859
976
  results.sort((a, b) => Number(b.time - a.time));
860
977
  return results;
861
978
  }
979
+ async function getAttestationsForDid(params) {
980
+ const provider = params.provider;
981
+ const toBlock = params.toBlock ?? await provider.getBlockNumber();
982
+ const fromBlock = params.fromBlock ?? Math.max(0, toBlock - 5e4);
983
+ return queryAttestationEvents(
984
+ params.easContractAddress,
985
+ provider,
986
+ fromBlock,
987
+ toBlock,
988
+ { recipient: didToAddress(params.did), schemas: params.schemas }
989
+ );
990
+ }
991
+ async function getAttestationsByAttester(params) {
992
+ const provider = params.provider;
993
+ const toBlock = params.toBlock ?? await provider.getBlockNumber();
994
+ const fromBlock = params.fromBlock ?? Math.max(0, toBlock - 5e4);
995
+ if (params.limit !== void 0 && params.limit <= 0) {
996
+ return [];
997
+ }
998
+ const results = await queryAttestationEvents(
999
+ params.easContractAddress,
1000
+ provider,
1001
+ fromBlock,
1002
+ toBlock,
1003
+ { attester: params.attester, schemas: params.schemas }
1004
+ );
1005
+ return params.limit !== void 0 ? results.slice(0, params.limit) : results;
1006
+ }
862
1007
  async function listAttestations(params) {
863
1008
  const limit = params.limit ?? 20;
864
1009
  if (limit <= 0) {
@@ -869,34 +1014,15 @@ async function listAttestations(params) {
869
1014
  }
870
1015
  async function getLatestAttestations(params) {
871
1016
  const provider = params.provider;
872
- const contract = new ethers.Contract(params.easContractAddress, EAS_EVENT_ABI, provider);
873
- const currentBlock = await provider.getBlockNumber();
874
- const fromBlock = params.fromBlock ?? Math.max(0, currentBlock - 5e4);
875
- const events = await contract.queryFilter(contract.filters.Attested(), fromBlock, currentBlock);
876
- const eas = new easSdk.EAS(params.easContractAddress);
877
- eas.connect(provider);
878
- const schemaFilter = params.schemas?.map((schema) => schema.toLowerCase());
879
- const results = [];
880
- for (const event of events) {
881
- if (!("args" in event && Array.isArray(event.args))) {
882
- continue;
883
- }
884
- const args = event.args;
885
- const uid = args?.[2];
886
- const schemaUid = args?.[3];
887
- if (!uid || !schemaUid) {
888
- continue;
889
- }
890
- if (schemaFilter && !schemaFilter.includes(schemaUid.toLowerCase())) {
891
- continue;
892
- }
893
- const attestation = await eas.getAttestation(uid);
894
- if (!attestation || !attestation.uid) {
895
- continue;
896
- }
897
- results.push(parseAttestation(attestation, void 0, parseEventTxHash(event)));
898
- }
899
- results.sort((a, b) => Number(b.time - a.time));
1017
+ const toBlock = await provider.getBlockNumber();
1018
+ const fromBlock = params.fromBlock ?? Math.max(0, toBlock - 5e4);
1019
+ const results = await queryAttestationEvents(
1020
+ params.easContractAddress,
1021
+ provider,
1022
+ fromBlock,
1023
+ toBlock,
1024
+ { schemas: params.schemas }
1025
+ );
900
1026
  return results.slice(0, params.limit ?? 20);
901
1027
  }
902
1028
  function deduplicateReviews(attestations) {