@notabene/verify-proof 1.11.1-next.1 → 1.12.0-next.12

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.
Files changed (85) hide show
  1. package/dist/{bitcoin-3CW4MNAW.cjs → cjs/bitcoin-UIEQV3IM.cjs} +105 -16
  2. package/dist/cjs/bitcoin-UIEQV3IM.cjs.map +1 -0
  3. package/dist/{cardano-DYBYEAAF.cjs → cjs/cardano-QG2S452K.cjs} +5 -22
  4. package/dist/cjs/cardano-QG2S452K.cjs.map +1 -0
  5. package/dist/cjs/concordium-4B33UJJ5.cjs +44 -0
  6. package/dist/cjs/concordium-4B33UJJ5.cjs.map +1 -0
  7. package/dist/cjs/cosmos-JTT3AZCF.cjs +92 -0
  8. package/dist/cjs/cosmos-JTT3AZCF.cjs.map +1 -0
  9. package/dist/{eth-3DX3PXDU.cjs → cjs/eth-BVXX47HH.cjs} +2 -3
  10. package/dist/cjs/eth-BVXX47HH.cjs.map +1 -0
  11. package/dist/{index.cjs → cjs/index.cjs} +10 -12
  12. package/dist/cjs/index.cjs.map +1 -0
  13. package/dist/{solana-PQ5K4NGO.cjs → cjs/solana-4WNBEQSU.cjs} +6 -23
  14. package/dist/cjs/solana-4WNBEQSU.cjs.map +1 -0
  15. package/dist/{tron-F5AARBY4.cjs → cjs/tron-IM2O2VLM.cjs} +2 -3
  16. package/dist/cjs/tron-IM2O2VLM.cjs.map +1 -0
  17. package/dist/{xlm-5GODWWL2.cjs → cjs/xlm-CHT7RN4Z.cjs} +2 -3
  18. package/dist/cjs/xlm-CHT7RN4Z.cjs.map +1 -0
  19. package/dist/cjs/xrpl-HJ2XWSOO.cjs +74 -0
  20. package/dist/cjs/xrpl-HJ2XWSOO.cjs.map +1 -0
  21. package/dist/{bitcoin-QK53ILBF.js → esm/bitcoin-BTZ4TXEK.js} +105 -16
  22. package/dist/esm/bitcoin-BTZ4TXEK.js.map +1 -0
  23. package/dist/{cardano-WE6YXYLW.js → esm/cardano-OMGAPH5N.js} +4 -5
  24. package/dist/esm/cardano-OMGAPH5N.js.map +1 -0
  25. package/dist/esm/concordium-JJ5VEIOA.js +42 -0
  26. package/dist/esm/concordium-JJ5VEIOA.js.map +1 -0
  27. package/dist/esm/cosmos-AVIWAIX7.js +90 -0
  28. package/dist/esm/cosmos-AVIWAIX7.js.map +1 -0
  29. package/dist/{eth-ICLGRJE5.js → esm/eth-GI4Z5V4T.js} +2 -3
  30. package/dist/esm/eth-GI4Z5V4T.js.map +1 -0
  31. package/dist/{index.js → esm/index.js} +10 -12
  32. package/dist/esm/index.js.map +1 -0
  33. package/dist/{solana-4KQFLZUC.js → esm/solana-ZARDAF6O.js} +3 -4
  34. package/dist/esm/solana-ZARDAF6O.js.map +1 -0
  35. package/dist/{tron-OBLPB2LN.js → esm/tron-FI2B6DRS.js} +2 -3
  36. package/dist/esm/tron-FI2B6DRS.js.map +1 -0
  37. package/dist/{xlm-GX2QGFLI.js → esm/xlm-TNRZ5CFC.js} +2 -3
  38. package/dist/esm/xlm-TNRZ5CFC.js.map +1 -0
  39. package/dist/esm/xrpl-52IBJ4EW.js +69 -0
  40. package/dist/esm/xrpl-52IBJ4EW.js.map +1 -0
  41. package/package.json +21 -9
  42. package/src/bitcoin.ts +43 -19
  43. package/src/cardano.ts +2 -2
  44. package/src/cashaddr.ts +157 -0
  45. package/src/concordium.ts +34 -283
  46. package/src/cosmos.ts +44 -6
  47. package/src/index.ts +0 -1
  48. package/src/solana.ts +1 -1
  49. package/src/tests/bitcoin.test.ts +527 -16
  50. package/src/tests/concordium.test.ts +96 -134
  51. package/src/tests/cosmos.test.ts +139 -0
  52. package/src/tests/index.test.ts +7 -7
  53. package/src/tests/xrpl.test.ts +8 -6
  54. package/dist/bitcoin-3CW4MNAW.cjs.map +0 -1
  55. package/dist/bitcoin-QK53ILBF.js.map +0 -1
  56. package/dist/cardano-DYBYEAAF.cjs.map +0 -1
  57. package/dist/cardano-WE6YXYLW.js.map +0 -1
  58. package/dist/chunk-E3V5ATTC.js +0 -38
  59. package/dist/chunk-E3V5ATTC.js.map +0 -1
  60. package/dist/chunk-OAXNH5XR.cjs +0 -42
  61. package/dist/chunk-OAXNH5XR.cjs.map +0 -1
  62. package/dist/concordium-HQC37GCK.cjs +0 -188
  63. package/dist/concordium-HQC37GCK.cjs.map +0 -1
  64. package/dist/concordium-XX4XYLLU.js +0 -186
  65. package/dist/concordium-XX4XYLLU.js.map +0 -1
  66. package/dist/cosmos-64MKE5FJ.cjs +0 -683
  67. package/dist/cosmos-64MKE5FJ.cjs.map +0 -1
  68. package/dist/cosmos-QMH7BK7S.js +0 -681
  69. package/dist/cosmos-QMH7BK7S.js.map +0 -1
  70. package/dist/eth-3DX3PXDU.cjs.map +0 -1
  71. package/dist/eth-ICLGRJE5.js.map +0 -1
  72. package/dist/index.cjs.map +0 -1
  73. package/dist/index.js.map +0 -1
  74. package/dist/solana-4KQFLZUC.js.map +0 -1
  75. package/dist/solana-PQ5K4NGO.cjs.map +0 -1
  76. package/dist/tron-F5AARBY4.cjs.map +0 -1
  77. package/dist/tron-OBLPB2LN.js.map +0 -1
  78. package/dist/xlm-5GODWWL2.cjs.map +0 -1
  79. package/dist/xlm-GX2QGFLI.js.map +0 -1
  80. package/dist/xrpl-7HQLIDAK.cjs +0 -1174
  81. package/dist/xrpl-7HQLIDAK.cjs.map +0 -1
  82. package/dist/xrpl-YCDFXBGQ.js +0 -1169
  83. package/dist/xrpl-YCDFXBGQ.js.map +0 -1
  84. /package/dist/{index.d.cts → cjs/index.d.cts} +0 -0
  85. /package/dist/{index.d.ts → esm/index.d.ts} +0 -0
@@ -7,216 +7,178 @@ import {
7
7
  } from "@notabene/javascript-sdk";
8
8
 
