@molpha/sdk 0.2.0-dev-20260913100330 → 0.2.0-dev-20261001084453
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/README.md +93 -52
- package/dist/index.d.ts +321 -72
- package/dist/index.js +2111 -4933
- package/dist/index.js.map +1 -1
- package/idl/molpha.json +1780 -4801
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -45,8 +45,8 @@ Every signed attestation commits to the same message across chains:
|
|
|
45
45
|
|
|
46
46
|
```text
|
|
47
47
|
message = keccak256(
|
|
48
|
-
keccak256("MOLPHA_MESSAGE_V1") || sourceId || u32be(registryVersion) ||
|
|
49
|
-
|
|
48
|
+
keccak256("MOLPHA_MESSAGE_V1") || value || sourceId || u32be(registryVersion) ||
|
|
49
|
+
u8(signaturesRequired) || u64be(canonicalTimestamp) || signersBitmap
|
|
50
50
|
)
|
|
51
51
|
```
|
|
52
52
|
|
|
@@ -290,6 +290,13 @@ The returned `DataUpdateResult` includes `sourceId`, the signed value, canonical
|
|
|
290
290
|
const { signature, feed } = await sdk.solana.submitAttestation(result);
|
|
291
291
|
```
|
|
292
292
|
|
|
293
|
+
If the signed 32-byte value is the keccak digest of a longer preimage, provide the
|
|
294
|
+
preimage explicitly (up to 256 bytes). The SDK verifies the digest before sending:
|
|
295
|
+
|
|
296
|
+
```ts
|
|
297
|
+
const { signature, feed } = await sdk.solana.submitAttestation(result, { rawValue });
|
|
298
|
+
```
|
|
299
|
+
|
|
293
300
|
Then read the feed this wallet wrote for that source and quorum:
|
|
294
301
|
|
|
295
302
|
```ts
|
|
@@ -455,90 +462,120 @@ Supported network ids (selection helpers only): `evm-sepolia`, `arbitrum-sepolia
|
|
|
455
462
|
|
|
456
463
|
### Build verifier arguments
|
|
457
464
|
|
|
465
|
+
The verifier's entrypoint is
|
|
466
|
+
`verify(Attestation attestation, uint64 maxAge) returns (bool success, uint8 code)`.
|
|
467
|
+
|
|
458
468
|
```ts
|
|
459
469
|
import { buildEvmVerifierArgs } from "@molpha/sdk";
|
|
460
470
|
|
|
461
471
|
const result = await sdk.gateway.requestSignedData({ apiConfig, signaturesRequired });
|
|
462
472
|
|
|
463
|
-
const {
|
|
473
|
+
const { attestation, maxAge } = buildEvmVerifierArgs(result, { maxAge: 300 });
|
|
464
474
|
```
|
|
465
475
|
|
|
466
|
-
|
|
476
|
+
`maxAge` is required. It is the freshness window in seconds: the verifier reports an older
|
|
477
|
+
attestation as `STALE`, and one dated after `block.timestamp` as `MALFORMED`. `0` disables the
|
|
478
|
+
check entirely — pass it only when your contract enforces freshness or ordering itself, because
|
|
479
|
+
a stateless verifier otherwise accepts a correctly signed attestation forever.
|
|
467
480
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
// uint32 registryVersion,
|
|
472
|
-
// uint32 signaturesRequired,
|
|
473
|
-
// bytes32 valuePacked,
|
|
474
|
-
// uint64 timestamp]
|
|
481
|
+
The generated object matches the Solidity `IVerifier.Attestation` struct, using viem's
|
|
482
|
+
primitive types so it passes straight into `readContract` or an ethers `Contract`. Member
|
|
483
|
+
order is ABI order (and the signed message's order), so it differs from `DataUpdateResult`:
|
|
475
484
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
485
|
+
```ts
|
|
486
|
+
attestation:
|
|
487
|
+
{
|
|
488
|
+
payload: {
|
|
489
|
+
value: `0x${string}`, // bytes32 (result.valuePacked)
|
|
490
|
+
sourceId: `0x${string}`, // bytes32
|
|
491
|
+
registryVersion: number, // uint32
|
|
492
|
+
signaturesRequired: number, // uint8
|
|
493
|
+
canonicalTimestamp: bigint, // uint64 (result.timestamp)
|
|
494
|
+
},
|
|
495
|
+
signature: {
|
|
496
|
+
signature: `0x${string}`, // bytes32 (result.s)
|
|
497
|
+
commitment: `0x${string}`, // address (result.commitmentAddr)
|
|
498
|
+
signersBitmap: bigint, // uint256
|
|
499
|
+
},
|
|
500
|
+
}
|
|
501
|
+
maxAge: bigint // uint64
|
|
480
502
|
```
|
|
481
503
|
|
|
482
|
-
|
|
504
|
+
The builder range-checks every integer against its Solidity type. Out-of-range calldata never
|
|
505
|
+
reaches `verify`: the ABI decoder reverts on it instead of returning a result code.
|
|
483
506
|
|
|
484
|
-
###
|
|
507
|
+
### viem
|
|
485
508
|
|
|
486
509
|
```ts
|
|
487
|
-
import {
|
|
510
|
+
import { createPublicClient, http } from "viem";
|
|
488
511
|
import {
|
|
489
512
|
buildEvmVerifierArgs,
|
|
513
|
+
MOLPHA_VERIFIER_ABI,
|
|
490
514
|
MOLPHA_VERIFIER_ADDRESS,
|
|
515
|
+
parseEvmVerifyResult,
|
|
491
516
|
} from "@molpha/sdk";
|
|
492
517
|
|
|
493
|
-
const
|
|
494
|
-
|
|
495
|
-
abi,
|
|
496
|
-
signer,
|
|
497
|
-
);
|
|
518
|
+
const client = createPublicClient({ chain, transport: http() });
|
|
519
|
+
const { attestation, maxAge } = buildEvmVerifierArgs(result, { maxAge: 300 });
|
|
498
520
|
|
|
499
|
-
const
|
|
521
|
+
const returned = await client.readContract({
|
|
522
|
+
address: MOLPHA_VERIFIER_ADDRESS,
|
|
523
|
+
abi: MOLPHA_VERIFIER_ABI,
|
|
524
|
+
functionName: "verify",
|
|
525
|
+
args: [attestation, maxAge],
|
|
526
|
+
});
|
|
500
527
|
|
|
501
|
-
|
|
528
|
+
const { success, code, reason } = parseEvmVerifyResult(returned);
|
|
529
|
+
// { success: true, code: 0, reason: "OK" }
|
|
530
|
+
// { success: false, code: 10, reason: "STALE" }
|
|
502
531
|
```
|
|
503
532
|
|
|
504
|
-
###
|
|
533
|
+
### ethers
|
|
505
534
|
|
|
506
535
|
```ts
|
|
507
|
-
import {
|
|
536
|
+
import { Contract } from "ethers";
|
|
508
537
|
import {
|
|
509
538
|
buildEvmVerifierArgs,
|
|
510
539
|
MOLPHA_VERIFIER_ABI,
|
|
511
540
|
MOLPHA_VERIFIER_ADDRESS,
|
|
541
|
+
parseEvmVerifyResult,
|
|
512
542
|
} from "@molpha/sdk";
|
|
513
543
|
|
|
514
|
-
const
|
|
515
|
-
|
|
516
|
-
transport: http(),
|
|
517
|
-
});
|
|
544
|
+
const verifier = new Contract(MOLPHA_VERIFIER_ADDRESS, MOLPHA_VERIFIER_ABI, provider);
|
|
545
|
+
const { attestation, maxAge } = buildEvmVerifierArgs(result, { maxAge: 300 });
|
|
518
546
|
|
|
519
|
-
const {
|
|
547
|
+
const { success, code, reason } = parseEvmVerifyResult(await verifier.verify(attestation, maxAge));
|
|
548
|
+
```
|
|
520
549
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
{
|
|
534
|
-
signature: signature[0],
|
|
535
|
-
commitment: signature[1],
|
|
536
|
-
signersBitmap: signature[2],
|
|
537
|
-
},
|
|
538
|
-
],
|
|
539
|
-
});
|
|
550
|
+
### Raw `eth_call`
|
|
551
|
+
|
|
552
|
+
`encodeEvmVerifyCalldata` produces the full calldata (selector `0x67e2907b` plus nine static
|
|
553
|
+
words), and `parseEvmVerifyResult` also accepts the raw 64-byte return data:
|
|
554
|
+
|
|
555
|
+
```ts
|
|
556
|
+
import { buildEvmVerifierArgs, encodeEvmVerifyCalldata, parseEvmVerifyResult } from "@molpha/sdk";
|
|
557
|
+
|
|
558
|
+
const args = buildEvmVerifierArgs(result, { maxAge: 300 });
|
|
559
|
+
const returnData = await provider.call({ to: verifierAddress, data: encodeEvmVerifyCalldata(args) });
|
|
560
|
+
|
|
561
|
+
const { success, code, reason } = parseEvmVerifyResult(returnData);
|
|
540
562
|
```
|
|
541
563
|
|
|
564
|
+
`verify` never reverts; a rejection is a result code from the shared `VERIFY_CODES` table (see
|
|
565
|
+
[the Starknet section](#call-verify-and-read-the-result) for the full list). The EVM verifier
|
|
566
|
+
returns `MALFORMED` for a zero `signaturesRequired`, a zero or out-of-range signature scalar, a
|
|
567
|
+
zero commitment, or fewer set bitmap bits than `signaturesRequired`. `parseEvmVerifyResult`
|
|
568
|
+
throws when `success` and `code` disagree, which means the call did not reach a Molpha verifier
|
|
569
|
+
of this interface.
|
|
570
|
+
|
|
571
|
+
### Registry reads
|
|
572
|
+
|
|
573
|
+
`MOLPHA_VERIFIER_ABI` also covers every read-only registry view — `getRegistryVersion`,
|
|
574
|
+
`getTotalNodes`, `redundancyBuffer`, `getRegistryRoot` / `getRegistryPointer` (current or per
|
|
575
|
+
version), `activatesAt`, `retiredAt`, `isLatestVersion`, `nodeStatus`, `isNode` — and the
|
|
576
|
+
`InvalidRegistryVersion` error the per-version views revert with. Owner-only mutators are not
|
|
577
|
+
included.
|
|
578
|
+
|
|
542
579
|
Lower-level helpers are also exported for manual integrations:
|
|
543
580
|
|
|
544
581
|
```ts
|
|
@@ -746,7 +783,7 @@ Current scope:
|
|
|
746
783
|
- Solana attestation submission and feed/registry reads;
|
|
747
784
|
- private API encryption helpers (pre-production);
|
|
748
785
|
- caller-funded x402 payments for paywalled API sources (Base USDC, pre-production);
|
|
749
|
-
- EVM and Starknet verifier argument building,
|
|
786
|
+
- EVM and Starknet verifier argument building, `verify` calldata encoding and result decoding;
|
|
750
787
|
- deployed testnet verifier address helpers.
|
|
751
788
|
|
|
752
789
|
Known limitations:
|
|
@@ -779,6 +816,10 @@ Solana paths such as selection bitmap and `submit_attestation` remaining-account
|
|
|
779
816
|
| `buildStarknetVerifierArgs(result)` → `{ dataUpdate, signature }` | `buildStarknetVerifierArgs(result, { maxAge })` → `{ attestation, maxAge }` for `verify(attestation, max_age)` |
|
|
780
817
|
| `StarknetDataUpdate` (`signatures_required: u32`) | `StarknetAttestationPayload` (`signatures_required: u8`, `value` first), nested in `StarknetAttestation` |
|
|
781
818
|
| Starknet `verify` returns `bool` | returns `(bool, u8)` — decode with `parseStarknetVerifyResult` |
|
|
819
|
+
| `buildEvmVerifierArgs(result)` → `{ dataUpdate, signature }` tuples | `buildEvmVerifierArgs(result, { maxAge })` → `{ attestation, maxAge }` for `verify(attestation, maxAge)` |
|
|
820
|
+
| `EvmDataUpdateTuple` / `EvmSchnorrSignatureTuple` (positional) | `EvmAttestationPayload` / `EvmSchnorrSignature` objects (`value` first, `signaturesRequired: uint8`, `canonicalTimestamp: bigint`), nested in `EvmAttestation` |
|
|
821
|
+
| EVM `verify(DataUpdate, SchnorrSignature)` returns `bool` | `verify(Attestation, uint64)` returns `(bool, uint8)` — decode with `parseEvmVerifyResult` |
|
|
822
|
+
| `attestationMessageHash`: `sourceId ‖ u32 rv ‖ u32 sigReq ‖ bitmap ‖ value ‖ u64 ts` | `value ‖ sourceId ‖ u32 rv ‖ u8 sigReq ‖ u64 ts ‖ bitmap` (what nodes sign and every verifier checks) |
|
|
782
823
|
| `resolveRegistryIndexForVersion`, `VIRTUAL_INDEX`, `nodePda(index)` | removed — signer accounts are `registry.nodes[bit]`; `nodePda(owner)` |
|
|
783
824
|
|
|
784
825
|
## Develop
|