9
9
  describe("verifyConcordiumSignature", () => {
10
- // Test with valid signature against mainnet (makes network calls)
11
- it("returns verified proof when valid message and address on mainnet", async () => {
10
+ it("returns verified proof when valid presentation on testnet", async () => {
11
+ const proof: SignatureProof = {
12
+ "address": "ccd:9dd9ca4d19e9393877d2c44b70f89acb:3Soqc3mEU5WC4R9Qho9fxm4CJ1157q6qsJbPvtGV8iT8FbQdv2",
13
+ "attestation": "b74a8e64f1568f1fb22a57b033bc8ef2b8f6ba23ff8e831e7abfbb671927fda1",
14
+ "type": ProofTypes.CONCORDIUM,
15
+ "did": "did:pkh:ccd:9dd9ca4d19e9393877d2c44b70f89acb:3Soqc3mEU5WC4R9Qho9fxm4CJ1157q6qsJbPvtGV8iT8FbQdv2",
16
+ "proof": "{\"presentationContext\":\"b74a8e64f1568f1fb22a57b033bc8ef2b8f6ba23ff8e831e7abfbb671927fda1\",\"proof\":{\"created\":\"2025-12-10T10:39:14.395Z\",\"proofValue\":[],\"type\":\"ConcordiumWeakLinkingProofV1\"},\"type\":\"VerifiablePresentation\",\"verifiableCredential\":[{\"credentialSubject\":{\"id\":\"did:ccd:mainnet:cred:91a1f28bc42222096856a54fb157f7c80b9827457d4ece682b9592bca964948f01dce51a7deb392ea9bd0c1e1630d17b\",\"proof\":{\"created\":\"2025-12-10T10:39:14.395Z\",\"proofValue\":[{\"proof\":\"988f08d03bc8adaac4d51986dfaafe70874ab3bb22e8c09c32da5bfcd0ff0407203770533220e74ba4386acb36f7b7288e38c461279f7edf6f41b8b285d629280a5ca297e7fc42155222c5b1ad3cc74f770d5c87addbba6935ade425460b1616a587d9c45a4676f7fc751b31110cd37b25998c61d7d85c84e4db155491665e556778a9784e557799f06531bafe6b4b8ca2ce386d66f7759079eaff74b1e519550c9d137a13851c0987ee434feb6dae0ca659d67661b27e92d7cca9567a1a6ecd2175c574f5a6c2f4691597cbf3680f65abab72633d050746211c56961277064d694a31c2a93ef3b64c4957ff8261978a53d8b65d40ff23ddc7ee65d0ea0817702be58fbaec3954322e00667c6c94736eba8d3aa3f2686b89f257ca34c90ae1200000000785c57df969a45b25b1d39bdb388d33a756147e98f285891e83ce58eab3bb1f466c25a0946fc62513b16f3f02397b15418ebc131b5e1a8c0f05d6983cd3c44cc40ab8364c1aa209c2e8c0e8e84694587053542fd5cbb918f025723a5a0c200f08875728874571f50cb8b54d1c8629a10c76f0a982ad667efcfa280943f7c8753d3fa859a8d5d9837e6bdd5026d54546a3ae5918055208b5d2f77e0206d7861b4c472c634ec4cece107aeb14c42fe3d801aba38aa38e15785152e7c061561a5594a6cabb34f469b3121c15437df5d6ba0638ba3a192f2106d07e2f7bfd73310f669d3e8bdeb1b43244455d7bd7fa5917a1af2b23dc3433dac68ee4571bea2b0c22ce2ed665e22cee5676b9c3de0169926e72c847f7e3f2caa671e55ab5c4530205845b08ee12bba954f4a41e5638b05043a93ed212f402273c2b477f95f7b82ddbe4621f1758f80fcec726df755a76d0f585eda201dff2b91147cca5eae5d5319b7e1438c0f4af42b9fe4f7e845d0c643328ddd5dead96bfd345ae972312650a9ab6e6d7fa3d3f5d1fe68e5ff513095e3caa5bb21bec64dae007e62b4494986ac40b9e14b61255a84ea51780b8439adaeeae0b83a8bcee382491dd8e7b2f1921e8eeffe39a45bffd470b5a8f74d82ccdb8ccda651c387844f61704cc04f51d65fb9069900cb1febfc0b2ba02ffc857c45c12a7b306440e6627995d67353e9f6327b6f6cfa6ad0b859ea904f087a5b29a888043ba21ccb3e36da0a2da797310c2f2ce56c275d6fc48b60aade4b4e6bb6ff62d5f5be1a529c8d71cab2b0904fa306cb779a897872f5f047df7c7bee150ca6be6f3ad840a862ecc0793bb27f0594ff8741a4ab426b53d72acbdbde6c20a7c4399ca181d81a4b0ac437c23220f52ff8e9095ae35a53f8cd58913c4999a8153b656fabb162feafe8fc8708eaeb2b5ce0d347e5733cd685783271eaf564e05efce61996686ee9f50663204841ff30416061721a5cab8e1c80708809b58d2bc9c402da453e486ce08e0ec6c72c1f0e9dc15\",\"type\":\"AttributeInRange\"}],\"type\":\"ConcordiumZKProofV3\"},\"statement\":[{\"attributeTag\":\"dob\",\"lower\":\"19300101\",\"type\":\"AttributeInRange\",\"upper\":\"99990101\"}]},\"issuer\":\"did:ccd:mainnet:idp:1\",\"type\":[\"VerifiableCredential\",\"ConcordiumVerifiableCredential\"]}]}",
17
+ "wallet_provider": "Concordium Browser",
18
+ "status": ProofStatus.PENDING
19
+ };
20
+
21
+ const result = await verifyConcordiumSignature(proof);
22
+
23
+ expect(result.status).toBe(ProofStatus.VERIFIED);
24
+ }, 15000);
25
+
26
+ it("returns failed proof when proof field contains invalid JSON", async () => {
12
27
  const proof: SignatureProof = {
13
28
  address:
14
29
  "ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
15
30
  attestation:
16
- "I certify that\n\nccd:9dd9ca4d19e9393877d2c44b70f89acb account 3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF\n\nbelonged to did:key:z6MksamQq4oVRktkeSDxs6pbixYFUaUca8xgCvnTVLQA5PC5\n\non Thu, 12 Jun 2025 09:20:01 GMT",
31
+ "d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983",
17
32
  type: ProofTypes.CONCORDIUM,
18
- did: "did:key:z6MksamQq4oVRktkeSDxs6pbixYFUaUca8xgCvnTVLQA5PC5",
19
- proof:
20
- '{"0":{"0":"9b7263696072d4c5a0e060fec77bee5cb62ca9c8b674be864893f9d1dab75d28bf435efba9d4651ea1effdbd5b000f44d0d5be0fb10a11b3626a9a7be52e0d0d"}}',
33
+ did: "did:pkh:ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
34
+ proof: "invalid json string",
35
+ wallet_provider: "Concordium Browser",
21
36
  status: ProofStatus.PENDING,
22
- wallet_provider: "Concordium Wallet",
23
37
  };
24
-
25
- // Test against mainnet (makes network calls, calls isValidSignature)
26
- const result = await verifyConcordiumSignature(proof, {
27
- network: "mainnet",
28
- testMode: false,
29
- timeout: 10000 // 10 second timeout for tests
30
- });
31
-
32
- // This should either be VERIFIED (if account exists and signature is valid)
33
- // or FAILED (if account doesn't exist or signature is invalid)
34
- expect([ProofStatus.VERIFIED, ProofStatus.FAILED]).toContain(result.status);
35
- }, 15000); // 15 second test timeout
36
-
37
- // Test with valid signature against testnet (makes network calls)
38
- it("returns verified proof when valid message and address on testnet", async () => {
38
+
39
+ const result = await verifyConcordiumSignature(proof);
40
+ expect(result.status).toBe(ProofStatus.FAILED);
41
+ });
42
+
43
+ it("returns failed proof when proof field is empty string", async () => {
39
44
  const proof: SignatureProof = {
40
45
  address:
41
- "ccd:testnet:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
46
+ "ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
42
47
  attestation:
43
- "I certify that\n\nccd:testnet account 3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF\n\nbelonged to did:key:z6MksamQq4oVRktkeSDxs6pbixYFUaUca8xgCvnTVLQA5PC5\n\non Thu, 12 Jun 2025 09:20:01 GMT",
48
+ "d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983",
44
49
  type: ProofTypes.CONCORDIUM,
45
- did: "did:key:z6MksamQq4oVRktkeSDxs6pbixYFUaUca8xgCvnTVLQA5PC5",
46
- proof:
47
- '{"0":{"0":"9b7263696072d4c5a0e060fec77bee5cb62ca9c8b674be864893f9d1dab75d28bf435efba9d4651ea1effdbd5b000f44d0d5be0fb10a11b3626a9a7be52e0d0d"}}',
50
+ did: "did:pkh:ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
51
+ proof: "",
52
+ wallet_provider: "Concordium Browser",
48
53
  status: ProofStatus.PENDING,
49
- wallet_provider: "Concordium Wallet",
50
54
  };
51
-
52
- // Test against testnet (makes network calls, calls isValidSignature)
53
- const result = await verifyConcordiumSignature(proof, {
54
- network: "testnet",
55
- testMode: false,
56
- timeout: 10000 // 10 second timeout for tests
57
- });
58
-
59
- // This should either be VERIFIED (if account exists and signature is valid)
60
- // or FAILED (if account doesn't exist or signature is invalid)
61
- expect([ProofStatus.VERIFIED, ProofStatus.FAILED]).toContain(result.status);
62
- }, 15000); // 15 second test timeout
63
-
64
- // Test with non-existent account on mainnet (should fail but make network calls)
65
- it("returns failed proof when account is not found on mainnet", async () => {
55
+
56
+ const result = await verifyConcordiumSignature(proof);
57
+ expect(result.status).toBe(ProofStatus.FAILED);
58
+ });
59
+
60
+ it("returns failed proof when proof field is empty object", async () => {
66
61
  const proof: SignatureProof = {
67
62
  address:
68
63
  "ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
69
64
  attestation:
70
- "I certify that\n\nccd:9dd9ca4d19e9393877d2c44b70f89acb account 3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF\n\nbelonged to did:key:z6MksamQq4oVRktkeSDxs6pbixYFUaUca8xgCvnTVLQA5PC5\n\non Thu, 12 Jun 2025 09:20:01 GMT",
65
+ "d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983",
71
66
  type: ProofTypes.CONCORDIUM,
72
- did: "did:key:z6MksamQq4oVRktkeSDxs6pbixYFUaUca8xgCvnTVLQA5PC5",
73
- proof:
74
- '{"0":{"0":"9b7263696072d4c5a0e060fec77bee5cb62ca9c8b674be864893f9d1dab75d28bf435efba9d4651ea1effdbd5b000f44d0d5be0fb10a11b3626a9a7be52e0d0d"}}',
67
+ did: "did:pkh:ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
68
+ proof: "{}",
69
+ wallet_provider: "Concordium Browser",
75
70
  status: ProofStatus.PENDING,
76
- wallet_provider: "Concordium Wallet",
77
71
  };
78
-
79
- // Test against mainnet (makes network calls, calls isValidSignature)
80
- const result = await verifyConcordiumSignature(proof, {
81
- network: "mainnet",
82
- testMode: false,
83
- timeout: 10000
84
- });
85
72
 
73
+ const result = await verifyConcordiumSignature(proof);
86
74
  expect(result.status).toBe(ProofStatus.FAILED);
87
- }, 15000);
75
+ });
88
76
 
89
- // Test with non-existent account on testnet (should fail but make network calls)
90
- it("returns failed proof when account is not found on testnet", async () => {
77
+ it("returns failed proof when presentation is missing verifiableCredential", async () => {
91
78
  const proof: SignatureProof = {
92
79
  address:
93
- "ccd:testnet:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
80
+ "ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
94
81
  attestation:
95
- "I certify that\n\nccd:testnet account 3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF\n\nbelonged to did:key:z6MksamQq4oVRktkeSDxs6pbixYFUaUca8xgCvnTVLQA5PC5\n\non Thu, 12 Jun 2025 09:20:01 GMT",
82
+ "d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983",
96
83
  type: ProofTypes.CONCORDIUM,
97
- did: "did:key:z6MksamQq4oVRktkeSDxs6pbixYFUaUca8xgCvnTVLQA5PC5",
84
+ did: "did:pkh:ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
98
85
  proof:
99
- '{"0":{"0":"9b7263696072d4c5a0e060fec77bee5cb62ca9c8b674be864893f9d1dab75d28bf435efba9d4651ea1effdbd5b000f44d0d5be0fb10a11b3626a9a7be52e0d0d"}}',
86
+ '{"presentationContext":"d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983","proof":{"created":"2025-11-22T15:53:04.074Z","proofValue":[],"type":"ConcordiumWeakLinkingProofV1"},"type":"VerifiablePresentation"}',
87
+ wallet_provider: "Concordium Browser",
100
88
  status: ProofStatus.PENDING,
101
- wallet_provider: "Concordium Wallet",
102
89
  };
103
-
104
- // Test against testnet (makes network calls, calls isValidSignature)
105
- const result = await verifyConcordiumSignature(proof, {
106
- network: "testnet",
107
- testMode: true,
108
- timeout: 10000
109
- });
110
90
 
111
- expect(result.status).toBe(ProofStatus.VERIFIED);
112
- }, 15000);
91
+ const result = await verifyConcordiumSignature(proof);
92
+ expect(result.status).toBe(ProofStatus.FAILED);
93
+ });
113
94
 
114
- // Test network connectivity and timeout handling
115
- it("handles network timeouts gracefully", async () => {
95
+ it("returns failed proof when presentation has empty verifiableCredential array", async () => {
116
96
  const proof: SignatureProof = {
117
97
  address:
118
98
  "ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
119
99
  attestation:
120
- "I certify that\n\nccd:9dd9ca4d19e9393877d2c44b70f89acb account 3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF\n\nbelonged to did:key:z6MksamQq4oVRktkeSDxs6pbixYFUaUca8xgCvnTVLQA5PC5\n\non Thu, 12 Jun 2025 09:20:01 GMT",
100
+ "d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983",
121
101
  type: ProofTypes.CONCORDIUM,
122
- did: "did:key:z6MksamQq4oVRktkeSDxs6pbixYFUaUca8xgCvnTVLQA5PC5",
102
+ did: "did:pkh:ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
123
103
  proof:
124
- '{"0":{"0":"9b7263696072d4c5a0e060fec77bee5cb62ca9c8b674be864893f9d1dab75d28bf435efba9d4651ea1effdbd5b000f44d0d5be0fb10a11b3626a9a7be52e0d0d"}}',
104
+ '{"presentationContext":"d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983","proof":{"created":"2025-11-22T15:53:04.074Z","proofValue":[],"type":"ConcordiumWeakLinkingProofV1"},"type":"VerifiablePresentation","verifiableCredential":[]}',
105
+ wallet_provider: "Concordium Browser",
125
106
  status: ProofStatus.PENDING,
126
- wallet_provider: "Concordium Wallet",
127
107
  };
128
-
129
- // Test with very short timeout to trigger timeout handling
130
- const result = await verifyConcordiumSignature(proof, {
131
- network: "mainnet",
132
- testMode: false,
133
- timeout: 1, // 1ms timeout to force timeout
134
- retries: 1
135
- });
136
108
 
109
+ const result = await verifyConcordiumSignature(proof);
137
110
  expect(result.status).toBe(ProofStatus.FAILED);
138
- }, 10000);
111
+ });
139
112
 
140
- // Test mode tests (for comparison - these don't make network calls)
141
- it("returns failed proof when invalid message and address in test mode", async () => {
113
+ it("returns failed proof when presentation is missing presentationContext", async () => {
142
114
  const proof: SignatureProof = {
143
115
  address:
144
116
  "ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
145
117
  attestation:
146
- "I certify that\n\nccd:9dd9ca4d19e9393877d2c44b70f89acb account 3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF\n\nbelonged to did:key:z6MksamQq4oVRktkeSDxs6pbixYFUaUca8xgCvnTVLQA5PC5\n\non Thu, 12 Jun 2025 09:20:01 GMT",
147
- proof: '{}',
148
- did: "did:key:z6MksamQq4oVRktkeSDxs6pbixYFUaUca8xgCvnTVLQA5PC5",
149
- status: ProofStatus.PENDING,
150
- wallet_provider: "Concordium Wallet",
118
+ "d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983",
151
119
  type: ProofTypes.CONCORDIUM,
120
+ did: "did:pkh:ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
121
+ proof:
122
+ '{"proof":{"created":"2025-11-22T15:53:04.074Z","proofValue":[],"type":"ConcordiumWeakLinkingProofV1"},"type":"VerifiablePresentation","verifiableCredential":[{"credentialSubject":{"id":"did:ccd:testnet:cred:8f73851550a5d2c2ed4df215731cf9e3f33614d4be6c1c336f0f8858522c94afa34a759258a2b3281f9bacd0a8a3cd09","proof":{"created":"2025-11-22T15:53:04.074Z","proofValue":[{"proof":"test","type":"AttributeInRange"}],"type":"ConcordiumZKProofV3"},"statement":[{"attributeTag":"dob","lower":"19300101","type":"AttributeInRange","upper":"99990101"}]},"issuer":"did:ccd:testnet:idp:0","type":["VerifiableCredential","ConcordiumVerifiableCredential"]}]}',
123
+ wallet_provider: "Concordium Browser",
124
+ status: ProofStatus.PENDING,
152
125
  };
153
126
 
154
- // Use test mode to skip network calls
155
- const result = await verifyConcordiumSignature(proof, { testMode: true });
156
-
127
+ const result = await verifyConcordiumSignature(proof);
157
128
  expect(result.status).toBe(ProofStatus.FAILED);
158
129
  });
159
130
 
160
- it("handles invalid signature format in test mode", async () => {
131
+ it("returns failed proof when credential is missing credentialSubject", async () => {
161
132
  const proof: SignatureProof = {
162
133
  address:
163
134
  "ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
164
135
  attestation:
165
- "I certify that\n\nccd:9dd9ca4d19e9393877d2c44b70f89acb account 3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF\n\nbelonged to did:key:z6MksamQq4oVRktkeSDxs6pbixYFUaUca8xgCvnTVLQA5PC5\n\non Thu, 12 Jun 2025 09:20:01 GMT",
166
- proof: 'invalid json',
167
- did: "did:key:z6MksamQq4oVRktkeSDxs6pbixYFUaUca8xgCvnTVLQA5PC5",
168
- status: ProofStatus.PENDING,
169
- wallet_provider: "Concordium Wallet",
136
+ "d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983",
170
137
  type: ProofTypes.CONCORDIUM,
138
+ did: "did:pkh:ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
139
+ proof:
140
+ '{"presentationContext":"d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983","proof":{"created":"2025-11-22T15:53:04.074Z","proofValue":[],"type":"ConcordiumWeakLinkingProofV1"},"type":"VerifiablePresentation","verifiableCredential":[{"issuer":"did:ccd:testnet:idp:0","type":["VerifiableCredential","ConcordiumVerifiableCredential"]}]}',
141
+ wallet_provider: "Concordium Browser",
142
+ status: ProofStatus.PENDING,
171
143
  };
172
144
 
173
- // Use test mode to skip network calls
174
- const result = await verifyConcordiumSignature(proof, { testMode: true });
175
-
145
+ const result = await verifyConcordiumSignature(proof);
176
146
  expect(result.status).toBe(ProofStatus.FAILED);
177
147
  });
178
148
 
179
- it("handles non-concordium address", async () => {
149
+ it("returns failed proof with tampered proof signature", async () => {
180
150
  const proof: SignatureProof = {
181
- address: "eth:mainnet:0x1234567890abcdef",
182
- attestation: "test message",
183
- proof: '{"0":{"0":"9b7263696072d4c5a0e060fec77bee5cb62ca9c8b674be864893f9d1dab75d28bf435efba9d4651ea1effdbd5b000f44d0d5be0fb10a11b3626a9a7be52e0d0d"}}',
184
- did: "did:key:test",
185
- status: ProofStatus.PENDING,
186
- wallet_provider: "Test Wallet",
151
+ address:
152
+ "ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
153
+ attestation:
154
+ "d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983",
187
155
  type: ProofTypes.CONCORDIUM,
156
+ did: "did:pkh:ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
157
+ proof:
158
+ '{"presentationContext":"d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983","proof":{"created":"2025-11-22T15:53:04.074Z","proofValue":[],"type":"ConcordiumWeakLinkingProofV1"},"type":"VerifiablePresentation","verifiableCredential":[{"credentialSubject":{"id":"did:ccd:testnet:cred:8f73851550a5d2c2ed4df215731cf9e3f33614d4be6c1c336f0f8858522c94afa34a759258a2b3281f9bacd0a8a3cd09","proof":{"created":"2025-11-22T15:53:04.074Z","proofValue":[{"proof":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","type":"AttributeInRange"}],"type":"ConcordiumZKProofV3"},"statement":[{"attributeTag":"dob","lower":"19300101","type":"AttributeInRange","upper":"99990101"}]},"issuer":"did:ccd:testnet:idp:0","type":["VerifiableCredential","ConcordiumVerifiableCredential"]}]}',
159
+ wallet_provider: "Concordium Browser",
160
+ status: ProofStatus.PENDING,
188
161
  };
189
162
 
190
- const result = await verifyConcordiumSignature(proof, { testMode: true });
191
-
163
+ const result = await verifyConcordiumSignature(proof);
192
164
  expect(result.status).toBe(ProofStatus.FAILED);
193
- });
165
+ }, 15000);
194
166
 
195
- // Test with a known valid account on mainnet (if available)
196
- it("tests with known valid mainnet account", async () => {
197
- // This test uses a potentially valid account address for testing
198
- // In a real scenario, you'd want to use an account that actually exists
167
+ it("returns failed proof with mismatched presentationContext and attestation", async () => {
199
168
  const proof: SignatureProof = {
200
169
  address:
201
- "ccd:9dd9ca4d19e9393877d2c44b70f89acb:4hVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoG",
170
+ "ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
202
171
  attestation:
203
- "I certify that\n\nccd:9dd9ca4d19e9393877d2c44b70f89acb account 4hVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoG\n\nbelonged to did:key:z6MksamQq4oVRktkeSDxs6pbixYFUaUca8xgCvnTVLQA5PC5\n\non Thu, 12 Jun 2025 09:20:01 GMT",
172
+ "0000000000000000000000000000000000000000000000000000000000000000",
204
173
  type: ProofTypes.CONCORDIUM,
205
- did: "did:key:z6MksamQq4oVRktkeSDxs6pbixYFUaUca8xgCvnTVLQA5PC5",
174
+ did: "did:pkh:ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
206
175
  proof:
207
- '{"0":{"0":"9b7263696072d4c5a0e060fec77bee5cb62ca9c8b674be864893f9d1dab75d28bf435efba9d4651ea1effdbd5b000f44d0d5be0fb10a11b3626a9a7be52e0d0d"}}',
176
+ '{"presentationContext":"d9380ba535f3fc379d507e7fabba726104ff4640b05a7c5696d0b0830d3a1983","proof":{"created":"2025-11-22T15:53:04.074Z","proofValue":[],"type":"ConcordiumWeakLinkingProofV1"},"type":"VerifiablePresentation","verifiableCredential":[{"credentialSubject":{"id":"did:ccd:testnet:cred:8f73851550a5d2c2ed4df215731cf9e3f33614d4be6c1c336f0f8858522c94afa34a759258a2b3281f9bacd0a8a3cd09","proof":{"created":"2025-11-22T15:53:04.074Z","proofValue":[{"proof":"a9f68ef2cb10cfe4b7734ab0464e6af952e9ebeb7d8701c00d6894ee64ee9f110d6dfbbdfd7de737ebaf0d3e85512ae98e7047e9db92d7d8bf5c4414f30443e13461bda7da17bd7a1e95d65add4e6fdc2d2da7338b9e2b71359a834df422d90682d490d1dc266806981c48cc39c1d7dfad0c86364cc1607d15dffe36a5f67b229f34567adcd9bbe249e9b3e521ecc4ccb260512d37da8cc7e61b224be723140b00412dfb57deb54ed8f0cd74e1cf31f64b50e649b7c262433f167c9e490cb06f4b12a3da45d25c45a76cfb94e21bf1b5950bb4edc83730ef882ecc376ff0e83957ef73535557ea865be9391f7948b6b34f5778025fcc681b469b9d1922e7605f1e768c0fd4280b6c1f338d7922a545536d5fb3c0e88b1da8b17020c9c26b544c00000007b15c3faa19a2f749f762be0f87820a299de52ccbea2e38dcc2c1275eca95e808bda09bffc4afdc0affca5e40308b2b00a1bf346359c0effc8c0cafbb17eb217cee0ac4239e053b5e058cd14fe8b687259255c5c9c110f11926f31760cf8ce4d2ae8fa37bdf19efaf35661fd2d31d45c535735e5af7871afbe8bea0783b01c1e66f62df3fce23309a7f743ebc7e27d9a5951821b5031c443310bb777ad4a04c3111ec017b18cdecab0a107f1a086bbfa513a2ed61e72665b8332e9f4809b04595a6bf76ed0ea0b38ca897aa5811a17df35bdab1a0a02ab6a8379acde4c9c01908de128821739028359e5173e7222fca0b8cad1206e0e6ca938a7bae3864445ca22ee60f7de2aceecb98d1f40a0c7a0519af09df4d7c536017c0236b7e579c73ea8aeb20762d31b3daa5a966f4f5824eb51ea037b3686cbd8a9d8daa0927fbe26ac1d9d41f0d96ce1896e6eaa69cfa88a09682079406a50718a47539999be699d4bfe2a414a13dc39d96a911e5113fab61a09b66346c74bc67c2bdbace3dcc74eca8e30bf2e64b2f577b0a4a9d484ff7696771e8e347bf870f51a9ef2d88b2bac8f53a0ae5ba2a537121b26977a57d585d8ef41596a8663ebada0626fcc4a919c115c8f766216abb76355970c5431152087d8e727aea7b245912ee35ca169bdf43ab89f1d2c857038faf337b7f0cfe16162fb43339a879159290116b95d64379d2a927b4b99e5aa50e784aa0b0ee930b17b31c778e09d3dd8879578179dc17e70f92252d0cc2226da0e70a0c1d6a375cca572818034242443f5f5e3d7bacff47d380e2698afc0e67fefc66fbb4e336744bde829f68ede5e4fac6315fd005471045fdee23a6f9c43ff69a2adddc597372f8acd2f02507ed99e195396412f181b207a3711ec68ce5b0811c46fe1be324fb64e8866d2850c16c33bb953a6ddf1bd8650f26db28333a7e2fd69f32e64778efd02c60730a96adad0fb12fa872d2c48268075c5335724f03d118b1e32593dc71e4141a5febcd078c1a85f21dd36d35af77","type":"AttributeInRange"}],"type":"ConcordiumZKProofV3"},"statement":[{"attributeTag":"dob","lower":"19300101","type":"AttributeInRange","upper":"99990101"}]},"issuer":"did:ccd:testnet:idp:0","type":["VerifiableCredential","ConcordiumVerifiableCredential"]}]}',
177
+ wallet_provider: "Concordium Browser",
208
178
  status: ProofStatus.PENDING,
209
- wallet_provider: "Concordium Wallet",
210
179
  };
211
-
212
- // Test against mainnet (makes network calls, calls isValidSignature)
213
- const result = await verifyConcordiumSignature(proof, {
214
- network: "mainnet",
215
- testMode: false,
216
- timeout: 10000
217
- });
218
-
219
- // Should fail because this account likely doesn't exist, but the network call should be made
180
+
181
+ const result = await verifyConcordiumSignature(proof);
220
182
  expect(result.status).toBe(ProofStatus.FAILED);
221
183
  }, 15000);
222
184
  });
@@ -5,6 +5,10 @@ import {
5
5
  SignatureProof,
6
6
  } from "@notabene/javascript-sdk";
7
7
  import { verifyCosmosSignature } from "../cosmos";
8
+ import { bech32 } from "bech32";
9
+ import { serializeSignDoc } from "@cosmjs/amino";
10
+ import { secp256k1 } from "@noble/curves/secp256k1";
11
+ import { keccak_256 } from "@noble/hashes/sha3";
8
12
 
9
13
  describe("verifyCosmosSignature", () => {
10
14
  it("returns verified proof when valid message and address", async () => {
@@ -48,4 +52,139 @@ describe("verifyCosmosSignature", () => {
48
52
 
49
53
  expect(result.status).toBe(ProofStatus.FAILED);
50
54
  });
55
+
56
+ // Signed with Keplr mobile on Celestia (PAY-1209). Every Cosmos SDK chain has its own
57
+ // bech32 prefix, so the address must be derived under the prefix the proof carries.
58
+ const celestiaProof: SignatureProof = {
59
+ type: ProofTypes.COSMOS,
60
+ did: "did:pkh:cosmos:celestia:celestia15f22nghu889nxwxgfak2th3z7fjq9atqvfw0vk",
61
+ status: ProofStatus.PENDING,
62
+ attestation:
63
+ "I certify that\n\ncosmos:celestia account celestia15f22nghu889nxwxgfak2th3z7fjq9atqvfw0vk\n\nbelonged to undefined\n\non Wed, 16 Sep 2026 15:34:35 GMT",
64
+ address:
65
+ "cosmos:celestia:celestia15f22nghu889nxwxgfak2th3z7fjq9atqvfw0vk",
66
+ proof:
67
+ "oI0CC9GVzR8rLrwXkXoMHnZWaGSL6GYq9G469p5OCKUB49WwAzVCqhTY8+mfkyFn//mIe6lEXfqjka8TWKkkag==",
68
+ wallet_provider: "Keplr (Wallet Connect)",
69
+ chainSpecificData: {
70
+ pub_key: {
71
+ type: "tendermint/PubKeySecp256k1",
72
+ value: "AqijUvgyDbKc0qm9M0M371FMiu384gJxXd67avWYEX1e",
73
+ },
74
+ },
75
+ };
76
+
77
+ it("verifies a proof from a cosmos chain with a non-cosmos bech32 prefix", async () => {
78
+ const result = await verifyCosmosSignature(celestiaProof);
79
+
80
+ expect(result.status).toBe(ProofStatus.VERIFIED);
81
+ });
82
+
83
+ it("fails when the public key does not derive to the signed address under its own prefix", async () => {
84
+ const result = await verifyCosmosSignature({
85
+ ...celestiaProof,
86
+ chainSpecificData: {
87
+ pub_key: {
88
+ type: "tendermint/PubKeySecp256k1",
89
+ // the cosmoshub-4 key from the first test
90
+ value: "Ak8k3jYgH4srYi1ygG0GWLrdbF7VwQgjiLqjifuJSsmU",
91
+ },
92
+ },
93
+ });
94
+
95
+ expect(result.status).toBe(ProofStatus.FAILED);
96
+ });
97
+
98
+ // Injective (and other ethermint-style chains) use eth-secp256k1 keys: the address is
99
+ // keccak256 of the uncompressed key, and ADR-036 signs a keccak256 digest (PAY-1210).
100
+ // Keplr's own verifier: @keplr-wallet/cosmos verifyADR36AminoSignDoc, algo "ethsecp256k1".
101
+ describe("eth-secp256k1 chains", () => {
102
+ const privateKey = Uint8Array.from({ length: 32 }, (_, i) => i + 1);
103
+ const pubKey = secp256k1.getPublicKey(privateKey, true);
104
+ const uncompressed = secp256k1.getPublicKey(privateKey, false).slice(1);
105
+ const injAddress = bech32.encode(
106
+ "inj",
107
+ bech32.toWords(keccak_256(uncompressed).slice(-20))
108
+ );
109
+ const attestation = `I certify that\n\ncosmos:injective-1 account ${injAddress}\n\nbelonged to did:key:test\n\non Wed, 16 Sep 2026 16:00:00 GMT`;
110
+ const signDoc = {
111
+ chain_id: "",
112
+ account_number: "0",
113
+ sequence: "0",
114
+ fee: { amount: [], gas: "0" },
115
+ msgs: [
116
+ {
117
+ type: "sign/MsgSignData",
118
+ value: {
119
+ signer: injAddress,
120
+ data: Buffer.from(attestation).toString("base64"),
121
+ },
122
+ },
123
+ ],
124
+ memo: "",
125
+ };
126
+ const sign = (digest: Uint8Array) =>
127
+ Buffer.from(
128
+ secp256k1.sign(digest, privateKey).toCompactRawBytes()
129
+ ).toString("base64");
130
+
131
+ const injectiveProof = (proof: string): SignatureProof => ({
132
+ type: ProofTypes.COSMOS,
133
+ did: `did:pkh:cosmos:injective-1:${injAddress}`,
134
+ status: ProofStatus.PENDING,
135
+ attestation,
136
+ address: `cosmos:injective-1:${injAddress}`,
137
+ proof,
138
+ wallet_provider: "Keplr (Wallet Connect)",
139
+ chainSpecificData: {
140
+ pub_key: {
141
+ type: "ethsecp256k1/PubKey",
142
+ value: Buffer.from(pubKey).toString("base64"),
143
+ },
144
+ },
145
+ });
146
+
147
+ it("verifies an inj1 address signed over a keccak256 digest", async () => {
148
+ const proof = injectiveProof(sign(keccak_256(serializeSignDoc(signDoc))));
149
+
150
+ const result = await verifyCosmosSignature(proof);
151
+
152
+ expect(result.status).toBe(ProofStatus.VERIFIED);
153
+ });
154
+
155
+ // Signed with Keplr mobile on Injective via WalletConnect. Keplr labels the key
156
+ // "tendermint/PubKeySecp256k1" even though it is eth-secp256k1, which is why the
157
+ // verifier picks the algorithm from the address rather than from pub_key.type.
158
+ it("verifies a real Keplr proof from injective-1", async () => {
159
+ const result = await verifyCosmosSignature({
160
+ type: ProofTypes.COSMOS,
161
+ did: "did:pkh:cosmos:injective-1:inj1jnk39fazhpf36kpmp6848cz7w2w9mnk8yvt7hj",
162
+ status: ProofStatus.PENDING,
163
+ attestation:
164
+ "I certify that\n\ncosmos:injective-1 account inj1jnk39fazhpf36kpmp6848cz7w2w9mnk8yvt7hj\n\nbelonged to undefined\n\non Wed, 16 Sep 2026 16:30:22 GMT",
165
+ address:
166
+ "cosmos:injective-1:inj1jnk39fazhpf36kpmp6848cz7w2w9mnk8yvt7hj",
167
+ proof:
168
+ "7aOueGwF+KrmBpx61+kjjUQq9qzqcIDA4xgG2lWtjtx8nqXIN++2u2kN6vfti1U9freaxxWgZF8zCPsr/TInoA==",
169
+ wallet_provider: "Keplr (Wallet Connect)",
170
+ chainSpecificData: {
171
+ pub_key: {
172
+ type: "tendermint/PubKeySecp256k1",
173
+ value: "AsEu8nenas+bG7oo+oNXET6nTV+dSSOutCD7SttV34HT",
174
+ },
175
+ },
176
+ });
177
+
178
+ expect(result.status).toBe(ProofStatus.VERIFIED);
179
+ });
180
+
181
+ it("fails an inj1 address signed over a sha256 digest", async () => {
182
+ const { sha256 } = await import("@noble/hashes/sha2");
183
+ const proof = injectiveProof(sign(sha256(serializeSignDoc(signDoc))));
184
+
185
+ const result = await verifyCosmosSignature(proof);
186
+
187
+ expect(result.status).toBe(ProofStatus.FAILED);
188
+ });
189
+ });
51
190
  });
@@ -328,13 +328,13 @@ describe("verifyProof", () => {
328
328
 
329
329
  describe("Concordium", () => {
330
330
  const proof: SignatureProof = {
331
- type: ProofTypes.CONCORDIUM,
332
- address: "ccd:9dd9ca4d19e9393877d2c44b70f89acb:3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF",
333
- attestation: "I certify that\n\nccd:9dd9ca4d19e9393877d2c44b70f89acb account 3thVBVWVwz1oHb4ob2VgehUGF7zyAJHkm5UDW8NdQKFKCvFnoF\n\nbelonged to did:key:z6MksamQq4oVRktkeSDxs6pbixYFUaUca8xgCvnTVLQA5PC5\n\non Thu, 12 Jun 2025 09:20:01 GMT",
334
- proof: '{"0":{"0":"9b7263696072d4c5a0e060fec77bee5cb62ca9c8b674be864893f9d1dab75d28bf435efba9d4651ea1effdbd5b000f44d0d5be0fb10a11b3626a9a7be52e0d0d"}}',
335
- did: "did:key:z6MksamQq4oVRktkeSDxs6pbixYFUaUca8xgCvnTVLQA5PC5",
336
- status: ProofStatus.PENDING,
337
- wallet_provider: "Concordium Wallet",
331
+ "address": "ccd:9dd9ca4d19e9393877d2c44b70f89acb:3Soqc3mEU5WC4R9Qho9fxm4CJ1157q6qsJbPvtGV8iT8FbQdv2",
332
+ "attestation": "b74a8e64f1568f1fb22a57b033bc8ef2b8f6ba23ff8e831e7abfbb671927fda1",
333
+ "type": ProofTypes.CONCORDIUM,
334
+ "did": "did:pkh:ccd:9dd9ca4d19e9393877d2c44b70f89acb:3Soqc3mEU5WC4R9Qho9fxm4CJ1157q6qsJbPvtGV8iT8FbQdv2",
335
+ "proof": "{\"presentationContext\":\"b74a8e64f1568f1fb22a57b033bc8ef2b8f6ba23ff8e831e7abfbb671927fda1\",\"proof\":{\"created\":\"2025-12-10T10:39:14.395Z\",\"proofValue\":[],\"type\":\"ConcordiumWeakLinkingProofV1\"},\"type\":\"VerifiablePresentation\",\"verifiableCredential\":[{\"credentialSubject\":{\"id\":\"did:ccd:mainnet:cred:91a1f28bc42222096856a54fb157f7c80b9827457d4ece682b9592bca964948f01dce51a7deb392ea9bd0c1e1630d17b\",\"proof\":{\"created\":\"2025-12-10T10:39:14.395Z\",\"proofValue\":[{\"proof\":\"988f08d03bc8adaac4d51986dfaafe70874ab3bb22e8c09c32da5bfcd0ff0407203770533220e74ba4386acb36f7b7288e38c461279f7edf6f41b8b285d629280a5ca297e7fc42155222c5b1ad3cc74f770d5c87addbba6935ade425460b1616a587d9c45a4676f7fc751b31110cd37b25998c61d7d85c84e4db155491665e556778a9784e557799f06531bafe6b4b8ca2ce386d66f7759079eaff74b1e519550c9d137a13851c0987ee434feb6dae0ca659d67661b27e92d7cca9567a1a6ecd2175c574f5a6c2f4691597cbf3680f65abab72633d050746211c56961277064d694a31c2a93ef3b64c4957ff8261978a53d8b65d40ff23ddc7ee65d0ea0817702be58fbaec3954322e00667c6c94736eba8d3aa3f2686b89f257ca34c90ae1200000000785c57df969a45b25b1d39bdb388d33a756147e98f285891e83ce58eab3bb1f466c25a0946fc62513b16f3f02397b15418ebc131b5e1a8c0f05d6983cd3c44cc40ab8364c1aa209c2e8c0e8e84694587053542fd5cbb918f025723a5a0c200f08875728874571f50cb8b54d1c8629a10c76f0a982ad667efcfa280943f7c8753d3fa859a8d5d9837e6bdd5026d54546a3ae5918055208b5d2f77e0206d7861b4c472c634ec4cece107aeb14c42fe3d801aba38aa38e15785152e7c061561a5594a6cabb34f469b3121c15437df5d6ba0638ba3a192f2106d07e2f7bfd73310f669d3e8bdeb1b43244455d7bd7fa5917a1af2b23dc3433dac68ee4571bea2b0c22ce2ed665e22cee5676b9c3de0169926e72c847f7e3f2caa671e55ab5c4530205845b08ee12bba954f4a41e5638b05043a93ed212f402273c2b477f95f7b82ddbe4621f1758f80fcec726df755a76d0f585eda201dff2b91147cca5eae5d5319b7e1438c0f4af42b9fe4f7e845d0c643328ddd5dead96bfd345ae972312650a9ab6e6d7fa3d3f5d1fe68e5ff513095e3caa5bb21bec64dae007e62b4494986ac40b9e14b61255a84ea51780b8439adaeeae0b83a8bcee382491dd8e7b2f1921e8eeffe39a45bffd470b5a8f74d82ccdb8ccda651c387844f61704cc04f51d65fb9069900cb1febfc0b2ba02ffc857c45c12a7b306440e6627995d67353e9f6327b6f6cfa6ad0b859ea904f087a5b29a888043ba21ccb3e36da0a2da797310c2f2ce56c275d6fc48b60aade4b4e6bb6ff62d5f5be1a529c8d71cab2b0904fa306cb779a897872f5f047df7c7bee150ca6be6f3ad840a862ecc0793bb27f0594ff8741a4ab426b53d72acbdbde6c20a7c4399ca181d81a4b0ac437c23220f52ff8e9095ae35a53f8cd58913c4999a8153b656fabb162feafe8fc8708eaeb2b5ce0d347e5733cd685783271eaf564e05efce61996686ee9f50663204841ff30416061721a5cab8e1c80708809b58d2bc9c402da453e486ce08e0ec6c72c1f0e9dc15\",\"type\":\"AttributeInRange\"}],\"type\":\"ConcordiumZKProofV3\"},\"statement\":[{\"attributeTag\":\"dob\",\"lower\":\"19300101\",\"type\":\"AttributeInRange\",\"upper\":\"99990101\"}]},\"issuer\":\"did:ccd:mainnet:idp:1\",\"type\":[\"VerifiableCredential\",\"ConcordiumVerifiableCredential\"]}]}",
336
+ "wallet_provider": "Concordium Browser",
337
+ "status": ProofStatus.PENDING
338
338
  };
339
339
 
340
340
  it("should verify proof", async () => {
@@ -28,21 +28,23 @@ describe("verifyPersonalSignXRPL", async () => {
28
28
  };
29
29
  }
30
30
 
31
- function existingXRPLProof(): SignatureProof {
31
+ const existingXRPLPublicKey = 'ED33CE53E97678D4C9016377B944716D80833098E666BB2BE160C5BE84C310E1D7';
32
+
33
+ function existingXRPLProof(): SignatureProof {
32
34
  return {
33
35
  type: ProofTypes.XRP_ED25519,
34
- proof: 'B080C34BCD2F1392420A5CB46C14772AC54841181CB3387A0793025C480A6A52292A869FB2B86B89EA33E096285F8CC45F5D35D4E29750BA8E127076CADF7906',
35
- address: `xrpl:1:rGWNp4P9DJpDNhPc7t9GeHoQb8SCKWBfYV`,
36
- did: `did:pkh:xrpl:1:rGWNp4P9DJpDNhPc7t9GeHoQb8SCKWBfYV`,
36
+ proof: '30DC5E837D23A408414E270C9E79E7BEE4450D4FD89E1A42B94BA5C36728011A0D47BF6036464BDDE842F90F72BFD0F521504EF8F181F41421B1748EAA8DBC04',
37
+ address: `xrpl:1:rUe11XPvngHVzwS61wDwj98unworBbRDNc`,
38
+ did: `did:pkh:xrpl:1:rUe11XPvngHVzwS61wDwj98unworBbRDNc`,
37
39
  status: ProofStatus.PENDING,
38
40
  wallet_provider: "XRPL",
39
- attestation: "I certify that\n\nxrpl:1 account rGWNp4P9DJpDNhPc7t9GeHoQb8SCKWBfYV\n\nbelonged to did:key:z6Mkq3vnQfZFLVe2UXBUTgonfEhzYr9QF7xvkSSpdt9LXeY6\n\non Thu, 06 Mar 2025 10:34:43 GMT"
41
+ attestation: "I certify that\n\nxrpl:1 account rUe11XPvngHVzwS61wDwj98unworBbRDNc\n\nbelonged to did:key:z6Mkq3vnQfZFLVe2UXBUTgonfEhzYr9QF7xvkSSpdt9LXeY6\n\non Thu, 06 Mar 2025 10:34:43 GMT"
40
42
  }
41
43
  }
42
44
 
43
45
  it("returns verified proof when valid existing XRPL proof", async () => {
44
46
  const proof = existingXRPLProof();
45
- const result = await verifyPersonalSignXRPL(proof, undefined, true);
47
+ const result = await verifyPersonalSignXRPL(proof, existingXRPLPublicKey);
46
48
  expect(result.status).toBe(ProofStatus.VERIFIED);
47
49
  });
48
50
 
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/bitcoin.ts"],"names":["ProofStatus","ProofTypes","Verifier","base64","secp256k1","createBase58check","Hash","encodeLength","bech32"],"mappings":"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","file":"bitcoin-3CW4MNAW.cjs","sourcesContent":["import {\n ProofStatus,\n ProofTypes,\n SignatureProof,\n} from \"@notabene/javascript-sdk\";\n\nimport { encode as encodeLength } from \"varuint-bitcoin\";\nimport { base64, bech32, createBase58check } from \"@scure/base\";\nimport { Hash } from \"ox\";\nimport { secp256k1 } from \"@noble/curves/secp256k1\";\nimport { SignatureType } from \"@noble/curves/abstract/weierstrass\";\nimport { Verifier } from \"bip322-js\";\n\nenum SEGWIT_TYPES {\n P2WPKH = \"p2wpkh\",\n P2SH_P2WPKH = \"p2sh(p2wpkh)\",\n}\n\ninterface ChainConfig {\n messagePrefix: string;\n pubKeyHashVersion: number | Uint8Array;\n scriptHashVersion: number | Uint8Array;\n bech32Prefix?: string;\n isTestnet?: boolean;\n}\n\nconst CHAIN_CONFIGS: Record<string, ChainConfig> = {\n bitcoin: {\n messagePrefix: \"\\u0018Bitcoin Signed Message:\\n\",\n pubKeyHashVersion: 0x00, // 1...\n scriptHashVersion: 0x05, // 3...\n bech32Prefix: \"bc\",\n isTestnet: false,\n },\n bitcoincash: {\n messagePrefix: \"\\u0018Bitcoin Signed Message:\\n\",\n pubKeyHashVersion: 0x00, // 1...\n scriptHashVersion: 0x05, // 3...\n bech32Prefix: \"bc\",\n isTestnet: false,\n },\n litecoin: {\n messagePrefix: \"\\u0019Litecoin Signed Message:\\n\",\n pubKeyHashVersion: 0x30, // L... or M...\n scriptHashVersion: 0x32, // 3... or M...\n bech32Prefix: \"ltc\",\n isTestnet: false,\n },\n dogecoin: {\n messagePrefix: \"\\u0019Dogecoin Signed Message:\\n\",\n pubKeyHashVersion: 0x1e, // D...\n scriptHashVersion: 0x16, // A...\n isTestnet: false,\n },\n dash: {\n messagePrefix: \"\\u0019DarkCoin Signed Message:\\n\",\n pubKeyHashVersion: 0x4c, // X...\n scriptHashVersion: 0x10, // 7...\n isTestnet: false,\n },\n zcash: {\n messagePrefix: \"\\u0018Zcash Signed Message:\\n\",\n pubKeyHashVersion: Uint8Array.from([0x1c, 0xb8]), // <-- FIXED\n scriptHashVersion: Uint8Array.from([0x1c, 0xbd]),\n isTestnet: false,\n },\n\n testnet: {\n messagePrefix: \"\\u0018Bitcoin Signed Message:\\n\",\n pubKeyHashVersion: 0x6f, // m or n\n scriptHashVersion: 0xc4, // 2\n bech32Prefix: \"tb\",\n isTestnet: true,\n },\n};\n\nenum DerivationMode {\n LEGACY = \"Legacy\",\n NATIVE = \"Native SegWit\",\n SEGWIT = \"SegWit\",\n P2SH_SEGWIT = \"p2sh\",\n BCH = \"Bitcoin Cash\",\n ETHEREUM = \"Ethereum\",\n DOGECOIN = \"Dogecoin\",\n UNKNOWN = \"Unknown\",\n}\n\nexport async function verifyBTCSignature(\n proof: SignatureProof\n): Promise<SignatureProof> {\n const [ns, , address] = proof.address.split(/:/);\n if (ns !== \"bip122\") return { ...proof, status: ProofStatus.FAILED };\n\n // Map chainId to our chain configuration\n const chainConfig = getChainConfig(address);\n if (!chainConfig) return { ...proof, status: ProofStatus.FAILED };\n\n const isZcash = address.startsWith(\"t1\") || address.startsWith(\"t3\");\n if (isZcash) {\n return verifyBIP137(address, proof, chainConfig);\n }\n\n // Use BIP322 for testnet addresses\n if (chainConfig.isTestnet) {\n return verifyBIP322(address, proof);\n }\n\n // Check if this is a Taproot address (bc1p or tb1p)\n const isTaproot = address.startsWith(\"bc1p\") || address.startsWith(\"tb1p\");\n\n // For Taproot addresses with BIP-137 proof type, use BIP-322 verification\n // since BIP-137 doesn't officially support Taproot\n if (isTaproot && proof.type === ProofTypes.BIP137) {\n return verifyBIP322(address, proof);\n }\n\n try {\n switch (proof.type) {\n case ProofTypes.BIP137:\n return verifyBIP137(address, proof, chainConfig);\n case ProofTypes.BIP322:\n return verifyBIP322(address, proof);\n default:\n return {\n ...proof,\n status: ProofStatus.FAILED,\n };\n }\n } catch {\n return {\n ...proof,\n status: ProofStatus.FAILED,\n };\n }\n}\n\nfunction getChainConfig(address: string): ChainConfig {\n if (\n address.startsWith(\"1\") ||\n address.startsWith(\"3\") ||\n address.startsWith(\"bc1\")\n ) {\n return CHAIN_CONFIGS[\"bitcoin\"];\n }\n if (address.startsWith(\"t1\") || address.startsWith(\"t3\")) {\n return CHAIN_CONFIGS[\"zcash\"];\n }\n if (\n address.startsWith(\"L\") ||\n address.startsWith(\"M\") ||\n address.startsWith(\"ltc1\")\n ) {\n return CHAIN_CONFIGS[\"litecoin\"];\n }\n if (address.startsWith(\"D\") || address.startsWith(\"A\")) {\n return CHAIN_CONFIGS[\"dogecoin\"];\n }\n if (address.startsWith(\"X\") || address.startsWith(\"7\")) {\n return CHAIN_CONFIGS[\"dash\"];\n }\n if (address.startsWith(\"q\")) {\n return CHAIN_CONFIGS[\"bitcoincash\"];\n }\n if (address.startsWith(\"tb1\")) {\n return CHAIN_CONFIGS[\"testnet\"];\n }\n\n return CHAIN_CONFIGS[\"bitcoin\"];\n}\n\nfunction verifyBIP322(address: string, proof: SignatureProof) {\n const { attestation, proof: signatureProof } = proof;\n const verified = Verifier.verifySignature(\n address,\n attestation,\n signatureProof\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n\nfunction verifyBIP137(\n address: string,\n proof: SignatureProof,\n chainConfig: ChainConfig\n) {\n const derivationMode = getDerivationMode(address);\n\n // For legacy addresses (starting with \"1\"), never use SegWit encoding\n // For P2SH addresses (starting with \"3\"), use SegWit encoding if they have bech32 support\n // For native SegWit addresses (bc1, tb1, ltc1), always use SegWit encoding\n const useSegwitEncoding = Boolean(\n chainConfig.bech32Prefix &&\n (derivationMode === DerivationMode.NATIVE ||\n (derivationMode === DerivationMode.SEGWIT && !address.startsWith(\"1\")))\n );\n\n const verified = verify(\n proof.attestation,\n address,\n proof.proof,\n useSegwitEncoding,\n chainConfig\n );\n\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n\nfunction getDerivationMode(address: string) {\n if (address.match(\"^(bc1|tb1|ltc1).*\")) {\n return DerivationMode.NATIVE;\n } else if (address.match(\"^[32M].*\")) {\n return DerivationMode.SEGWIT;\n } else if (address.match(\"^[1nmL].*\")) {\n return DerivationMode.LEGACY;\n } else if (address.match(\"^(D).*\")) {\n return DerivationMode.DOGECOIN;\n } else if (address.match(\"^(q).*\")) {\n return DerivationMode.BCH;\n } else if (address.match(\"^(t1|t3).*\")) {\n return DerivationMode.LEGACY; // Zcash addresses\n } else if (address.match(\"^[X7].*\")) {\n return DerivationMode.LEGACY; // Dash addresses\n } else {\n throw new Error(\n \"INVALID ADDRESS: \"\n .concat(address)\n .concat(\" is not a valid or a supported address\")\n );\n }\n}\n\ntype DecodedSignature = {\n compressed: boolean;\n segwitType?: SEGWIT_TYPES;\n signature: SignatureType;\n};\n\nfunction decodeSignature(proof: string): DecodedSignature {\n const sigbytes = base64.decode(proof);\n if (sigbytes.length !== 65) throw new Error(\"Invalid signature length\");\n const flagByte = sigbytes[0] - 27;\n if (flagByte > 15 || flagByte < 0) {\n throw new Error(\"Invalid signature parameter\");\n }\n const compressed = !!(flagByte & 12); // Are there cases that aren't compressed?\n const recovery = flagByte & 3;\n const signature = secp256k1.Signature.fromCompact(sigbytes.slice(1));\n\n return {\n compressed,\n segwitType: !(flagByte & 8)\n ? undefined\n : !(flagByte & 4)\n ? SEGWIT_TYPES.P2SH_P2WPKH\n : SEGWIT_TYPES.P2WPKH,\n signature: signature.addRecoveryBit(recovery),\n };\n}\n\nfunction verify(\n attestation: string,\n address: string,\n proof: string,\n checkSegwitAlways: boolean,\n chainConfig: ChainConfig\n) {\n const { compressed, segwitType, signature } = decodeSignature(proof);\n if (checkSegwitAlways && !compressed) {\n throw new Error(\n \"checkSegwitAlways can only be used with a compressed pubkey signature flagbyte\"\n );\n }\n const hash = magicHash(attestation, chainConfig.messagePrefix);\n const publicKey = signature.recoverPublicKey(hash);\n const publicKeyBytes = publicKey.toRawBytes(compressed);\n const publicKeyHash = hash160(publicKeyBytes);\n let actual: string = \"\";\n\n // Special handling for Bitcoin Cash addresses\n if (address.startsWith(\"q\")) {\n // For BCH, we'll compare the public key hash directly since we're getting a CashAddr\n // Convert the CashAddr to legacy format for comparison\n actual = encodeBase58AddressFormat(\n chainConfig.pubKeyHashVersion,\n publicKeyHash\n );\n // Legacy P2PKH addresses in BCH start with '1' just like BTC\n // Source: https://reference.cash/protocol/blockchain/encoding/cashaddr#legacy-address-format\n return actual.startsWith(\"1\");\n }\n\n if (segwitType) {\n if (segwitType === SEGWIT_TYPES.P2SH_P2WPKH) {\n actual = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n publicKeyHash\n );\n } else {\n // parsed.segwitType === SEGWIT_TYPES.P2WPKH\n if (chainConfig.bech32Prefix) {\n actual = encodeBech32Address(publicKeyHash, chainConfig.bech32Prefix);\n } else {\n // Fallback to legacy if bech32 not supported\n actual = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n publicKeyHash\n );\n // base58 can be p2pkh or p2sh-p2wpkh\n }\n }\n } else {\n // For addresses starting with \"3\" (P2SH), try both P2SH-P2WPKH and legacy P2SH encodings if segwitType is undefined\n if (address.startsWith(\"3\") && !segwitType) {\n // P2SH-P2WPKH: script hash of the redeem script (OP_0 <pubkeyhash>)\n const redeemScript = new Uint8Array(22);\n redeemScript[0] = 0x00; // OP_0\n redeemScript[1] = 0x14; // push 20 bytes\n redeemScript.set(publicKeyHash, 2);\n const redeemScriptHash = hash160(redeemScript);\n const p2shP2wpkh = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n redeemScriptHash\n );\n // Legacy P2SH: script hash of the public key\n const legacyP2sh = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n publicKeyHash\n );\n if (address === p2shP2wpkh || address === legacyP2sh) {\n return true;\n }\n actual = legacyP2sh; // fallback for error reporting\n } else if (address.startsWith(\"bc1q\") || address.startsWith(\"tb1q\") || address.startsWith(\"ltc1q\")) {\n // For native SegWit P2WPKH addresses (bc1q/tb1q/ltc1q), always encode as bech32\n // This handles Ledger wallets that sign without segwit flags\n if (chainConfig.bech32Prefix) {\n actual = encodeBech32Address(publicKeyHash, chainConfig.bech32Prefix);\n } else {\n actual = encodeBase58AddressFormat(\n chainConfig.pubKeyHashVersion,\n publicKeyHash\n );\n }\n } else if (checkSegwitAlways && chainConfig.bech32Prefix) {\n try {\n actual = encodeBech32Address(publicKeyHash, chainConfig.bech32Prefix);\n // if address is bech32 it is not p2sh\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (e) {\n actual = encodeBase58AddressFormat(\n chainConfig.scriptHashVersion,\n publicKeyHash\n );\n // base58 can be p2pkh or p2sh-p2wpkh\n }\n } else {\n actual = encodeBase58AddressFormat(\n chainConfig.pubKeyHashVersion,\n publicKeyHash\n );\n }\n }\n\n return actual === address;\n}\n\nconst base58check = createBase58check(Hash.sha256);\n\nfunction encodeBase58AddressFormat(\n version: number | Uint8Array,\n publicKeyHash: Uint8Array\n) {\n const prefixBytes =\n typeof version === \"number\" ? Uint8Array.of(version) : version; // Accept raw Uint8Array for Zcash\n\n const payload = new Uint8Array(prefixBytes.length + publicKeyHash.length);\n payload.set(prefixBytes);\n payload.set(publicKeyHash, prefixBytes.length);\n return base58check.encode(payload);\n}\n\nfunction magicHash(attestation: string, messagePrefix: string) {\n const prefix = new TextEncoder().encode(messagePrefix);\n const message = new TextEncoder().encode(attestation);\n const length = encodeLength(message.length).buffer;\n const buffer = new Uint8Array(\n prefix.length + length.byteLength + message.length\n );\n buffer.set(prefix);\n buffer.set(new Uint8Array(length), prefix.length);\n buffer.set(message, prefix.length + length.byteLength);\n return hash256(buffer);\n}\n\nfunction encodeBech32Address(\n publicKeyHash: Uint8Array,\n prefix: string = \"bc\"\n): string {\n const bwords = bech32.toWords(publicKeyHash);\n bwords.unshift(0);\n return bech32.encode(prefix, bwords);\n}\n\nfunction hash256(buffer: Uint8Array): Uint8Array {\n return Hash.sha256(Hash.sha256(buffer));\n}\n\nfunction hash160(buffer: Uint8Array): Uint8Array {\n return Hash.ripemd160(Hash.sha256(buffer));\n}\n"]}